In routerlist_assert_ok(), check r2 before taking &(r2->cache_info)
[tor.git] / src / or / rendservice.c
bloba7c1e32f1552332e690e8038b3b2b2aeca87a91b
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 * Copyright (c) 2007-2013, 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 #define RENDSERVICE_PRIVATE
12 #include "or.h"
13 #include "circpathbias.h"
14 #include "circuitbuild.h"
15 #include "circuitlist.h"
16 #include "circuituse.h"
17 #include "config.h"
18 #include "directory.h"
19 #include "networkstatus.h"
20 #include "nodelist.h"
21 #include "rendclient.h"
22 #include "rendcommon.h"
23 #include "rendservice.h"
24 #include "router.h"
25 #include "relay.h"
26 #include "rephist.h"
27 #include "replaycache.h"
28 #include "routerlist.h"
29 #include "routerparse.h"
30 #include "routerset.h"
32 static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro,
33 const char *pk_digest);
34 static rend_intro_point_t *find_intro_point(origin_circuit_t *circ);
36 static extend_info_t *find_rp_for_intro(
37 const rend_intro_cell_t *intro,
38 uint8_t *need_free_out, char **err_msg_out);
40 static int intro_point_accepted_intro_count(rend_intro_point_t *intro);
41 static int intro_point_should_expire_now(rend_intro_point_t *intro,
42 time_t now);
43 struct rend_service_t;
44 static int rend_service_load_keys(struct rend_service_t *s);
45 static int rend_service_load_auth_keys(struct rend_service_t *s,
46 const char *hfname);
48 static ssize_t rend_service_parse_intro_for_v0_or_v1(
49 rend_intro_cell_t *intro,
50 const uint8_t *buf,
51 size_t plaintext_len,
52 char **err_msg_out);
53 static ssize_t rend_service_parse_intro_for_v2(
54 rend_intro_cell_t *intro,
55 const uint8_t *buf,
56 size_t plaintext_len,
57 char **err_msg_out);
58 static ssize_t rend_service_parse_intro_for_v3(
59 rend_intro_cell_t *intro,
60 const uint8_t *buf,
61 size_t plaintext_len,
62 char **err_msg_out);
64 /** Represents the mapping from a virtual port of a rendezvous service to
65 * a real port on some IP.
67 typedef struct rend_service_port_config_t {
68 uint16_t virtual_port;
69 uint16_t real_port;
70 tor_addr_t real_addr;
71 } rend_service_port_config_t;
73 /** Try to maintain this many intro points per service by default. */
74 #define NUM_INTRO_POINTS_DEFAULT 3
75 /** Maintain no more than this many intro points per hidden service. */
76 #define NUM_INTRO_POINTS_MAX 10
78 /** If we can't build our intro circuits, don't retry for this long. */
79 #define INTRO_CIRC_RETRY_PERIOD (60*5)
80 /** Don't try to build more than this many circuits before giving up
81 * for a while.*/
82 #define MAX_INTRO_CIRCS_PER_PERIOD 10
83 /** How many times will a hidden service operator attempt to connect to
84 * a requested rendezvous point before giving up? */
85 #define MAX_REND_FAILURES 8
86 /** How many seconds should we spend trying to connect to a requested
87 * rendezvous point before giving up? */
88 #define MAX_REND_TIMEOUT 30
90 /** How many seconds should we wait for new HS descriptors to reach
91 * our clients before we close an expiring intro point? */
92 #define INTRO_POINT_EXPIRATION_GRACE_PERIOD (5*60)
94 /** Represents a single hidden service running at this OP. */
95 typedef struct rend_service_t {
96 /* Fields specified in config file */
97 char *directory; /**< where in the filesystem it stores it */
98 smartlist_t *ports; /**< List of rend_service_port_config_t */
99 rend_auth_type_t auth_type; /**< Client authorization type or 0 if no client
100 * authorization is performed. */
101 smartlist_t *clients; /**< List of rend_authorized_client_t's of
102 * clients that may access our service. Can be NULL
103 * if no client authorization is performed. */
104 /* Other fields */
105 crypto_pk_t *private_key; /**< Permanent hidden-service key. */
106 char service_id[REND_SERVICE_ID_LEN_BASE32+1]; /**< Onion address without
107 * '.onion' */
108 char pk_digest[DIGEST_LEN]; /**< Hash of permanent hidden-service key. */
109 smartlist_t *intro_nodes; /**< List of rend_intro_point_t's we have,
110 * or are trying to establish. */
111 time_t intro_period_started; /**< Start of the current period to build
112 * introduction points. */
113 int n_intro_circuits_launched; /**< Count of intro circuits we have
114 * established in this period. */
115 unsigned int n_intro_points_wanted; /**< Number of intro points this
116 * service wants to have open. */
117 rend_service_descriptor_t *desc; /**< Current hidden service descriptor. */
118 time_t desc_is_dirty; /**< Time at which changes to the hidden service
119 * descriptor content occurred, or 0 if it's
120 * up-to-date. */
121 time_t next_upload_time; /**< Scheduled next hidden service descriptor
122 * upload time. */
123 /** Replay cache for Diffie-Hellman values of INTRODUCE2 cells, to
124 * detect repeats. Clients may send INTRODUCE1 cells for the same
125 * rendezvous point through two or more different introduction points;
126 * when they do, this keeps us from launching multiple simultaneous attempts
127 * to connect to the same rend point. */
128 replaycache_t *accepted_intro_dh_parts;
129 } rend_service_t;
131 /** A list of rend_service_t's for services run on this OP.
133 static smartlist_t *rend_service_list = NULL;
135 /** Return the number of rendezvous services we have configured. */
137 num_rend_services(void)
139 if (!rend_service_list)
140 return 0;
141 return smartlist_len(rend_service_list);
144 /** Return a string identifying <b>service</b>, suitable for use in a
145 * log message. The result does not need to be freed, but may be
146 * overwritten by the next call to this function. */
147 static const char *
148 rend_service_describe_for_log(rend_service_t *service)
150 /* XXX024 Use this function throughout rendservice.c. */
151 /* XXX024 Return a more useful description? */
152 return safe_str_client(service->service_id);
155 /** Helper: free storage held by a single service authorized client entry. */
156 static void
157 rend_authorized_client_free(rend_authorized_client_t *client)
159 if (!client)
160 return;
161 if (client->client_key)
162 crypto_pk_free(client->client_key);
163 tor_strclear(client->client_name);
164 tor_free(client->client_name);
165 memwipe(client->descriptor_cookie, 0, sizeof(client->descriptor_cookie));
166 tor_free(client);
169 /** Helper for strmap_free. */
170 static void
171 rend_authorized_client_strmap_item_free(void *authorized_client)
173 rend_authorized_client_free(authorized_client);
176 /** Release the storage held by <b>service</b>.
178 static void
179 rend_service_free(rend_service_t *service)
181 if (!service)
182 return;
184 tor_free(service->directory);
185 SMARTLIST_FOREACH(service->ports, void*, p, tor_free(p));
186 smartlist_free(service->ports);
187 if (service->private_key)
188 crypto_pk_free(service->private_key);
189 if (service->intro_nodes) {
190 SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro,
191 rend_intro_point_free(intro););
192 smartlist_free(service->intro_nodes);
195 rend_service_descriptor_free(service->desc);
196 if (service->clients) {
197 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, c,
198 rend_authorized_client_free(c););
199 smartlist_free(service->clients);
201 if (service->accepted_intro_dh_parts) {
202 replaycache_free(service->accepted_intro_dh_parts);
204 tor_free(service);
207 /** Release all the storage held in rend_service_list.
209 void
210 rend_service_free_all(void)
212 if (!rend_service_list)
213 return;
215 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
216 rend_service_free(ptr));
217 smartlist_free(rend_service_list);
218 rend_service_list = NULL;
221 /** Validate <b>service</b> and add it to rend_service_list if possible.
223 static void
224 rend_add_service(rend_service_t *service)
226 int i;
227 rend_service_port_config_t *p;
229 service->intro_nodes = smartlist_new();
231 if (service->auth_type != REND_NO_AUTH &&
232 smartlist_len(service->clients) == 0) {
233 log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no "
234 "clients; ignoring.",
235 escaped(service->directory));
236 rend_service_free(service);
237 return;
240 if (!smartlist_len(service->ports)) {
241 log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured; "
242 "ignoring.",
243 escaped(service->directory));
244 rend_service_free(service);
245 } else {
246 int dupe = 0;
247 /* XXX This duplicate check has two problems:
249 * a) It's O(n^2), but the same comment from the bottom of
250 * rend_config_services() should apply.
252 * b) We only compare directory paths as strings, so we can't
253 * detect two distinct paths that specify the same directory
254 * (which can arise from symlinks, case-insensitivity, bind
255 * mounts, etc.).
257 * It also can't detect that two separate Tor instances are trying
258 * to use the same HiddenServiceDir; for that, we would need a
259 * lock file. But this is enough to detect a simple mistake that
260 * at least one person has actually made.
262 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
263 dupe = dupe ||
264 !strcmp(ptr->directory, service->directory));
265 if (dupe) {
266 log_warn(LD_REND, "Another hidden service is already configured for "
267 "directory %s, ignoring.", service->directory);
268 rend_service_free(service);
269 return;
271 smartlist_add(rend_service_list, service);
272 log_debug(LD_REND,"Configuring service with directory \"%s\"",
273 service->directory);
274 for (i = 0; i < smartlist_len(service->ports); ++i) {
275 p = smartlist_get(service->ports, i);
276 log_debug(LD_REND,"Service maps port %d to %s",
277 p->virtual_port, fmt_addrport(&p->real_addr, p->real_port));
282 /** Parses a real-port to virtual-port mapping and returns a new
283 * rend_service_port_config_t.
285 * The format is: VirtualPort (IP|RealPort|IP:RealPort)?
287 * IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
289 static rend_service_port_config_t *
290 parse_port_config(const char *string)
292 smartlist_t *sl;
293 int virtport;
294 int realport;
295 uint16_t p;
296 tor_addr_t addr;
297 const char *addrport;
298 rend_service_port_config_t *result = NULL;
300 sl = smartlist_new();
301 smartlist_split_string(sl, string, " ",
302 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
303 if (smartlist_len(sl) < 1 || smartlist_len(sl) > 2) {
304 log_warn(LD_CONFIG, "Bad syntax in hidden service port configuration.");
305 goto err;
308 virtport = (int)tor_parse_long(smartlist_get(sl,0), 10, 1, 65535, NULL,NULL);
309 if (!virtport) {
310 log_warn(LD_CONFIG, "Missing or invalid port %s in hidden service port "
311 "configuration", escaped(smartlist_get(sl,0)));
312 goto err;
315 if (smartlist_len(sl) == 1) {
316 /* No addr:port part; use default. */
317 realport = virtport;
318 tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */
319 } else {
320 addrport = smartlist_get(sl,1);
321 if (strchr(addrport, ':') || strchr(addrport, '.')) {
322 if (tor_addr_port_lookup(addrport, &addr, &p)<0) {
323 log_warn(LD_CONFIG,"Unparseable address in hidden service port "
324 "configuration.");
325 goto err;
327 realport = p?p:virtport;
328 } else {
329 /* No addr:port, no addr -- must be port. */
330 realport = (int)tor_parse_long(addrport, 10, 1, 65535, NULL, NULL);
331 if (!realport) {
332 log_warn(LD_CONFIG,"Unparseable or out-of-range port %s in hidden "
333 "service port configuration.", escaped(addrport));
334 goto err;
336 tor_addr_from_ipv4h(&addr, 0x7F000001u); /* Default to 127.0.0.1 */
340 result = tor_malloc(sizeof(rend_service_port_config_t));
341 result->virtual_port = virtport;
342 result->real_port = realport;
343 tor_addr_copy(&result->real_addr, &addr);
344 err:
345 SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
346 smartlist_free(sl);
347 return result;
350 /** Set up rend_service_list, based on the values of HiddenServiceDir and
351 * HiddenServicePort in <b>options</b>. Return 0 on success and -1 on
352 * failure. (If <b>validate_only</b> is set, parse, warn and return as
353 * normal, but don't actually change the configured services.)
356 rend_config_services(const or_options_t *options, int validate_only)
358 config_line_t *line;
359 rend_service_t *service = NULL;
360 rend_service_port_config_t *portcfg;
361 smartlist_t *old_service_list = NULL;
363 if (!validate_only) {
364 old_service_list = rend_service_list;
365 rend_service_list = smartlist_new();
368 for (line = options->RendConfigLines; line; line = line->next) {
369 if (!strcasecmp(line->key, "HiddenServiceDir")) {
370 if (service) { /* register the one we just finished parsing */
371 if (validate_only)
372 rend_service_free(service);
373 else
374 rend_add_service(service);
376 service = tor_malloc_zero(sizeof(rend_service_t));
377 service->directory = tor_strdup(line->value);
378 service->ports = smartlist_new();
379 service->intro_period_started = time(NULL);
380 service->n_intro_points_wanted = NUM_INTRO_POINTS_DEFAULT;
381 continue;
383 if (!service) {
384 log_warn(LD_CONFIG, "%s with no preceding HiddenServiceDir directive",
385 line->key);
386 rend_service_free(service);
387 return -1;
389 if (!strcasecmp(line->key, "HiddenServicePort")) {
390 portcfg = parse_port_config(line->value);
391 if (!portcfg) {
392 rend_service_free(service);
393 return -1;
395 smartlist_add(service->ports, portcfg);
396 } else if (!strcasecmp(line->key, "HiddenServiceAuthorizeClient")) {
397 /* Parse auth type and comma-separated list of client names and add a
398 * rend_authorized_client_t for each client to the service's list
399 * of authorized clients. */
400 smartlist_t *type_names_split, *clients;
401 const char *authname;
402 int num_clients;
403 if (service->auth_type != REND_NO_AUTH) {
404 log_warn(LD_CONFIG, "Got multiple HiddenServiceAuthorizeClient "
405 "lines for a single service.");
406 rend_service_free(service);
407 return -1;
409 type_names_split = smartlist_new();
410 smartlist_split_string(type_names_split, line->value, " ", 0, 2);
411 if (smartlist_len(type_names_split) < 1) {
412 log_warn(LD_BUG, "HiddenServiceAuthorizeClient has no value. This "
413 "should have been prevented when parsing the "
414 "configuration.");
415 smartlist_free(type_names_split);
416 rend_service_free(service);
417 return -1;
419 authname = smartlist_get(type_names_split, 0);
420 if (!strcasecmp(authname, "basic")) {
421 service->auth_type = REND_BASIC_AUTH;
422 } else if (!strcasecmp(authname, "stealth")) {
423 service->auth_type = REND_STEALTH_AUTH;
424 } else {
425 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
426 "unrecognized auth-type '%s'. Only 'basic' or 'stealth' "
427 "are recognized.",
428 (char *) smartlist_get(type_names_split, 0));
429 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
430 smartlist_free(type_names_split);
431 rend_service_free(service);
432 return -1;
434 service->clients = smartlist_new();
435 if (smartlist_len(type_names_split) < 2) {
436 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
437 "auth-type '%s', but no client names.",
438 service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth");
439 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
440 smartlist_free(type_names_split);
441 continue;
443 clients = smartlist_new();
444 smartlist_split_string(clients, smartlist_get(type_names_split, 1),
445 ",", SPLIT_SKIP_SPACE, 0);
446 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
447 smartlist_free(type_names_split);
448 /* Remove duplicate client names. */
449 num_clients = smartlist_len(clients);
450 smartlist_sort_strings(clients);
451 smartlist_uniq_strings(clients);
452 if (smartlist_len(clients) < num_clients) {
453 log_info(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
454 "duplicate client name(s); removing.",
455 num_clients - smartlist_len(clients));
456 num_clients = smartlist_len(clients);
458 SMARTLIST_FOREACH_BEGIN(clients, const char *, client_name)
460 rend_authorized_client_t *client;
461 size_t len = strlen(client_name);
462 if (len < 1 || len > REND_CLIENTNAME_MAX_LEN) {
463 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
464 "illegal client name: '%s'. Length must be "
465 "between 1 and %d characters.",
466 client_name, REND_CLIENTNAME_MAX_LEN);
467 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
468 smartlist_free(clients);
469 rend_service_free(service);
470 return -1;
472 if (strspn(client_name, REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
473 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
474 "illegal client name: '%s'. Valid "
475 "characters are [A-Za-z0-9+_-].",
476 client_name);
477 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
478 smartlist_free(clients);
479 rend_service_free(service);
480 return -1;
482 client = tor_malloc_zero(sizeof(rend_authorized_client_t));
483 client->client_name = tor_strdup(client_name);
484 smartlist_add(service->clients, client);
485 log_debug(LD_REND, "Adding client name '%s'", client_name);
487 SMARTLIST_FOREACH_END(client_name);
488 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
489 smartlist_free(clients);
490 /* Ensure maximum number of clients. */
491 if ((service->auth_type == REND_BASIC_AUTH &&
492 smartlist_len(service->clients) > 512) ||
493 (service->auth_type == REND_STEALTH_AUTH &&
494 smartlist_len(service->clients) > 16)) {
495 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
496 "client authorization entries, but only a "
497 "maximum of %d entries is allowed for "
498 "authorization type '%s'.",
499 smartlist_len(service->clients),
500 service->auth_type == REND_BASIC_AUTH ? 512 : 16,
501 service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth");
502 rend_service_free(service);
503 return -1;
505 } else {
506 tor_assert(!strcasecmp(line->key, "HiddenServiceVersion"));
507 if (strcmp(line->value, "2")) {
508 log_warn(LD_CONFIG,
509 "The only supported HiddenServiceVersion is 2.");
510 rend_service_free(service);
511 return -1;
515 if (service) {
516 if (validate_only)
517 rend_service_free(service);
518 else
519 rend_add_service(service);
522 /* If this is a reload and there were hidden services configured before,
523 * keep the introduction points that are still needed and close the
524 * other ones. */
525 if (old_service_list && !validate_only) {
526 smartlist_t *surviving_services = smartlist_new();
527 circuit_t *circ;
529 /* Copy introduction points to new services. */
530 /* XXXX This is O(n^2), but it's only called on reconfigure, so it's
531 * probably ok? */
532 SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, new) {
533 SMARTLIST_FOREACH_BEGIN(old_service_list, rend_service_t *, old) {
534 if (!strcmp(old->directory, new->directory)) {
535 smartlist_add_all(new->intro_nodes, old->intro_nodes);
536 smartlist_clear(old->intro_nodes);
537 smartlist_add(surviving_services, old);
538 break;
540 } SMARTLIST_FOREACH_END(old);
541 } SMARTLIST_FOREACH_END(new);
543 /* Close introduction circuits of services we don't serve anymore. */
544 /* XXXX it would be nicer if we had a nicer abstraction to use here,
545 * so we could just iterate over the list of services to close, but
546 * once again, this isn't critical-path code. */
547 TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) {
548 if (!circ->marked_for_close &&
549 circ->state == CIRCUIT_STATE_OPEN &&
550 (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
551 circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
552 origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
553 int keep_it = 0;
554 tor_assert(oc->rend_data);
555 SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
556 if (tor_memeq(ptr->pk_digest, oc->rend_data->rend_pk_digest,
557 DIGEST_LEN)) {
558 keep_it = 1;
559 break;
562 if (keep_it)
563 continue;
564 log_info(LD_REND, "Closing intro point %s for service %s.",
565 safe_str_client(extend_info_describe(
566 oc->build_state->chosen_exit)),
567 oc->rend_data->onion_address);
568 circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
569 /* XXXX Is there another reason we should use here? */
572 smartlist_free(surviving_services);
573 SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr,
574 rend_service_free(ptr));
575 smartlist_free(old_service_list);
578 return 0;
581 /** Replace the old value of <b>service</b>-\>desc with one that reflects
582 * the other fields in service.
584 static void
585 rend_service_update_descriptor(rend_service_t *service)
587 rend_service_descriptor_t *d;
588 origin_circuit_t *circ;
589 int i;
591 rend_service_descriptor_free(service->desc);
592 service->desc = NULL;
594 d = service->desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
595 d->pk = crypto_pk_dup_key(service->private_key);
596 d->timestamp = time(NULL);
597 d->timestamp -= d->timestamp % 3600; /* Round down to nearest hour */
598 d->intro_nodes = smartlist_new();
599 /* Support intro protocols 2 and 3. */
600 d->protocols = (1 << 2) + (1 << 3);
602 for (i = 0; i < smartlist_len(service->intro_nodes); ++i) {
603 rend_intro_point_t *intro_svc = smartlist_get(service->intro_nodes, i);
604 rend_intro_point_t *intro_desc;
606 /* This intro point won't be listed in the descriptor... */
607 intro_svc->listed_in_last_desc = 0;
609 if (intro_svc->time_expiring != -1) {
610 /* This intro point is expiring. Don't list it. */
611 continue;
614 circ = find_intro_circuit(intro_svc, service->pk_digest);
615 if (!circ || circ->base_.purpose != CIRCUIT_PURPOSE_S_INTRO) {
616 /* This intro point's circuit isn't finished yet. Don't list it. */
617 continue;
620 /* ...unless this intro point is listed in the descriptor. */
621 intro_svc->listed_in_last_desc = 1;
623 /* We have an entirely established intro circuit. Publish it in
624 * our descriptor. */
625 intro_desc = tor_malloc_zero(sizeof(rend_intro_point_t));
626 intro_desc->extend_info = extend_info_dup(intro_svc->extend_info);
627 if (intro_svc->intro_key)
628 intro_desc->intro_key = crypto_pk_dup_key(intro_svc->intro_key);
629 smartlist_add(d->intro_nodes, intro_desc);
631 if (intro_svc->time_published == -1) {
632 /* We are publishing this intro point in a descriptor for the
633 * first time -- note the current time in the service's copy of
634 * the intro point. */
635 intro_svc->time_published = time(NULL);
640 /** Load and/or generate private keys for all hidden services, possibly
641 * including keys for client authorization. Return 0 on success, -1 on
642 * failure. */
644 rend_service_load_all_keys(void)
646 SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, s) {
647 if (s->private_key)
648 continue;
649 log_info(LD_REND, "Loading hidden-service keys from \"%s\"",
650 s->directory);
652 if (rend_service_load_keys(s) < 0)
653 return -1;
654 } SMARTLIST_FOREACH_END(s);
656 return 0;
659 /** Add to <b>lst</b> every filename used by <b>s</b>. */
660 static void
661 rend_service_add_filenames_to_list(smartlist_t *lst, const rend_service_t *s)
663 tor_assert(lst);
664 tor_assert(s);
665 smartlist_add_asprintf(lst, "%s"PATH_SEPARATOR"private_key",
666 s->directory);
667 smartlist_add_asprintf(lst, "%s"PATH_SEPARATOR"hostname",
668 s->directory);
669 smartlist_add_asprintf(lst, "%s"PATH_SEPARATOR"client_keys",
670 s->directory);
673 /** Add to <b>open_lst</b> every filename used by a configured hidden service,
674 * and to <b>stat_lst</b> every directory used by a configured hidden
675 * service */
676 void
677 rend_services_add_filenames_to_lists(smartlist_t *open_lst,
678 smartlist_t *stat_lst)
680 if (!rend_service_list)
681 return;
682 SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, s) {
683 rend_service_add_filenames_to_list(open_lst, s);
684 smartlist_add(stat_lst, tor_strdup(s->directory));
685 } SMARTLIST_FOREACH_END(s);
688 /** Load and/or generate private keys for the hidden service <b>s</b>,
689 * possibly including keys for client authorization. Return 0 on success, -1
690 * on failure. */
691 static int
692 rend_service_load_keys(rend_service_t *s)
694 char fname[512];
695 char buf[128];
697 /* Check/create directory */
698 if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0)
699 return -1;
701 /* Load key */
702 if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
703 strlcat(fname,PATH_SEPARATOR"private_key",sizeof(fname))
704 >= sizeof(fname)) {
705 log_warn(LD_CONFIG, "Directory name too long to store key file: \"%s\".",
706 s->directory);
707 return -1;
709 s->private_key = init_key_from_file(fname, 1, LOG_ERR);
710 if (!s->private_key)
711 return -1;
713 /* Create service file */
714 if (rend_get_service_id(s->private_key, s->service_id)<0) {
715 log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
716 return -1;
718 if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) {
719 log_warn(LD_BUG, "Couldn't compute hash of public key.");
720 return -1;
722 if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
723 strlcat(fname,PATH_SEPARATOR"hostname",sizeof(fname))
724 >= sizeof(fname)) {
725 log_warn(LD_CONFIG, "Directory name too long to store hostname file:"
726 " \"%s\".", s->directory);
727 return -1;
730 tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id);
731 if (write_str_to_file(fname,buf,0)<0) {
732 log_warn(LD_CONFIG, "Could not write onion address to hostname file.");
733 memwipe(buf, 0, sizeof(buf));
734 return -1;
736 memwipe(buf, 0, sizeof(buf));
738 /* If client authorization is configured, load or generate keys. */
739 if (s->auth_type != REND_NO_AUTH) {
740 if (rend_service_load_auth_keys(s, fname) < 0)
741 return -1;
744 return 0;
747 /** Load and/or generate client authorization keys for the hidden service
748 * <b>s</b>, which stores its hostname in <b>hfname</b>. Return 0 on success,
749 * -1 on failure. */
750 static int
751 rend_service_load_auth_keys(rend_service_t *s, const char *hfname)
753 int r = 0;
754 char cfname[512];
755 char *client_keys_str = NULL;
756 strmap_t *parsed_clients = strmap_new();
757 FILE *cfile, *hfile;
758 open_file_t *open_cfile = NULL, *open_hfile = NULL;
759 char extended_desc_cookie[REND_DESC_COOKIE_LEN+1];
760 char desc_cook_out[3*REND_DESC_COOKIE_LEN_BASE64+1];
761 char service_id[16+1];
762 char buf[1500];
764 /* Load client keys and descriptor cookies, if available. */
765 if (tor_snprintf(cfname, sizeof(cfname), "%s"PATH_SEPARATOR"client_keys",
766 s->directory)<0) {
767 log_warn(LD_CONFIG, "Directory name too long to store client keys "
768 "file: \"%s\".", s->directory);
769 goto err;
771 client_keys_str = read_file_to_str(cfname, RFTS_IGNORE_MISSING, NULL);
772 if (client_keys_str) {
773 if (rend_parse_client_keys(parsed_clients, client_keys_str) < 0) {
774 log_warn(LD_CONFIG, "Previously stored client_keys file could not "
775 "be parsed.");
776 goto err;
777 } else {
778 log_info(LD_CONFIG, "Parsed %d previously stored client entries.",
779 strmap_size(parsed_clients));
783 /* Prepare client_keys and hostname files. */
784 if (!(cfile = start_writing_to_stdio_file(cfname,
785 OPEN_FLAGS_REPLACE | O_TEXT,
786 0600, &open_cfile))) {
787 log_warn(LD_CONFIG, "Could not open client_keys file %s",
788 escaped(cfname));
789 goto err;
792 if (!(hfile = start_writing_to_stdio_file(hfname,
793 OPEN_FLAGS_REPLACE | O_TEXT,
794 0600, &open_hfile))) {
795 log_warn(LD_CONFIG, "Could not open hostname file %s", escaped(hfname));
796 goto err;
799 /* Either use loaded keys for configured clients or generate new
800 * ones if a client is new. */
801 SMARTLIST_FOREACH_BEGIN(s->clients, rend_authorized_client_t *, client) {
802 rend_authorized_client_t *parsed =
803 strmap_get(parsed_clients, client->client_name);
804 int written;
805 size_t len;
806 /* Copy descriptor cookie from parsed entry or create new one. */
807 if (parsed) {
808 memcpy(client->descriptor_cookie, parsed->descriptor_cookie,
809 REND_DESC_COOKIE_LEN);
810 } else {
811 crypto_rand(client->descriptor_cookie, REND_DESC_COOKIE_LEN);
813 if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
814 client->descriptor_cookie,
815 REND_DESC_COOKIE_LEN) < 0) {
816 log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
817 goto err;
819 /* Copy client key from parsed entry or create new one if required. */
820 if (parsed && parsed->client_key) {
821 client->client_key = crypto_pk_dup_key(parsed->client_key);
822 } else if (s->auth_type == REND_STEALTH_AUTH) {
823 /* Create private key for client. */
824 crypto_pk_t *prkey = NULL;
825 if (!(prkey = crypto_pk_new())) {
826 log_warn(LD_BUG,"Error constructing client key");
827 goto err;
829 if (crypto_pk_generate_key(prkey)) {
830 log_warn(LD_BUG,"Error generating client key");
831 crypto_pk_free(prkey);
832 goto err;
834 if (crypto_pk_check_key(prkey) <= 0) {
835 log_warn(LD_BUG,"Generated client key seems invalid");
836 crypto_pk_free(prkey);
837 goto err;
839 client->client_key = prkey;
841 /* Add entry to client_keys file. */
842 desc_cook_out[strlen(desc_cook_out)-1] = '\0'; /* Remove newline. */
843 written = tor_snprintf(buf, sizeof(buf),
844 "client-name %s\ndescriptor-cookie %s\n",
845 client->client_name, desc_cook_out);
846 if (written < 0) {
847 log_warn(LD_BUG, "Could not write client entry.");
848 goto err;
850 if (client->client_key) {
851 char *client_key_out = NULL;
852 if (crypto_pk_write_private_key_to_string(client->client_key,
853 &client_key_out, &len) != 0) {
854 log_warn(LD_BUG, "Internal error: "
855 "crypto_pk_write_private_key_to_string() failed.");
856 goto err;
858 if (rend_get_service_id(client->client_key, service_id)<0) {
859 log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
861 * len is string length, not buffer length, but last byte is NUL
862 * anyway.
864 memwipe(client_key_out, 0, len);
865 tor_free(client_key_out);
866 goto err;
868 written = tor_snprintf(buf + written, sizeof(buf) - written,
869 "client-key\n%s", client_key_out);
870 memwipe(client_key_out, 0, len);
871 tor_free(client_key_out);
872 if (written < 0) {
873 log_warn(LD_BUG, "Could not write client entry.");
874 goto err;
878 if (fputs(buf, cfile) < 0) {
879 log_warn(LD_FS, "Could not append client entry to file: %s",
880 strerror(errno));
881 goto err;
884 /* Add line to hostname file. */
885 if (s->auth_type == REND_BASIC_AUTH) {
886 /* Remove == signs (newline has been removed above). */
887 desc_cook_out[strlen(desc_cook_out)-2] = '\0';
888 tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
889 s->service_id, desc_cook_out, client->client_name);
890 } else {
891 memcpy(extended_desc_cookie, client->descriptor_cookie,
892 REND_DESC_COOKIE_LEN);
893 extended_desc_cookie[REND_DESC_COOKIE_LEN] =
894 ((int)s->auth_type - 1) << 4;
895 if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
896 extended_desc_cookie,
897 REND_DESC_COOKIE_LEN+1) < 0) {
898 log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
899 goto err;
901 desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove A= and
902 newline. */
903 tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
904 service_id, desc_cook_out, client->client_name);
907 if (fputs(buf, hfile)<0) {
908 log_warn(LD_FS, "Could not append host entry to file: %s",
909 strerror(errno));
910 goto err;
912 } SMARTLIST_FOREACH_END(client);
914 finish_writing_to_file(open_cfile);
915 finish_writing_to_file(open_hfile);
917 goto done;
918 err:
919 r = -1;
920 if (open_cfile)
921 abort_writing_to_file(open_cfile);
922 if (open_hfile)
923 abort_writing_to_file(open_hfile);
924 done:
925 if (client_keys_str) {
926 tor_strclear(client_keys_str);
927 tor_free(client_keys_str);
929 strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
931 memwipe(cfname, 0, sizeof(cfname));
933 /* Clear stack buffers that held key-derived material. */
934 memwipe(buf, 0, sizeof(buf));
935 memwipe(desc_cook_out, 0, sizeof(desc_cook_out));
936 memwipe(service_id, 0, sizeof(service_id));
937 memwipe(extended_desc_cookie, 0, sizeof(extended_desc_cookie));
939 return r;
942 /** Return the service whose public key has a digest of <b>digest</b>, or
943 * NULL if no such service exists.
945 static rend_service_t *
946 rend_service_get_by_pk_digest(const char* digest)
948 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
949 if (tor_memeq(s->pk_digest,digest,DIGEST_LEN))
950 return s);
951 return NULL;
954 /** Return 1 if any virtual port in <b>service</b> wants a circuit
955 * to have good uptime. Else return 0.
957 static int
958 rend_service_requires_uptime(rend_service_t *service)
960 int i;
961 rend_service_port_config_t *p;
963 for (i=0; i < smartlist_len(service->ports); ++i) {
964 p = smartlist_get(service->ports, i);
965 if (smartlist_contains_int_as_string(get_options()->LongLivedPorts,
966 p->virtual_port))
967 return 1;
969 return 0;
972 /** Check client authorization of a given <b>descriptor_cookie</b> for
973 * <b>service</b>. Return 1 for success and 0 for failure. */
974 static int
975 rend_check_authorization(rend_service_t *service,
976 const char *descriptor_cookie)
978 rend_authorized_client_t *auth_client = NULL;
979 tor_assert(service);
980 tor_assert(descriptor_cookie);
981 if (!service->clients) {
982 log_warn(LD_BUG, "Can't check authorization for a service that has no "
983 "authorized clients configured.");
984 return 0;
987 /* Look up client authorization by descriptor cookie. */
988 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, client, {
989 if (tor_memeq(client->descriptor_cookie, descriptor_cookie,
990 REND_DESC_COOKIE_LEN)) {
991 auth_client = client;
992 break;
995 if (!auth_client) {
996 char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64];
997 base64_encode(descriptor_cookie_base64, sizeof(descriptor_cookie_base64),
998 descriptor_cookie, REND_DESC_COOKIE_LEN);
999 log_info(LD_REND, "No authorization found for descriptor cookie '%s'! "
1000 "Dropping cell!",
1001 descriptor_cookie_base64);
1002 return 0;
1005 /* Allow the request. */
1006 log_debug(LD_REND, "Client %s authorized for service %s.",
1007 auth_client->client_name, service->service_id);
1008 return 1;
1011 /** Called when <b>intro</b> will soon be removed from
1012 * <b>service</b>'s list of intro points. */
1013 static void
1014 rend_service_note_removing_intro_point(rend_service_t *service,
1015 rend_intro_point_t *intro)
1017 time_t now = time(NULL);
1019 /* Don't process an intro point twice here. */
1020 if (intro->rend_service_note_removing_intro_point_called) {
1021 return;
1022 } else {
1023 intro->rend_service_note_removing_intro_point_called = 1;
1026 /* Update service->n_intro_points_wanted based on how long intro
1027 * lasted and how many introductions it handled. */
1028 if (intro->time_published == -1) {
1029 /* This intro point was never used. Don't change
1030 * n_intro_points_wanted. */
1031 } else {
1032 /* We want to increase the number of introduction points service
1033 * operates if intro was heavily used, or decrease the number of
1034 * intro points if intro was lightly used.
1036 * We consider an intro point's target 'usage' to be
1037 * INTRO_POINT_LIFETIME_INTRODUCTIONS introductions in
1038 * INTRO_POINT_LIFETIME_MIN_SECONDS seconds. To calculate intro's
1039 * fraction of target usage, we divide the fraction of
1040 * _LIFETIME_INTRODUCTIONS introductions that it has handled by
1041 * the fraction of _LIFETIME_MIN_SECONDS for which it existed.
1043 * Then we multiply that fraction of desired usage by a fudge
1044 * factor of 1.5, to decide how many new introduction points
1045 * should ideally replace intro (which is now closed or soon to be
1046 * closed). In theory, assuming that introduction load is
1047 * distributed equally across all intro points and ignoring the
1048 * fact that different intro points are established and closed at
1049 * different times, that number of intro points should bring all
1050 * of our intro points exactly to our target usage.
1052 * Then we clamp that number to a number of intro points we might
1053 * be willing to replace this intro point with and turn it into an
1054 * integer. then we clamp it again to the number of new intro
1055 * points we could establish now, then we adjust
1056 * service->n_intro_points_wanted and let rend_services_introduce
1057 * create the new intro points we want (if any).
1059 const double intro_point_usage =
1060 intro_point_accepted_intro_count(intro) /
1061 (double)(now - intro->time_published);
1062 const double intro_point_target_usage =
1063 INTRO_POINT_LIFETIME_INTRODUCTIONS /
1064 (double)INTRO_POINT_LIFETIME_MIN_SECONDS;
1065 const double fractional_n_intro_points_wanted_to_replace_this_one =
1066 (1.5 * (intro_point_usage / intro_point_target_usage));
1067 unsigned int n_intro_points_wanted_to_replace_this_one;
1068 unsigned int n_intro_points_wanted_now;
1069 unsigned int n_intro_points_really_wanted_now;
1070 int n_intro_points_really_replacing_this_one;
1072 if (fractional_n_intro_points_wanted_to_replace_this_one >
1073 NUM_INTRO_POINTS_MAX) {
1074 n_intro_points_wanted_to_replace_this_one = NUM_INTRO_POINTS_MAX;
1075 } else if (fractional_n_intro_points_wanted_to_replace_this_one < 0) {
1076 n_intro_points_wanted_to_replace_this_one = 0;
1077 } else {
1078 n_intro_points_wanted_to_replace_this_one = (unsigned)
1079 fractional_n_intro_points_wanted_to_replace_this_one;
1082 n_intro_points_wanted_now =
1083 service->n_intro_points_wanted +
1084 n_intro_points_wanted_to_replace_this_one - 1;
1086 if (n_intro_points_wanted_now < NUM_INTRO_POINTS_DEFAULT) {
1087 /* XXXX This should be NUM_INTRO_POINTS_MIN instead. Perhaps
1088 * another use of NUM_INTRO_POINTS_DEFAULT should be, too. */
1089 n_intro_points_really_wanted_now = NUM_INTRO_POINTS_DEFAULT;
1090 } else if (n_intro_points_wanted_now > NUM_INTRO_POINTS_MAX) {
1091 n_intro_points_really_wanted_now = NUM_INTRO_POINTS_MAX;
1092 } else {
1093 n_intro_points_really_wanted_now = n_intro_points_wanted_now;
1096 n_intro_points_really_replacing_this_one =
1097 n_intro_points_really_wanted_now - service->n_intro_points_wanted + 1;
1099 log_info(LD_REND, "Replacing closing intro point for service %s "
1100 "with %d new intro points (wanted %g replacements); "
1101 "service will now try to have %u intro points",
1102 rend_service_describe_for_log(service),
1103 n_intro_points_really_replacing_this_one,
1104 fractional_n_intro_points_wanted_to_replace_this_one,
1105 n_intro_points_really_wanted_now);
1107 service->n_intro_points_wanted = n_intro_points_really_wanted_now;
1111 /******
1112 * Handle cells
1113 ******/
1115 /** Respond to an INTRODUCE2 cell by launching a circuit to the chosen
1116 * rendezvous point.
1119 rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
1120 size_t request_len)
1122 /* Global status stuff */
1123 int status = 0, result;
1124 const or_options_t *options = get_options();
1125 char *err_msg = NULL;
1126 const char *stage_descr = NULL;
1127 int reason = END_CIRC_REASON_TORPROTOCOL;
1128 /* Service/circuit/key stuff we can learn before parsing */
1129 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
1130 rend_service_t *service = NULL;
1131 rend_intro_point_t *intro_point = NULL;
1132 crypto_pk_t *intro_key = NULL;
1133 /* Parsed cell */
1134 rend_intro_cell_t *parsed_req = NULL;
1135 /* Rendezvous point */
1136 extend_info_t *rp = NULL;
1138 * We need to look up and construct the extend_info_t for v0 and v1,
1139 * but all the info is in the cell and it's constructed by the parser
1140 * for v2 and v3, so freeing it would be a double-free. Use this to
1141 * keep track of whether we should free it.
1143 uint8_t need_rp_free = 0;
1144 /* XXX not handled yet */
1145 char buf[RELAY_PAYLOAD_SIZE];
1146 char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
1147 int i;
1148 crypto_dh_t *dh = NULL;
1149 origin_circuit_t *launched = NULL;
1150 crypt_path_t *cpath = NULL;
1151 char hexcookie[9];
1152 int circ_needs_uptime;
1153 time_t now = time(NULL);
1154 time_t elapsed;
1155 int replay;
1157 /* Do some initial validation and logging before we parse the cell */
1158 if (circuit->base_.purpose != CIRCUIT_PURPOSE_S_INTRO) {
1159 log_warn(LD_PROTOCOL,
1160 "Got an INTRODUCE2 over a non-introduction circuit %u.",
1161 (unsigned) circuit->base_.n_circ_id);
1162 goto err;
1165 #ifndef NON_ANONYMOUS_MODE_ENABLED
1166 tor_assert(!(circuit->build_state->onehop_tunnel));
1167 #endif
1168 tor_assert(circuit->rend_data);
1170 /* We'll use this in a bazillion log messages */
1171 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
1172 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
1174 /* look up service depending on circuit. */
1175 service =
1176 rend_service_get_by_pk_digest(circuit->rend_data->rend_pk_digest);
1177 if (!service) {
1178 log_warn(LD_BUG,
1179 "Internal error: Got an INTRODUCE2 cell on an intro "
1180 "circ for an unrecognized service %s.",
1181 escaped(serviceid));
1182 goto err;
1185 intro_point = find_intro_point(circuit);
1186 if (intro_point == NULL) {
1187 log_warn(LD_BUG,
1188 "Internal error: Got an INTRODUCE2 cell on an "
1189 "intro circ (for service %s) with no corresponding "
1190 "rend_intro_point_t.",
1191 escaped(serviceid));
1192 goto err;
1195 log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %u.",
1196 escaped(serviceid), (unsigned)circuit->base_.n_circ_id);
1198 /* use intro key instead of service key. */
1199 intro_key = circuit->intro_key;
1201 tor_free(err_msg);
1202 stage_descr = NULL;
1204 stage_descr = "early parsing";
1205 /* Early parsing pass (get pk, ciphertext); type 2 is INTRODUCE2 */
1206 parsed_req =
1207 rend_service_begin_parse_intro(request, request_len, 2, &err_msg);
1208 if (!parsed_req) {
1209 goto log_error;
1210 } else if (err_msg) {
1211 log_info(LD_REND, "%s on circ %u.", err_msg,
1212 (unsigned)circuit->base_.n_circ_id);
1213 tor_free(err_msg);
1216 stage_descr = "early validation";
1217 /* Early validation of pk/ciphertext part */
1218 result = rend_service_validate_intro_early(parsed_req, &err_msg);
1219 if (result < 0) {
1220 goto log_error;
1221 } else if (err_msg) {
1222 log_info(LD_REND, "%s on circ %u.", err_msg,
1223 (unsigned)circuit->base_.n_circ_id);
1224 tor_free(err_msg);
1227 /* make sure service replay caches are present */
1228 if (!service->accepted_intro_dh_parts) {
1229 service->accepted_intro_dh_parts =
1230 replaycache_new(REND_REPLAY_TIME_INTERVAL,
1231 REND_REPLAY_TIME_INTERVAL);
1234 if (!intro_point->accepted_intro_rsa_parts) {
1235 intro_point->accepted_intro_rsa_parts = replaycache_new(0, 0);
1238 /* check for replay of PK-encrypted portion. */
1239 replay = replaycache_add_test_and_elapsed(
1240 intro_point->accepted_intro_rsa_parts,
1241 parsed_req->ciphertext, parsed_req->ciphertext_len,
1242 &elapsed);
1244 if (replay) {
1245 log_warn(LD_REND,
1246 "Possible replay detected! We received an "
1247 "INTRODUCE2 cell with same PK-encrypted part %d "
1248 "seconds ago. Dropping cell.",
1249 (int)elapsed);
1250 goto err;
1253 stage_descr = "decryption";
1254 /* Now try to decrypt it */
1255 result = rend_service_decrypt_intro(parsed_req, intro_key, &err_msg);
1256 if (result < 0) {
1257 goto log_error;
1258 } else if (err_msg) {
1259 log_info(LD_REND, "%s on circ %u.", err_msg,
1260 (unsigned)circuit->base_.n_circ_id);
1261 tor_free(err_msg);
1264 stage_descr = "late parsing";
1265 /* Parse the plaintext */
1266 result = rend_service_parse_intro_plaintext(parsed_req, &err_msg);
1267 if (result < 0) {
1268 goto log_error;
1269 } else if (err_msg) {
1270 log_info(LD_REND, "%s on circ %u.", err_msg,
1271 (unsigned)circuit->base_.n_circ_id);
1272 tor_free(err_msg);
1275 stage_descr = "late validation";
1276 /* Validate the parsed plaintext parts */
1277 result = rend_service_validate_intro_late(parsed_req, &err_msg);
1278 if (result < 0) {
1279 goto log_error;
1280 } else if (err_msg) {
1281 log_info(LD_REND, "%s on circ %u.", err_msg,
1282 (unsigned)circuit->base_.n_circ_id);
1283 tor_free(err_msg);
1285 stage_descr = NULL;
1287 /* Increment INTRODUCE2 counter */
1288 ++(intro_point->accepted_introduce2_count);
1290 /* Find the rendezvous point */
1291 rp = find_rp_for_intro(parsed_req, &need_rp_free, &err_msg);
1292 if (!rp)
1293 goto log_error;
1295 /* Check if we'd refuse to talk to this router */
1296 if (options->StrictNodes &&
1297 routerset_contains_extendinfo(options->ExcludeNodes, rp)) {
1298 log_warn(LD_REND, "Client asked to rendezvous at a relay that we "
1299 "exclude, and StrictNodes is set. Refusing service.");
1300 reason = END_CIRC_REASON_INTERNAL; /* XXX might leak why we refused */
1301 goto err;
1304 base16_encode(hexcookie, 9, (const char *)(parsed_req->rc), 4);
1306 /* Check whether there is a past request with the same Diffie-Hellman,
1307 * part 1. */
1308 replay = replaycache_add_test_and_elapsed(
1309 service->accepted_intro_dh_parts,
1310 parsed_req->dh, DH_KEY_LEN,
1311 &elapsed);
1313 if (replay) {
1314 /* A Tor client will send a new INTRODUCE1 cell with the same rend
1315 * cookie and DH public key as its previous one if its intro circ
1316 * times out while in state CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT .
1317 * If we received the first INTRODUCE1 cell (the intro-point relay
1318 * converts it into an INTRODUCE2 cell), we are already trying to
1319 * connect to that rend point (and may have already succeeded);
1320 * drop this cell. */
1321 log_info(LD_REND, "We received an "
1322 "INTRODUCE2 cell with same first part of "
1323 "Diffie-Hellman handshake %d seconds ago. Dropping "
1324 "cell.",
1325 (int) elapsed);
1326 goto err;
1329 /* If the service performs client authorization, check included auth data. */
1330 if (service->clients) {
1331 if (parsed_req->version == 3 && parsed_req->u.v3.auth_len > 0) {
1332 if (rend_check_authorization(service,
1333 (const char*)parsed_req->u.v3.auth_data)) {
1334 log_info(LD_REND, "Authorization data in INTRODUCE2 cell are valid.");
1335 } else {
1336 log_info(LD_REND, "The authorization data that are contained in "
1337 "the INTRODUCE2 cell are invalid. Dropping cell.");
1338 reason = END_CIRC_REASON_CONNECTFAILED;
1339 goto err;
1341 } else {
1342 log_info(LD_REND, "INTRODUCE2 cell does not contain authentication "
1343 "data, but we require client authorization. Dropping cell.");
1344 reason = END_CIRC_REASON_CONNECTFAILED;
1345 goto err;
1349 /* Try DH handshake... */
1350 dh = crypto_dh_new(DH_TYPE_REND);
1351 if (!dh || crypto_dh_generate_public(dh)<0) {
1352 log_warn(LD_BUG,"Internal error: couldn't build DH state "
1353 "or generate public key.");
1354 reason = END_CIRC_REASON_INTERNAL;
1355 goto err;
1357 if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh,
1358 (char *)(parsed_req->dh),
1359 DH_KEY_LEN, keys,
1360 DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
1361 log_warn(LD_BUG, "Internal error: couldn't complete DH handshake");
1362 reason = END_CIRC_REASON_INTERNAL;
1363 goto err;
1366 circ_needs_uptime = rend_service_requires_uptime(service);
1368 /* help predict this next time */
1369 rep_hist_note_used_internal(now, circ_needs_uptime, 1);
1371 /* Launch a circuit to alice's chosen rendezvous point.
1373 for (i=0;i<MAX_REND_FAILURES;i++) {
1374 int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL;
1375 if (circ_needs_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
1376 launched = circuit_launch_by_extend_info(
1377 CIRCUIT_PURPOSE_S_CONNECT_REND, rp, flags);
1379 if (launched)
1380 break;
1382 if (!launched) { /* give up */
1383 log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous "
1384 "point %s for service %s.",
1385 safe_str_client(extend_info_describe(rp)),
1386 serviceid);
1387 reason = END_CIRC_REASON_CONNECTFAILED;
1388 goto err;
1390 log_info(LD_REND,
1391 "Accepted intro; launching circuit to %s "
1392 "(cookie %s) for service %s.",
1393 safe_str_client(extend_info_describe(rp)),
1394 hexcookie, serviceid);
1395 tor_assert(launched->build_state);
1396 /* Fill in the circuit's state. */
1397 launched->rend_data = tor_malloc_zero(sizeof(rend_data_t));
1398 memcpy(launched->rend_data->rend_pk_digest,
1399 circuit->rend_data->rend_pk_digest,
1400 DIGEST_LEN);
1401 memcpy(launched->rend_data->rend_cookie, parsed_req->rc, REND_COOKIE_LEN);
1402 strlcpy(launched->rend_data->onion_address, service->service_id,
1403 sizeof(launched->rend_data->onion_address));
1405 launched->build_state->service_pending_final_cpath_ref =
1406 tor_malloc_zero(sizeof(crypt_path_reference_t));
1407 launched->build_state->service_pending_final_cpath_ref->refcount = 1;
1409 launched->build_state->service_pending_final_cpath_ref->cpath = cpath =
1410 tor_malloc_zero(sizeof(crypt_path_t));
1411 cpath->magic = CRYPT_PATH_MAGIC;
1412 launched->build_state->expiry_time = now + MAX_REND_TIMEOUT;
1414 cpath->rend_dh_handshake_state = dh;
1415 dh = NULL;
1416 if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0)
1417 goto err;
1418 memcpy(cpath->rend_circ_nonce, keys, DIGEST_LEN);
1420 goto done;
1422 log_error:
1423 if (!err_msg) {
1424 if (stage_descr) {
1425 tor_asprintf(&err_msg,
1426 "unknown %s error for INTRODUCE2", stage_descr);
1427 } else {
1428 err_msg = tor_strdup("unknown error for INTRODUCE2");
1432 log_warn(LD_REND, "%s on circ %u", err_msg,
1433 (unsigned)circuit->base_.n_circ_id);
1434 err:
1435 status = -1;
1436 if (dh) crypto_dh_free(dh);
1437 if (launched) {
1438 circuit_mark_for_close(TO_CIRCUIT(launched), reason);
1440 tor_free(err_msg);
1442 done:
1443 memwipe(keys, 0, sizeof(keys));
1444 memwipe(buf, 0, sizeof(buf));
1445 memwipe(serviceid, 0, sizeof(serviceid));
1446 memwipe(hexcookie, 0, sizeof(hexcookie));
1448 /* Free the parsed cell */
1449 if (parsed_req) {
1450 rend_service_free_intro(parsed_req);
1451 parsed_req = NULL;
1454 /* Free rp if we must */
1455 if (need_rp_free) extend_info_free(rp);
1457 return status;
1460 /** Given a parsed and decrypted INTRODUCE2, find the rendezvous point or
1461 * return NULL and an error string if we can't.
1464 static extend_info_t *
1465 find_rp_for_intro(const rend_intro_cell_t *intro,
1466 uint8_t *need_free_out, char **err_msg_out)
1468 extend_info_t *rp = NULL;
1469 char *err_msg = NULL;
1470 const char *rp_nickname = NULL;
1471 const node_t *node = NULL;
1472 uint8_t need_free = 0;
1474 if (!intro || !need_free_out) {
1475 if (err_msg_out)
1476 err_msg = tor_strdup("Bad parameters to find_rp_for_intro()");
1478 goto err;
1481 if (intro->version == 0 || intro->version == 1) {
1482 if (intro->version == 1) rp_nickname = (const char *)(intro->u.v1.rp);
1483 else rp_nickname = (const char *)(intro->u.v0.rp);
1485 node = node_get_by_nickname(rp_nickname, 0);
1486 if (!node) {
1487 if (err_msg_out) {
1488 tor_asprintf(&err_msg,
1489 "Couldn't find router %s named in INTRODUCE2 cell",
1490 escaped_safe_str_client(rp_nickname));
1493 goto err;
1496 rp = extend_info_from_node(node, 0);
1497 if (!rp) {
1498 if (err_msg_out) {
1499 tor_asprintf(&err_msg,
1500 "Could build extend_info_t for router %s named "
1501 "in INTRODUCE2 cell",
1502 escaped_safe_str_client(rp_nickname));
1505 goto err;
1506 } else {
1507 need_free = 1;
1509 } else if (intro->version == 2) {
1510 rp = intro->u.v2.extend_info;
1511 } else if (intro->version == 3) {
1512 rp = intro->u.v3.extend_info;
1513 } else {
1514 if (err_msg_out) {
1515 tor_asprintf(&err_msg,
1516 "Unknown version %d in INTRODUCE2 cell",
1517 (int)(intro->version));
1520 goto err;
1523 goto done;
1525 err:
1526 if (err_msg_out) *err_msg_out = err_msg;
1527 else tor_free(err_msg);
1529 done:
1530 if (rp && need_free_out) *need_free_out = need_free;
1532 return rp;
1535 /** Free a parsed INTRODUCE1 or INTRODUCE2 cell that was allocated by
1536 * rend_service_parse_intro().
1538 void
1539 rend_service_free_intro(rend_intro_cell_t *request)
1541 if (!request) {
1542 log_info(LD_BUG, "rend_service_free_intro() called with NULL request!");
1543 return;
1546 /* Free ciphertext */
1547 tor_free(request->ciphertext);
1548 request->ciphertext_len = 0;
1550 /* Have plaintext? */
1551 if (request->plaintext) {
1552 /* Zero it out just to be safe */
1553 memwipe(request->plaintext, 0, request->plaintext_len);
1554 tor_free(request->plaintext);
1555 request->plaintext_len = 0;
1558 /* Have parsed plaintext? */
1559 if (request->parsed) {
1560 switch (request->version) {
1561 case 0:
1562 case 1:
1564 * Nothing more to do; these formats have no further pointers
1565 * in them.
1567 break;
1568 case 2:
1569 extend_info_free(request->u.v2.extend_info);
1570 request->u.v2.extend_info = NULL;
1571 break;
1572 case 3:
1573 if (request->u.v3.auth_data) {
1574 memwipe(request->u.v3.auth_data, 0, request->u.v3.auth_len);
1575 tor_free(request->u.v3.auth_data);
1578 extend_info_free(request->u.v3.extend_info);
1579 request->u.v3.extend_info = NULL;
1580 break;
1581 default:
1582 log_info(LD_BUG,
1583 "rend_service_free_intro() saw unknown protocol "
1584 "version %d.",
1585 request->version);
1589 /* Zero it out to make sure sensitive stuff doesn't hang around in memory */
1590 memwipe(request, 0, sizeof(*request));
1592 tor_free(request);
1595 /** Parse an INTRODUCE1 or INTRODUCE2 cell into a newly allocated
1596 * rend_intro_cell_t structure. Free it with rend_service_free_intro()
1597 * when finished. The type parameter should be 1 or 2 to indicate whether
1598 * this is INTRODUCE1 or INTRODUCE2. This parses only the non-encrypted
1599 * parts; after this, call rend_service_decrypt_intro() with a key, then
1600 * rend_service_parse_intro_plaintext() to finish parsing. The optional
1601 * err_msg_out parameter is set to a string suitable for log output
1602 * if parsing fails. This function does some validation, but only
1603 * that which depends solely on the contents of the cell and the
1604 * key; it can be unit-tested. Further validation is done in
1605 * rend_service_validate_intro().
1608 rend_intro_cell_t *
1609 rend_service_begin_parse_intro(const uint8_t *request,
1610 size_t request_len,
1611 uint8_t type,
1612 char **err_msg_out)
1614 rend_intro_cell_t *rv = NULL;
1615 char *err_msg = NULL;
1617 if (!request || request_len <= 0) goto err;
1618 if (!(type == 1 || type == 2)) goto err;
1620 /* First, check that the cell is long enough to be a sensible INTRODUCE */
1622 /* min key length plus digest length plus nickname length */
1623 if (request_len <
1624 (DIGEST_LEN + REND_COOKIE_LEN + (MAX_NICKNAME_LEN + 1) +
1625 DH_KEY_LEN + 42)) {
1626 if (err_msg_out) {
1627 tor_asprintf(&err_msg,
1628 "got a truncated INTRODUCE%d cell",
1629 (int)type);
1631 goto err;
1634 /* Allocate a new parsed cell structure */
1635 rv = tor_malloc_zero(sizeof(*rv));
1637 /* Set the type */
1638 rv->type = type;
1640 /* Copy in the ID */
1641 memcpy(rv->pk, request, DIGEST_LEN);
1643 /* Copy in the ciphertext */
1644 rv->ciphertext = tor_malloc(request_len - DIGEST_LEN);
1645 memcpy(rv->ciphertext, request + DIGEST_LEN, request_len - DIGEST_LEN);
1646 rv->ciphertext_len = request_len - DIGEST_LEN;
1648 goto done;
1650 err:
1651 if (rv) rend_service_free_intro(rv);
1652 rv = NULL;
1653 if (err_msg_out && !err_msg) {
1654 tor_asprintf(&err_msg,
1655 "unknown INTRODUCE%d error",
1656 (int)type);
1659 done:
1660 if (err_msg_out) *err_msg_out = err_msg;
1661 else tor_free(err_msg);
1663 return rv;
1666 /** Parse the version-specific parts of a v0 or v1 INTRODUCE1 or INTRODUCE2
1667 * cell
1670 static ssize_t
1671 rend_service_parse_intro_for_v0_or_v1(
1672 rend_intro_cell_t *intro,
1673 const uint8_t *buf,
1674 size_t plaintext_len,
1675 char **err_msg_out)
1677 const char *rp_nickname, *endptr;
1678 size_t nickname_field_len, ver_specific_len;
1680 if (intro->version == 1) {
1681 ver_specific_len = MAX_HEX_NICKNAME_LEN + 2;
1682 rp_nickname = ((const char *)buf) + 1;
1683 nickname_field_len = MAX_HEX_NICKNAME_LEN + 1;
1684 } else if (intro->version == 0) {
1685 ver_specific_len = MAX_NICKNAME_LEN + 1;
1686 rp_nickname = (const char *)buf;
1687 nickname_field_len = MAX_NICKNAME_LEN + 1;
1688 } else {
1689 if (err_msg_out)
1690 tor_asprintf(err_msg_out,
1691 "rend_service_parse_intro_for_v0_or_v1() called with "
1692 "bad version %d on INTRODUCE%d cell (this is a bug)",
1693 intro->version,
1694 (int)(intro->type));
1695 goto err;
1698 if (plaintext_len < ver_specific_len) {
1699 if (err_msg_out)
1700 tor_asprintf(err_msg_out,
1701 "short plaintext of encrypted part in v1 INTRODUCE%d "
1702 "cell (%lu bytes, needed %lu)",
1703 (int)(intro->type),
1704 (unsigned long)plaintext_len,
1705 (unsigned long)ver_specific_len);
1706 goto err;
1709 endptr = memchr(rp_nickname, 0, nickname_field_len);
1710 if (!endptr || endptr == rp_nickname) {
1711 if (err_msg_out) {
1712 tor_asprintf(err_msg_out,
1713 "couldn't find a nul-padded nickname in "
1714 "INTRODUCE%d cell",
1715 (int)(intro->type));
1717 goto err;
1720 if ((intro->version == 0 &&
1721 !is_legal_nickname(rp_nickname)) ||
1722 (intro->version == 1 &&
1723 !is_legal_nickname_or_hexdigest(rp_nickname))) {
1724 if (err_msg_out) {
1725 tor_asprintf(err_msg_out,
1726 "bad nickname in INTRODUCE%d cell",
1727 (int)(intro->type));
1729 goto err;
1732 if (intro->version == 1) {
1733 memcpy(intro->u.v1.rp, rp_nickname, endptr - rp_nickname + 1);
1734 } else {
1735 memcpy(intro->u.v0.rp, rp_nickname, endptr - rp_nickname + 1);
1738 return ver_specific_len;
1740 err:
1741 return -1;
1744 /** Parse the version-specific parts of a v2 INTRODUCE1 or INTRODUCE2 cell
1747 static ssize_t
1748 rend_service_parse_intro_for_v2(
1749 rend_intro_cell_t *intro,
1750 const uint8_t *buf,
1751 size_t plaintext_len,
1752 char **err_msg_out)
1754 unsigned int klen;
1755 extend_info_t *extend_info = NULL;
1756 ssize_t ver_specific_len;
1759 * We accept version 3 too so that the v3 parser can call this with
1760 * and adjusted buffer for the latter part of a v3 cell, which is
1761 * identical to a v2 cell.
1763 if (!(intro->version == 2 ||
1764 intro->version == 3)) {
1765 if (err_msg_out)
1766 tor_asprintf(err_msg_out,
1767 "rend_service_parse_intro_for_v2() called with "
1768 "bad version %d on INTRODUCE%d cell (this is a bug)",
1769 intro->version,
1770 (int)(intro->type));
1771 goto err;
1774 /* 7 == version, IP and port, DIGEST_LEN == id, 2 == key length */
1775 if (plaintext_len < 7 + DIGEST_LEN + 2) {
1776 if (err_msg_out) {
1777 tor_asprintf(err_msg_out,
1778 "truncated plaintext of encrypted parted of "
1779 "version %d INTRODUCE%d cell",
1780 intro->version,
1781 (int)(intro->type));
1784 goto err;
1787 extend_info = tor_malloc_zero(sizeof(extend_info_t));
1788 tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf + 1));
1789 extend_info->port = ntohs(get_uint16(buf + 5));
1790 memcpy(extend_info->identity_digest, buf + 7, DIGEST_LEN);
1791 extend_info->nickname[0] = '$';
1792 base16_encode(extend_info->nickname + 1, sizeof(extend_info->nickname) - 1,
1793 extend_info->identity_digest, DIGEST_LEN);
1794 klen = ntohs(get_uint16(buf + 7 + DIGEST_LEN));
1796 /* 7 == version, IP and port, DIGEST_LEN == id, 2 == key length */
1797 if (plaintext_len < 7 + DIGEST_LEN + 2 + klen) {
1798 if (err_msg_out) {
1799 tor_asprintf(err_msg_out,
1800 "truncated plaintext of encrypted parted of "
1801 "version %d INTRODUCE%d cell",
1802 intro->version,
1803 (int)(intro->type));
1806 goto err;
1809 extend_info->onion_key =
1810 crypto_pk_asn1_decode((const char *)(buf + 7 + DIGEST_LEN + 2), klen);
1811 if (!extend_info->onion_key) {
1812 if (err_msg_out) {
1813 tor_asprintf(err_msg_out,
1814 "error decoding onion key in version %d "
1815 "INTRODUCE%d cell",
1816 intro->version,
1817 (intro->type));
1820 goto err;
1823 ver_specific_len = 7+DIGEST_LEN+2+klen;
1825 if (intro->version == 2) intro->u.v2.extend_info = extend_info;
1826 else intro->u.v3.extend_info = extend_info;
1828 return ver_specific_len;
1830 err:
1831 extend_info_free(extend_info);
1833 return -1;
1836 /** Parse the version-specific parts of a v3 INTRODUCE1 or INTRODUCE2 cell
1839 static ssize_t
1840 rend_service_parse_intro_for_v3(
1841 rend_intro_cell_t *intro,
1842 const uint8_t *buf,
1843 size_t plaintext_len,
1844 char **err_msg_out)
1846 ssize_t adjust, v2_ver_specific_len, ts_offset;
1848 /* This should only be called on v3 cells */
1849 if (intro->version != 3) {
1850 if (err_msg_out)
1851 tor_asprintf(err_msg_out,
1852 "rend_service_parse_intro_for_v3() called with "
1853 "bad version %d on INTRODUCE%d cell (this is a bug)",
1854 intro->version,
1855 (int)(intro->type));
1856 goto err;
1860 * Check that we have at least enough to get auth_len:
1862 * 1 octet for version, 1 for auth_type, 2 for auth_len
1864 if (plaintext_len < 4) {
1865 if (err_msg_out) {
1866 tor_asprintf(err_msg_out,
1867 "truncated plaintext of encrypted parted of "
1868 "version %d INTRODUCE%d cell",
1869 intro->version,
1870 (int)(intro->type));
1873 goto err;
1877 * The rend_client_send_introduction() function over in rendclient.c is
1878 * broken (i.e., fails to match the spec) in such a way that we can't
1879 * change it without breaking the protocol. Specifically, it doesn't
1880 * emit auth_len when auth-type is REND_NO_AUTH, so everything is off
1881 * by two bytes after that. Calculate ts_offset and do everything from
1882 * the timestamp on relative to that to handle this dain bramage.
1885 intro->u.v3.auth_type = buf[1];
1886 if (intro->u.v3.auth_type != REND_NO_AUTH) {
1887 intro->u.v3.auth_len = ntohs(get_uint16(buf + 2));
1888 ts_offset = 4 + intro->u.v3.auth_len;
1889 } else {
1890 intro->u.v3.auth_len = 0;
1891 ts_offset = 2;
1894 /* Check that auth len makes sense for this auth type */
1895 if (intro->u.v3.auth_type == REND_BASIC_AUTH ||
1896 intro->u.v3.auth_type == REND_STEALTH_AUTH) {
1897 if (intro->u.v3.auth_len != REND_DESC_COOKIE_LEN) {
1898 if (err_msg_out) {
1899 tor_asprintf(err_msg_out,
1900 "wrong auth data size %d for INTRODUCE%d cell, "
1901 "should be %d",
1902 (int)(intro->u.v3.auth_len),
1903 (int)(intro->type),
1904 REND_DESC_COOKIE_LEN);
1907 goto err;
1911 /* Check that we actually have everything up through the timestamp */
1912 if (plaintext_len < (size_t)(ts_offset)+4) {
1913 if (err_msg_out) {
1914 tor_asprintf(err_msg_out,
1915 "truncated plaintext of encrypted parted of "
1916 "version %d INTRODUCE%d cell",
1917 intro->version,
1918 (int)(intro->type));
1921 goto err;
1924 if (intro->u.v3.auth_type != REND_NO_AUTH &&
1925 intro->u.v3.auth_len > 0) {
1926 /* Okay, we can go ahead and copy auth_data */
1927 intro->u.v3.auth_data = tor_malloc(intro->u.v3.auth_len);
1929 * We know we had an auth_len field in this case, so 4 is
1930 * always right.
1932 memcpy(intro->u.v3.auth_data, buf + 4, intro->u.v3.auth_len);
1936 * From here on, the format is as in v2, so we call the v2 parser with
1937 * adjusted buffer and length. We are 4 + ts_offset octets in, but the
1938 * v2 parser expects to skip over a version byte at the start, so we
1939 * adjust by 3 + ts_offset.
1941 adjust = 3 + ts_offset;
1943 v2_ver_specific_len =
1944 rend_service_parse_intro_for_v2(intro,
1945 buf + adjust, plaintext_len - adjust,
1946 err_msg_out);
1948 /* Success in v2 parser */
1949 if (v2_ver_specific_len >= 0) return v2_ver_specific_len + adjust;
1950 /* Failure in v2 parser; it will have provided an err_msg */
1951 else return v2_ver_specific_len;
1953 err:
1954 return -1;
1957 /** Table of parser functions for version-specific parts of an INTRODUCE2
1958 * cell.
1961 static ssize_t
1962 (*intro_version_handlers[])(
1963 rend_intro_cell_t *,
1964 const uint8_t *,
1965 size_t,
1966 char **) =
1967 { rend_service_parse_intro_for_v0_or_v1,
1968 rend_service_parse_intro_for_v0_or_v1,
1969 rend_service_parse_intro_for_v2,
1970 rend_service_parse_intro_for_v3 };
1972 /** Decrypt the encrypted part of an INTRODUCE1 or INTRODUCE2 cell,
1973 * return 0 if successful, or < 0 and write an error message to
1974 * *err_msg_out if provided.
1978 rend_service_decrypt_intro(
1979 rend_intro_cell_t *intro,
1980 crypto_pk_t *key,
1981 char **err_msg_out)
1983 char *err_msg = NULL;
1984 uint8_t key_digest[DIGEST_LEN];
1985 char service_id[REND_SERVICE_ID_LEN_BASE32+1];
1986 ssize_t key_len;
1987 uint8_t buf[RELAY_PAYLOAD_SIZE];
1988 int result, status = 0;
1990 if (!intro || !key) {
1991 if (err_msg_out) {
1992 err_msg =
1993 tor_strdup("rend_service_decrypt_intro() called with bad "
1994 "parameters");
1997 status = -2;
1998 goto err;
2001 /* Make sure we have ciphertext */
2002 if (!(intro->ciphertext) || intro->ciphertext_len <= 0) {
2003 if (err_msg_out) {
2004 tor_asprintf(&err_msg,
2005 "rend_intro_cell_t was missing ciphertext for "
2006 "INTRODUCE%d cell",
2007 (int)(intro->type));
2009 status = -3;
2010 goto err;
2013 /* Check that this cell actually matches this service key */
2015 /* first DIGEST_LEN bytes of request is intro or service pk digest */
2016 crypto_pk_get_digest(key, (char *)key_digest);
2017 if (tor_memneq(key_digest, intro->pk, DIGEST_LEN)) {
2018 if (err_msg_out) {
2019 base32_encode(service_id, REND_SERVICE_ID_LEN_BASE32 + 1,
2020 (char*)(intro->pk), REND_SERVICE_ID_LEN);
2021 tor_asprintf(&err_msg,
2022 "got an INTRODUCE%d cell for the wrong service (%s)",
2023 (int)(intro->type),
2024 escaped(service_id));
2027 status = -4;
2028 goto err;
2031 /* Make sure the encrypted part is long enough to decrypt */
2033 key_len = crypto_pk_keysize(key);
2034 if (intro->ciphertext_len < key_len) {
2035 if (err_msg_out) {
2036 tor_asprintf(&err_msg,
2037 "got an INTRODUCE%d cell with a truncated PK-encrypted "
2038 "part",
2039 (int)(intro->type));
2042 status = -5;
2043 goto err;
2046 /* Decrypt the encrypted part */
2048 note_crypto_pk_op(REND_SERVER);
2049 result =
2050 crypto_pk_private_hybrid_decrypt(
2051 key, (char *)buf, sizeof(buf),
2052 (const char *)(intro->ciphertext), intro->ciphertext_len,
2053 PK_PKCS1_OAEP_PADDING, 1);
2054 if (result < 0) {
2055 if (err_msg_out) {
2056 tor_asprintf(&err_msg,
2057 "couldn't decrypt INTRODUCE%d cell",
2058 (int)(intro->type));
2060 status = -6;
2061 goto err;
2063 intro->plaintext_len = result;
2064 intro->plaintext = tor_malloc(intro->plaintext_len);
2065 memcpy(intro->plaintext, buf, intro->plaintext_len);
2067 goto done;
2069 err:
2070 if (err_msg_out && !err_msg) {
2071 tor_asprintf(&err_msg,
2072 "unknown INTRODUCE%d error decrypting encrypted part",
2073 intro ? (int)(intro->type) : -1);
2075 if (status >= 0) status = -1;
2077 done:
2078 if (err_msg_out) *err_msg_out = err_msg;
2079 else tor_free(err_msg);
2081 /* clean up potentially sensitive material */
2082 memwipe(buf, 0, sizeof(buf));
2083 memwipe(key_digest, 0, sizeof(key_digest));
2084 memwipe(service_id, 0, sizeof(service_id));
2086 return status;
2089 /** Parse the plaintext of the encrypted part of an INTRODUCE1 or
2090 * INTRODUCE2 cell, return 0 if successful, or < 0 and write an error
2091 * message to *err_msg_out if provided.
2095 rend_service_parse_intro_plaintext(
2096 rend_intro_cell_t *intro,
2097 char **err_msg_out)
2099 char *err_msg = NULL;
2100 ssize_t ver_specific_len, ver_invariant_len;
2101 uint8_t version;
2102 int status = 0;
2104 if (!intro) {
2105 if (err_msg_out) {
2106 err_msg =
2107 tor_strdup("rend_service_parse_intro_plaintext() called with NULL "
2108 "rend_intro_cell_t");
2111 status = -2;
2112 goto err;
2115 /* Check that we have plaintext */
2116 if (!(intro->plaintext) || intro->plaintext_len <= 0) {
2117 if (err_msg_out) {
2118 err_msg = tor_strdup("rend_intro_cell_t was missing plaintext");
2120 status = -3;
2121 goto err;
2124 /* In all formats except v0, the first byte is a version number */
2125 version = intro->plaintext[0];
2127 /* v0 has no version byte (stupid...), so handle it as a fallback */
2128 if (version > 3) version = 0;
2130 /* Copy the version into the parsed cell structure */
2131 intro->version = version;
2133 /* Call the version-specific parser from the table */
2134 ver_specific_len =
2135 intro_version_handlers[version](intro,
2136 intro->plaintext, intro->plaintext_len,
2137 &err_msg);
2138 if (ver_specific_len < 0) {
2139 status = -4;
2140 goto err;
2143 /** The rendezvous cookie and Diffie-Hellman stuff are version-invariant
2144 * and at the end of the plaintext of the encrypted part of the cell.
2147 ver_invariant_len = intro->plaintext_len - ver_specific_len;
2148 if (ver_invariant_len < REND_COOKIE_LEN + DH_KEY_LEN) {
2149 tor_asprintf(&err_msg,
2150 "decrypted plaintext of INTRODUCE%d cell was truncated (%ld bytes)",
2151 (int)(intro->type),
2152 (long)(intro->plaintext_len));
2153 status = -5;
2154 goto err;
2155 } else if (ver_invariant_len > REND_COOKIE_LEN + DH_KEY_LEN) {
2156 tor_asprintf(&err_msg,
2157 "decrypted plaintext of INTRODUCE%d cell was too long (%ld bytes)",
2158 (int)(intro->type),
2159 (long)(intro->plaintext_len));
2160 status = -6;
2161 } else {
2162 memcpy(intro->rc,
2163 intro->plaintext + ver_specific_len,
2164 REND_COOKIE_LEN);
2165 memcpy(intro->dh,
2166 intro->plaintext + ver_specific_len + REND_COOKIE_LEN,
2167 DH_KEY_LEN);
2170 /* Flag it as being fully parsed */
2171 intro->parsed = 1;
2173 goto done;
2175 err:
2176 if (err_msg_out && !err_msg) {
2177 tor_asprintf(&err_msg,
2178 "unknown INTRODUCE%d error parsing encrypted part",
2179 intro ? (int)(intro->type) : -1);
2181 if (status >= 0) status = -1;
2183 done:
2184 if (err_msg_out) *err_msg_out = err_msg;
2185 else tor_free(err_msg);
2187 return status;
2190 /** Do validity checks on a parsed intro cell before decryption; some of
2191 * these are not done in rend_service_begin_parse_intro() itself because
2192 * they depend on a lot of other state and would make it hard to unit test.
2193 * Returns >= 0 if successful or < 0 if the intro cell is invalid, and
2194 * optionally writes out an error message for logging. If an err_msg
2195 * pointer is provided, it is the caller's responsibility to free any
2196 * provided message.
2200 rend_service_validate_intro_early(const rend_intro_cell_t *intro,
2201 char **err_msg_out)
2203 int status = 0;
2205 if (!intro) {
2206 if (err_msg_out)
2207 *err_msg_out =
2208 tor_strdup("NULL intro cell passed to "
2209 "rend_service_validate_intro_early()");
2211 status = -1;
2212 goto err;
2215 /* TODO */
2217 err:
2218 return status;
2221 /** Do validity checks on a parsed intro cell after decryption; some of
2222 * these are not done in rend_service_parse_intro_plaintext() itself because
2223 * they depend on a lot of other state and would make it hard to unit test.
2224 * Returns >= 0 if successful or < 0 if the intro cell is invalid, and
2225 * optionally writes out an error message for logging. If an err_msg
2226 * pointer is provided, it is the caller's responsibility to free any
2227 * provided message.
2231 rend_service_validate_intro_late(const rend_intro_cell_t *intro,
2232 char **err_msg_out)
2234 int status = 0;
2236 if (!intro) {
2237 if (err_msg_out)
2238 *err_msg_out =
2239 tor_strdup("NULL intro cell passed to "
2240 "rend_service_validate_intro_late()");
2242 status = -1;
2243 goto err;
2246 if (intro->version == 3 && intro->parsed) {
2247 if (!(intro->u.v3.auth_type == REND_NO_AUTH ||
2248 intro->u.v3.auth_type == REND_BASIC_AUTH ||
2249 intro->u.v3.auth_type == REND_STEALTH_AUTH)) {
2250 /* This is an informative message, not an error, as in the old code */
2251 if (err_msg_out)
2252 tor_asprintf(err_msg_out,
2253 "unknown authorization type %d",
2254 intro->u.v3.auth_type);
2258 err:
2259 return status;
2262 /** Called when we fail building a rendezvous circuit at some point other
2263 * than the last hop: launches a new circuit to the same rendezvous point.
2265 void
2266 rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
2268 origin_circuit_t *newcirc;
2269 cpath_build_state_t *newstate, *oldstate;
2271 tor_assert(oldcirc->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
2273 /* Don't relaunch the same rend circ twice. */
2274 if (oldcirc->hs_service_side_rend_circ_has_been_relaunched) {
2275 log_info(LD_REND, "Rendezvous circuit to %s has already been relaunched; "
2276 "not relaunching it again.",
2277 oldcirc->build_state ?
2278 safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
2279 : "*unknown*");
2280 return;
2282 oldcirc->hs_service_side_rend_circ_has_been_relaunched = 1;
2284 if (!oldcirc->build_state ||
2285 oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
2286 oldcirc->build_state->expiry_time < time(NULL)) {
2287 log_info(LD_REND,
2288 "Attempt to build circuit to %s for rendezvous has failed "
2289 "too many times or expired; giving up.",
2290 oldcirc->build_state ?
2291 safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
2292 : "*unknown*");
2293 return;
2296 oldstate = oldcirc->build_state;
2297 tor_assert(oldstate);
2299 if (oldstate->service_pending_final_cpath_ref == NULL) {
2300 log_info(LD_REND,"Skipping relaunch of circ that failed on its first hop. "
2301 "Initiator will retry.");
2302 return;
2305 log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
2306 safe_str(extend_info_describe(oldstate->chosen_exit)));
2308 newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
2309 oldstate->chosen_exit,
2310 CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
2312 if (!newcirc) {
2313 log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
2314 safe_str(extend_info_describe(oldstate->chosen_exit)));
2315 return;
2317 newstate = newcirc->build_state;
2318 tor_assert(newstate);
2319 newstate->failure_count = oldstate->failure_count+1;
2320 newstate->expiry_time = oldstate->expiry_time;
2321 newstate->service_pending_final_cpath_ref =
2322 oldstate->service_pending_final_cpath_ref;
2323 ++(newstate->service_pending_final_cpath_ref->refcount);
2325 newcirc->rend_data = rend_data_dup(oldcirc->rend_data);
2328 /** Launch a circuit to serve as an introduction point for the service
2329 * <b>service</b> at the introduction point <b>nickname</b>
2331 static int
2332 rend_service_launch_establish_intro(rend_service_t *service,
2333 rend_intro_point_t *intro)
2335 origin_circuit_t *launched;
2337 log_info(LD_REND,
2338 "Launching circuit to introduction point %s for service %s",
2339 safe_str_client(extend_info_describe(intro->extend_info)),
2340 service->service_id);
2342 rep_hist_note_used_internal(time(NULL), 1, 0);
2344 ++service->n_intro_circuits_launched;
2345 launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
2346 intro->extend_info,
2347 CIRCLAUNCH_NEED_UPTIME|CIRCLAUNCH_IS_INTERNAL);
2349 if (!launched) {
2350 log_info(LD_REND,
2351 "Can't launch circuit to establish introduction at %s.",
2352 safe_str_client(extend_info_describe(intro->extend_info)));
2353 return -1;
2356 if (tor_memneq(intro->extend_info->identity_digest,
2357 launched->build_state->chosen_exit->identity_digest, DIGEST_LEN)) {
2358 char cann[HEX_DIGEST_LEN+1], orig[HEX_DIGEST_LEN+1];
2359 base16_encode(cann, sizeof(cann),
2360 launched->build_state->chosen_exit->identity_digest,
2361 DIGEST_LEN);
2362 base16_encode(orig, sizeof(orig),
2363 intro->extend_info->identity_digest, DIGEST_LEN);
2364 log_info(LD_REND, "The intro circuit we just cannibalized ends at $%s, "
2365 "but we requested an intro circuit to $%s. Updating "
2366 "our service.", cann, orig);
2367 extend_info_free(intro->extend_info);
2368 intro->extend_info = extend_info_dup(launched->build_state->chosen_exit);
2371 launched->rend_data = tor_malloc_zero(sizeof(rend_data_t));
2372 strlcpy(launched->rend_data->onion_address, service->service_id,
2373 sizeof(launched->rend_data->onion_address));
2374 memcpy(launched->rend_data->rend_pk_digest, service->pk_digest, DIGEST_LEN);
2375 launched->intro_key = crypto_pk_dup_key(intro->intro_key);
2376 if (launched->base_.state == CIRCUIT_STATE_OPEN)
2377 rend_service_intro_has_opened(launched);
2378 return 0;
2381 /** Return the number of introduction points that are or have been
2382 * established for the given service address in <b>query</b>. */
2383 static int
2384 count_established_intro_points(const char *query)
2386 int num_ipos = 0;
2387 circuit_t *circ;
2388 TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) {
2389 if (!circ->marked_for_close &&
2390 circ->state == CIRCUIT_STATE_OPEN &&
2391 (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
2392 circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
2393 origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
2394 if (oc->rend_data &&
2395 !rend_cmp_service_ids(query, oc->rend_data->onion_address))
2396 num_ipos++;
2399 return num_ipos;
2402 /** Called when we're done building a circuit to an introduction point:
2403 * sends a RELAY_ESTABLISH_INTRO cell.
2405 void
2406 rend_service_intro_has_opened(origin_circuit_t *circuit)
2408 rend_service_t *service;
2409 size_t len;
2410 int r;
2411 char buf[RELAY_PAYLOAD_SIZE];
2412 char auth[DIGEST_LEN + 9];
2413 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2414 int reason = END_CIRC_REASON_TORPROTOCOL;
2415 crypto_pk_t *intro_key;
2417 tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
2418 #ifndef NON_ANONYMOUS_MODE_ENABLED
2419 tor_assert(!(circuit->build_state->onehop_tunnel));
2420 #endif
2421 tor_assert(circuit->cpath);
2422 tor_assert(circuit->rend_data);
2424 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
2425 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
2427 service = rend_service_get_by_pk_digest(
2428 circuit->rend_data->rend_pk_digest);
2429 if (!service) {
2430 log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %u.",
2431 serviceid, (unsigned)circuit->base_.n_circ_id);
2432 reason = END_CIRC_REASON_NOSUCHSERVICE;
2433 goto err;
2436 /* If we already have enough introduction circuits for this service,
2437 * redefine this one as a general circuit or close it, depending. */
2438 if (count_established_intro_points(serviceid) >
2439 (int)service->n_intro_points_wanted) { /* XXX023 remove cast */
2440 const or_options_t *options = get_options();
2441 if (options->ExcludeNodes) {
2442 /* XXXX in some future version, we can test whether the transition is
2443 allowed or not given the actual nodes in the circuit. But for now,
2444 this case, we might as well close the thing. */
2445 log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
2446 "circuit, but we already have enough. Closing it.");
2447 reason = END_CIRC_REASON_NONE;
2448 goto err;
2449 } else {
2450 tor_assert(circuit->build_state->is_internal);
2451 log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
2452 "circuit, but we already have enough. Redefining purpose to "
2453 "general; leaving as internal.");
2455 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_C_GENERAL);
2458 rend_data_t *rend_data = circuit->rend_data;
2459 circuit->rend_data = NULL;
2460 rend_data_free(rend_data);
2463 crypto_pk_t *intro_key = circuit->intro_key;
2464 circuit->intro_key = NULL;
2465 crypto_pk_free(intro_key);
2468 circuit_has_opened(circuit);
2469 goto done;
2473 log_info(LD_REND,
2474 "Established circuit %u as introduction point for service %s",
2475 (unsigned)circuit->base_.n_circ_id, serviceid);
2477 /* Use the intro key instead of the service key in ESTABLISH_INTRO. */
2478 intro_key = circuit->intro_key;
2479 /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
2480 r = crypto_pk_asn1_encode(intro_key, buf+2,
2481 RELAY_PAYLOAD_SIZE-2);
2482 if (r < 0) {
2483 log_warn(LD_BUG, "Internal error; failed to establish intro point.");
2484 reason = END_CIRC_REASON_INTERNAL;
2485 goto err;
2487 len = r;
2488 set_uint16(buf, htons((uint16_t)len));
2489 len += 2;
2490 memcpy(auth, circuit->cpath->prev->rend_circ_nonce, DIGEST_LEN);
2491 memcpy(auth+DIGEST_LEN, "INTRODUCE", 9);
2492 if (crypto_digest(buf+len, auth, DIGEST_LEN+9))
2493 goto err;
2494 len += 20;
2495 note_crypto_pk_op(REND_SERVER);
2496 r = crypto_pk_private_sign_digest(intro_key, buf+len, sizeof(buf)-len,
2497 buf, len);
2498 if (r<0) {
2499 log_warn(LD_BUG, "Internal error: couldn't sign introduction request.");
2500 reason = END_CIRC_REASON_INTERNAL;
2501 goto err;
2503 len += r;
2505 if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
2506 RELAY_COMMAND_ESTABLISH_INTRO,
2507 buf, len, circuit->cpath->prev)<0) {
2508 log_info(LD_GENERAL,
2509 "Couldn't send introduction request for service %s on circuit %u",
2510 serviceid, (unsigned)circuit->base_.n_circ_id);
2511 reason = END_CIRC_REASON_INTERNAL;
2512 goto err;
2515 /* We've attempted to use this circuit */
2516 pathbias_count_use_attempt(circuit);
2518 goto done;
2520 err:
2521 circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
2522 done:
2523 memwipe(buf, 0, sizeof(buf));
2524 memwipe(auth, 0, sizeof(auth));
2525 memwipe(serviceid, 0, sizeof(serviceid));
2527 return;
2530 /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
2531 * live introduction point, and note that the service descriptor is
2532 * now out-of-date. */
2534 rend_service_intro_established(origin_circuit_t *circuit,
2535 const uint8_t *request,
2536 size_t request_len)
2538 rend_service_t *service;
2539 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2540 (void) request;
2541 (void) request_len;
2543 if (circuit->base_.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
2544 log_warn(LD_PROTOCOL,
2545 "received INTRO_ESTABLISHED cell on non-intro circuit.");
2546 goto err;
2548 tor_assert(circuit->rend_data);
2549 service = rend_service_get_by_pk_digest(
2550 circuit->rend_data->rend_pk_digest);
2551 if (!service) {
2552 log_warn(LD_REND, "Unknown service on introduction circuit %u.",
2553 (unsigned)circuit->base_.n_circ_id);
2554 goto err;
2556 service->desc_is_dirty = time(NULL);
2557 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_INTRO);
2559 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32 + 1,
2560 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
2561 log_info(LD_REND,
2562 "Received INTRO_ESTABLISHED cell on circuit %u for service %s",
2563 (unsigned)circuit->base_.n_circ_id, serviceid);
2565 /* Getting a valid INTRODUCE_ESTABLISHED means we've successfully
2566 * used the circ */
2567 pathbias_mark_use_success(circuit);
2569 return 0;
2570 err:
2571 circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
2572 return -1;
2575 /** Called once a circuit to a rendezvous point is established: sends a
2576 * RELAY_COMMAND_RENDEZVOUS1 cell.
2578 void
2579 rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
2581 rend_service_t *service;
2582 char buf[RELAY_PAYLOAD_SIZE];
2583 crypt_path_t *hop;
2584 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2585 char hexcookie[9];
2586 int reason;
2588 tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
2589 tor_assert(circuit->cpath);
2590 tor_assert(circuit->build_state);
2591 #ifndef NON_ANONYMOUS_MODE_ENABLED
2592 tor_assert(!(circuit->build_state->onehop_tunnel));
2593 #endif
2594 tor_assert(circuit->rend_data);
2596 /* Declare the circuit dirty to avoid reuse, and for path-bias */
2597 if (!circuit->base_.timestamp_dirty)
2598 circuit->base_.timestamp_dirty = time(NULL);
2600 /* This may be redundant */
2601 pathbias_count_use_attempt(circuit);
2603 hop = circuit->build_state->service_pending_final_cpath_ref->cpath;
2605 base16_encode(hexcookie,9,circuit->rend_data->rend_cookie,4);
2606 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
2607 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
2609 log_info(LD_REND,
2610 "Done building circuit %u to rendezvous with "
2611 "cookie %s for service %s",
2612 (unsigned)circuit->base_.n_circ_id, hexcookie, serviceid);
2614 /* Clear the 'in-progress HS circ has timed out' flag for
2615 * consistency with what happens on the client side; this line has
2616 * no effect on Tor's behaviour. */
2617 circuit->hs_circ_has_timed_out = 0;
2619 /* If hop is NULL, another rend circ has already connected to this
2620 * rend point. Close this circ. */
2621 if (hop == NULL) {
2622 log_info(LD_REND, "Another rend circ has already reached this rend point; "
2623 "closing this rend circ.");
2624 reason = END_CIRC_REASON_NONE;
2625 goto err;
2628 /* Remove our final cpath element from the reference, so that no
2629 * other circuit will try to use it. Store it in
2630 * pending_final_cpath for now to ensure that it will be freed if
2631 * our rendezvous attempt fails. */
2632 circuit->build_state->pending_final_cpath = hop;
2633 circuit->build_state->service_pending_final_cpath_ref->cpath = NULL;
2635 service = rend_service_get_by_pk_digest(
2636 circuit->rend_data->rend_pk_digest);
2637 if (!service) {
2638 log_warn(LD_GENERAL, "Internal error: unrecognized service ID on "
2639 "rendezvous circuit.");
2640 reason = END_CIRC_REASON_INTERNAL;
2641 goto err;
2644 /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
2645 memcpy(buf, circuit->rend_data->rend_cookie, REND_COOKIE_LEN);
2646 if (crypto_dh_get_public(hop->rend_dh_handshake_state,
2647 buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
2648 log_warn(LD_GENERAL,"Couldn't get DH public key.");
2649 reason = END_CIRC_REASON_INTERNAL;
2650 goto err;
2652 memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->rend_circ_nonce,
2653 DIGEST_LEN);
2655 /* Send the cell */
2656 if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
2657 RELAY_COMMAND_RENDEZVOUS1,
2658 buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
2659 circuit->cpath->prev)<0) {
2660 log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
2661 reason = END_CIRC_REASON_INTERNAL;
2662 goto err;
2665 crypto_dh_free(hop->rend_dh_handshake_state);
2666 hop->rend_dh_handshake_state = NULL;
2668 /* Append the cpath entry. */
2669 hop->state = CPATH_STATE_OPEN;
2670 /* set the windows to default. these are the windows
2671 * that bob thinks alice has.
2673 hop->package_window = circuit_initial_package_window();
2674 hop->deliver_window = CIRCWINDOW_START;
2676 onion_append_to_cpath(&circuit->cpath, hop);
2677 circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
2679 /* Change the circuit purpose. */
2680 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_REND_JOINED);
2682 goto done;
2684 err:
2685 circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
2686 done:
2687 memwipe(buf, 0, sizeof(buf));
2688 memwipe(serviceid, 0, sizeof(serviceid));
2689 memwipe(hexcookie, 0, sizeof(hexcookie));
2691 return;
2695 * Manage introduction points
2698 /** Return the (possibly non-open) introduction circuit ending at
2699 * <b>intro</b> for the service whose public key is <b>pk_digest</b>.
2700 * (<b>desc_version</b> is ignored). Return NULL if no such service is
2701 * found.
2703 static origin_circuit_t *
2704 find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
2706 origin_circuit_t *circ = NULL;
2708 tor_assert(intro);
2709 while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
2710 CIRCUIT_PURPOSE_S_INTRO))) {
2711 if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
2712 intro->extend_info->identity_digest, DIGEST_LEN) &&
2713 circ->rend_data) {
2714 return circ;
2718 circ = NULL;
2719 while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
2720 CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
2721 if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
2722 intro->extend_info->identity_digest, DIGEST_LEN) &&
2723 circ->rend_data) {
2724 return circ;
2727 return NULL;
2730 /** Return a pointer to the rend_intro_point_t corresponding to the
2731 * service-side introduction circuit <b>circ</b>. */
2732 static rend_intro_point_t *
2733 find_intro_point(origin_circuit_t *circ)
2735 const char *serviceid;
2736 rend_service_t *service = NULL;
2738 tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
2739 TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO);
2740 tor_assert(circ->rend_data);
2741 serviceid = circ->rend_data->onion_address;
2743 SMARTLIST_FOREACH(rend_service_list, rend_service_t *, s,
2744 if (tor_memeq(s->service_id, serviceid, REND_SERVICE_ID_LEN_BASE32)) {
2745 service = s;
2746 break;
2749 if (service == NULL) return NULL;
2751 SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro_point,
2752 if (crypto_pk_eq_keys(intro_point->intro_key, circ->intro_key)) {
2753 return intro_point;
2756 return NULL;
2759 /** Determine the responsible hidden service directories for the
2760 * rend_encoded_v2_service_descriptor_t's in <b>descs</b> and upload them;
2761 * <b>service_id</b> and <b>seconds_valid</b> are only passed for logging
2762 * purposes. */
2763 static void
2764 directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
2765 smartlist_t *descs, const char *service_id,
2766 int seconds_valid)
2768 int i, j, failed_upload = 0;
2769 smartlist_t *responsible_dirs = smartlist_new();
2770 smartlist_t *successful_uploads = smartlist_new();
2771 routerstatus_t *hs_dir;
2772 for (i = 0; i < smartlist_len(descs); i++) {
2773 rend_encoded_v2_service_descriptor_t *desc = smartlist_get(descs, i);
2774 /* Determine responsible dirs. */
2775 if (hid_serv_get_responsible_directories(responsible_dirs,
2776 desc->desc_id) < 0) {
2777 log_warn(LD_REND, "Could not determine the responsible hidden service "
2778 "directories to post descriptors to.");
2779 smartlist_free(responsible_dirs);
2780 smartlist_free(successful_uploads);
2781 return;
2783 for (j = 0; j < smartlist_len(responsible_dirs); j++) {
2784 char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
2785 char *hs_dir_ip;
2786 const node_t *node;
2787 hs_dir = smartlist_get(responsible_dirs, j);
2788 if (smartlist_contains_digest(renddesc->successful_uploads,
2789 hs_dir->identity_digest))
2790 /* Don't upload descriptor if we succeeded in doing so last time. */
2791 continue;
2792 node = node_get_by_id(hs_dir->identity_digest);
2793 if (!node || !node_has_descriptor(node)) {
2794 log_info(LD_REND, "Not launching upload for for v2 descriptor to "
2795 "hidden service directory %s; we don't have its "
2796 "router descriptor. Queuing for later upload.",
2797 safe_str_client(routerstatus_describe(hs_dir)));
2798 failed_upload = -1;
2799 continue;
2801 /* Send publish request. */
2802 directory_initiate_command_routerstatus(hs_dir,
2803 DIR_PURPOSE_UPLOAD_RENDDESC_V2,
2804 ROUTER_PURPOSE_GENERAL,
2805 DIRIND_ANONYMOUS, NULL,
2806 desc->desc_str,
2807 strlen(desc->desc_str), 0);
2808 base32_encode(desc_id_base32, sizeof(desc_id_base32),
2809 desc->desc_id, DIGEST_LEN);
2810 hs_dir_ip = tor_dup_ip(hs_dir->addr);
2811 log_info(LD_REND, "Launching upload for v2 descriptor for "
2812 "service '%s' with descriptor ID '%s' with validity "
2813 "of %d seconds to hidden service directory '%s' on "
2814 "%s:%d.",
2815 safe_str_client(service_id),
2816 safe_str_client(desc_id_base32),
2817 seconds_valid,
2818 hs_dir->nickname,
2819 hs_dir_ip,
2820 hs_dir->or_port);
2821 tor_free(hs_dir_ip);
2822 /* Remember successful upload to this router for next time. */
2823 if (!smartlist_contains_digest(successful_uploads,
2824 hs_dir->identity_digest))
2825 smartlist_add(successful_uploads, hs_dir->identity_digest);
2827 smartlist_clear(responsible_dirs);
2829 if (!failed_upload) {
2830 if (renddesc->successful_uploads) {
2831 SMARTLIST_FOREACH(renddesc->successful_uploads, char *, c, tor_free(c););
2832 smartlist_free(renddesc->successful_uploads);
2833 renddesc->successful_uploads = NULL;
2835 renddesc->all_uploads_performed = 1;
2836 } else {
2837 /* Remember which routers worked this time, so that we don't upload the
2838 * descriptor to them again. */
2839 if (!renddesc->successful_uploads)
2840 renddesc->successful_uploads = smartlist_new();
2841 SMARTLIST_FOREACH(successful_uploads, const char *, c, {
2842 if (!smartlist_contains_digest(renddesc->successful_uploads, c)) {
2843 char *hsdir_id = tor_memdup(c, DIGEST_LEN);
2844 smartlist_add(renddesc->successful_uploads, hsdir_id);
2848 smartlist_free(responsible_dirs);
2849 smartlist_free(successful_uploads);
2852 /** Encode and sign an up-to-date service descriptor for <b>service</b>,
2853 * and upload it/them to the responsible hidden service directories.
2855 static void
2856 upload_service_descriptor(rend_service_t *service)
2858 time_t now = time(NULL);
2859 int rendpostperiod;
2860 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2861 int uploaded = 0;
2863 rendpostperiod = get_options()->RendPostPeriod;
2865 /* Upload descriptor? */
2866 if (get_options()->PublishHidServDescriptors) {
2867 networkstatus_t *c = networkstatus_get_latest_consensus();
2868 if (c && smartlist_len(c->routerstatus_list) > 0) {
2869 int seconds_valid, i, j, num_descs;
2870 smartlist_t *descs = smartlist_new();
2871 smartlist_t *client_cookies = smartlist_new();
2872 /* Either upload a single descriptor (including replicas) or one
2873 * descriptor for each authorized client in case of authorization
2874 * type 'stealth'. */
2875 num_descs = service->auth_type == REND_STEALTH_AUTH ?
2876 smartlist_len(service->clients) : 1;
2877 for (j = 0; j < num_descs; j++) {
2878 crypto_pk_t *client_key = NULL;
2879 rend_authorized_client_t *client = NULL;
2880 smartlist_clear(client_cookies);
2881 switch (service->auth_type) {
2882 case REND_NO_AUTH:
2883 /* Do nothing here. */
2884 break;
2885 case REND_BASIC_AUTH:
2886 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *,
2887 cl, smartlist_add(client_cookies, cl->descriptor_cookie));
2888 break;
2889 case REND_STEALTH_AUTH:
2890 client = smartlist_get(service->clients, j);
2891 client_key = client->client_key;
2892 smartlist_add(client_cookies, client->descriptor_cookie);
2893 break;
2895 /* Encode the current descriptor. */
2896 seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
2897 now, 0,
2898 service->auth_type,
2899 client_key,
2900 client_cookies);
2901 if (seconds_valid < 0) {
2902 log_warn(LD_BUG, "Internal error: couldn't encode service "
2903 "descriptor; not uploading.");
2904 smartlist_free(descs);
2905 smartlist_free(client_cookies);
2906 return;
2908 /* Post the current descriptors to the hidden service directories. */
2909 rend_get_service_id(service->desc->pk, serviceid);
2910 log_info(LD_REND, "Launching upload for hidden service %s",
2911 serviceid);
2912 directory_post_to_hs_dir(service->desc, descs, serviceid,
2913 seconds_valid);
2914 /* Free memory for descriptors. */
2915 for (i = 0; i < smartlist_len(descs); i++)
2916 rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
2917 smartlist_clear(descs);
2918 /* Update next upload time. */
2919 if (seconds_valid - REND_TIME_PERIOD_OVERLAPPING_V2_DESCS
2920 > rendpostperiod)
2921 service->next_upload_time = now + rendpostperiod;
2922 else if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS)
2923 service->next_upload_time = now + seconds_valid + 1;
2924 else
2925 service->next_upload_time = now + seconds_valid -
2926 REND_TIME_PERIOD_OVERLAPPING_V2_DESCS + 1;
2927 /* Post also the next descriptors, if necessary. */
2928 if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS) {
2929 seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
2930 now, 1,
2931 service->auth_type,
2932 client_key,
2933 client_cookies);
2934 if (seconds_valid < 0) {
2935 log_warn(LD_BUG, "Internal error: couldn't encode service "
2936 "descriptor; not uploading.");
2937 smartlist_free(descs);
2938 smartlist_free(client_cookies);
2939 return;
2941 directory_post_to_hs_dir(service->desc, descs, serviceid,
2942 seconds_valid);
2943 /* Free memory for descriptors. */
2944 for (i = 0; i < smartlist_len(descs); i++)
2945 rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
2946 smartlist_clear(descs);
2949 smartlist_free(descs);
2950 smartlist_free(client_cookies);
2951 uploaded = 1;
2952 log_info(LD_REND, "Successfully uploaded v2 rend descriptors!");
2956 /* If not uploaded, try again in one minute. */
2957 if (!uploaded)
2958 service->next_upload_time = now + 60;
2960 /* Unmark dirty flag of this service. */
2961 service->desc_is_dirty = 0;
2964 /** Return the number of INTRODUCE2 cells this hidden service has received
2965 * from this intro point. */
2966 static int
2967 intro_point_accepted_intro_count(rend_intro_point_t *intro)
2969 return intro->accepted_introduce2_count;
2972 /** Return non-zero iff <b>intro</b> should 'expire' now (i.e. we
2973 * should stop publishing it in new descriptors and eventually close
2974 * it). */
2975 static int
2976 intro_point_should_expire_now(rend_intro_point_t *intro,
2977 time_t now)
2979 tor_assert(intro != NULL);
2981 if (intro->time_published == -1) {
2982 /* Don't expire an intro point if we haven't even published it yet. */
2983 return 0;
2986 if (intro->time_expiring != -1) {
2987 /* We've already started expiring this intro point. *Don't* let
2988 * this function's result 'flap'. */
2989 return 1;
2992 if (intro_point_accepted_intro_count(intro) >=
2993 INTRO_POINT_LIFETIME_INTRODUCTIONS) {
2994 /* This intro point has been used too many times. Expire it now. */
2995 return 1;
2998 if (intro->time_to_expire == -1) {
2999 /* This intro point has been published, but we haven't picked an
3000 * expiration time for it. Pick one now. */
3001 int intro_point_lifetime_seconds =
3002 INTRO_POINT_LIFETIME_MIN_SECONDS +
3003 crypto_rand_int(INTRO_POINT_LIFETIME_MAX_SECONDS -
3004 INTRO_POINT_LIFETIME_MIN_SECONDS);
3006 /* Start the expiration timer now, rather than when the intro
3007 * point was first published. There shouldn't be much of a time
3008 * difference. */
3009 intro->time_to_expire = now + intro_point_lifetime_seconds;
3011 return 0;
3014 /* This intro point has a time to expire set already. Use it. */
3015 return (now >= intro->time_to_expire);
3018 /** For every service, check how many intro points it currently has, and:
3019 * - Pick new intro points as necessary.
3020 * - Launch circuits to any new intro points.
3022 void
3023 rend_services_introduce(void)
3025 int i,j,r;
3026 const node_t *node;
3027 rend_service_t *service;
3028 rend_intro_point_t *intro;
3029 int intro_point_set_changed, prev_intro_nodes;
3030 unsigned int n_intro_points_unexpired;
3031 unsigned int n_intro_points_to_open;
3032 smartlist_t *intro_nodes;
3033 time_t now;
3034 const or_options_t *options = get_options();
3036 intro_nodes = smartlist_new();
3037 now = time(NULL);
3039 for (i=0; i < smartlist_len(rend_service_list); ++i) {
3040 smartlist_clear(intro_nodes);
3041 service = smartlist_get(rend_service_list, i);
3043 tor_assert(service);
3045 /* intro_point_set_changed becomes non-zero iff the set of intro
3046 * points to be published in service's descriptor has changed. */
3047 intro_point_set_changed = 0;
3049 /* n_intro_points_unexpired collects the number of non-expiring
3050 * intro points we have, so that we know how many new intro
3051 * circuits we need to launch for this service. */
3052 n_intro_points_unexpired = 0;
3054 if (now > service->intro_period_started+INTRO_CIRC_RETRY_PERIOD) {
3055 /* One period has elapsed; we can try building circuits again. */
3056 service->intro_period_started = now;
3057 service->n_intro_circuits_launched = 0;
3058 } else if (service->n_intro_circuits_launched >=
3059 MAX_INTRO_CIRCS_PER_PERIOD) {
3060 /* We have failed too many times in this period; wait for the next
3061 * one before we try again. */
3062 continue;
3065 /* Find out which introduction points we have in progress for this
3066 service. */
3067 SMARTLIST_FOREACH_BEGIN(service->intro_nodes, rend_intro_point_t *,
3068 intro) {
3069 origin_circuit_t *intro_circ =
3070 find_intro_circuit(intro, service->pk_digest);
3072 if (intro->time_expiring + INTRO_POINT_EXPIRATION_GRACE_PERIOD > now) {
3073 /* This intro point has completely expired. Remove it, and
3074 * mark the circuit for close if it's still alive. */
3075 if (intro_circ != NULL &&
3076 intro_circ->base_.purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
3077 circuit_mark_for_close(TO_CIRCUIT(intro_circ),
3078 END_CIRC_REASON_FINISHED);
3080 rend_intro_point_free(intro);
3081 intro = NULL; /* SMARTLIST_DEL_CURRENT takes a name, not a value. */
3082 SMARTLIST_DEL_CURRENT(service->intro_nodes, intro);
3083 /* We don't need to set intro_point_set_changed here, because
3084 * this intro point wouldn't have been published in a current
3085 * descriptor anyway. */
3086 continue;
3089 node = node_get_by_id(intro->extend_info->identity_digest);
3090 if (!node || !intro_circ) {
3091 int removing_this_intro_point_changes_the_intro_point_set = 1;
3092 log_info(LD_REND, "Giving up on %s as intro point for %s"
3093 " (circuit disappeared).",
3094 safe_str_client(extend_info_describe(intro->extend_info)),
3095 safe_str_client(service->service_id));
3096 rend_service_note_removing_intro_point(service, intro);
3097 if (intro->time_expiring != -1) {
3098 log_info(LD_REND, "We were already expiring the intro point; "
3099 "no need to mark the HS descriptor as dirty over this.");
3100 removing_this_intro_point_changes_the_intro_point_set = 0;
3101 } else if (intro->listed_in_last_desc) {
3102 log_info(LD_REND, "The intro point we are giving up on was "
3103 "included in the last published descriptor. "
3104 "Marking current descriptor as dirty.");
3105 service->desc_is_dirty = now;
3107 rend_intro_point_free(intro);
3108 intro = NULL; /* SMARTLIST_DEL_CURRENT takes a name, not a value. */
3109 SMARTLIST_DEL_CURRENT(service->intro_nodes, intro);
3110 if (removing_this_intro_point_changes_the_intro_point_set)
3111 intro_point_set_changed = 1;
3114 if (intro != NULL && intro_point_should_expire_now(intro, now)) {
3115 log_info(LD_REND, "Expiring %s as intro point for %s.",
3116 safe_str_client(extend_info_describe(intro->extend_info)),
3117 safe_str_client(service->service_id));
3119 rend_service_note_removing_intro_point(service, intro);
3121 /* The polite (and generally Right) way to expire an intro
3122 * point is to establish a new one to replace it, publish a
3123 * new descriptor that doesn't list any expiring intro points,
3124 * and *then*, once our upload attempts for the new descriptor
3125 * have ended (whether in success or failure), close the
3126 * expiring intro points.
3128 * Unfortunately, we can't find out when the new descriptor
3129 * has actually been uploaded, so we'll have to settle for a
3130 * five-minute timer. Start it. XXXX024 This sucks. */
3131 intro->time_expiring = now;
3133 intro_point_set_changed = 1;
3136 if (intro != NULL && intro->time_expiring == -1)
3137 ++n_intro_points_unexpired;
3139 if (node)
3140 smartlist_add(intro_nodes, (void*)node);
3141 } SMARTLIST_FOREACH_END(intro);
3143 if (!intro_point_set_changed &&
3144 (n_intro_points_unexpired >= service->n_intro_points_wanted)) {
3145 continue;
3148 /* Remember how many introduction circuits we started with.
3150 * prev_intro_nodes serves a different purpose than
3151 * n_intro_points_unexpired -- this variable tells us where our
3152 * previously-created intro points end and our new ones begin in
3153 * the intro-point list, so we don't have to launch the circuits
3154 * at the same time as we create the intro points they correspond
3155 * to. XXXX This is daft. */
3156 prev_intro_nodes = smartlist_len(service->intro_nodes);
3158 /* We have enough directory information to start establishing our
3159 * intro points. We want to end up with n_intro_points_wanted
3160 * intro points, but if we're just starting, we launch two extra
3161 * circuits and use the first n_intro_points_wanted that complete.
3163 * The ones after the first three will be converted to 'general'
3164 * internal circuits in rend_service_intro_has_opened(), and then
3165 * we'll drop them from the list of intro points next time we
3166 * go through the above "find out which introduction points we have
3167 * in progress" loop. */
3168 n_intro_points_to_open = (service->n_intro_points_wanted +
3169 (prev_intro_nodes == 0 ? 2 : 0));
3170 for (j = (int)n_intro_points_unexpired;
3171 j < (int)n_intro_points_to_open;
3172 ++j) { /* XXXX remove casts */
3173 router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
3174 if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION)
3175 flags |= CRN_ALLOW_INVALID;
3176 node = router_choose_random_node(intro_nodes,
3177 options->ExcludeNodes, flags);
3178 if (!node) {
3179 log_warn(LD_REND,
3180 "Could only establish %d introduction points for %s; "
3181 "wanted %u.",
3182 smartlist_len(service->intro_nodes), service->service_id,
3183 n_intro_points_to_open);
3184 break;
3186 intro_point_set_changed = 1;
3187 smartlist_add(intro_nodes, (void*)node);
3188 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
3189 intro->extend_info = extend_info_from_node(node, 0);
3190 intro->intro_key = crypto_pk_new();
3191 tor_assert(!crypto_pk_generate_key(intro->intro_key));
3192 intro->time_published = -1;
3193 intro->time_to_expire = -1;
3194 intro->time_expiring = -1;
3195 smartlist_add(service->intro_nodes, intro);
3196 log_info(LD_REND, "Picked router %s as an intro point for %s.",
3197 safe_str_client(node_describe(node)),
3198 safe_str_client(service->service_id));
3201 /* If there's no need to launch new circuits, stop here. */
3202 if (!intro_point_set_changed)
3203 continue;
3205 /* Establish new introduction points. */
3206 for (j=prev_intro_nodes; j < smartlist_len(service->intro_nodes); ++j) {
3207 intro = smartlist_get(service->intro_nodes, j);
3208 r = rend_service_launch_establish_intro(service, intro);
3209 if (r<0) {
3210 log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
3211 safe_str_client(extend_info_describe(intro->extend_info)),
3212 safe_str_client(service->service_id));
3216 smartlist_free(intro_nodes);
3219 /** Regenerate and upload rendezvous service descriptors for all
3220 * services, if necessary. If the descriptor has been dirty enough
3221 * for long enough, definitely upload; else only upload when the
3222 * periodic timeout has expired.
3224 * For the first upload, pick a random time between now and two periods
3225 * from now, and pick it independently for each service.
3227 void
3228 rend_consider_services_upload(time_t now)
3230 int i;
3231 rend_service_t *service;
3232 int rendpostperiod = get_options()->RendPostPeriod;
3234 if (!get_options()->PublishHidServDescriptors)
3235 return;
3237 for (i=0; i < smartlist_len(rend_service_list); ++i) {
3238 service = smartlist_get(rend_service_list, i);
3239 if (!service->next_upload_time) { /* never been uploaded yet */
3240 /* The fixed lower bound of 30 seconds ensures that the descriptor
3241 * is stable before being published. See comment below. */
3242 service->next_upload_time =
3243 now + 30 + crypto_rand_int(2*rendpostperiod);
3245 if (service->next_upload_time < now ||
3246 (service->desc_is_dirty &&
3247 service->desc_is_dirty < now-30)) {
3248 /* if it's time, or if the directory servers have a wrong service
3249 * descriptor and ours has been stable for 30 seconds, upload a
3250 * new one of each format. */
3251 rend_service_update_descriptor(service);
3252 upload_service_descriptor(service);
3257 /** True if the list of available router descriptors might have changed so
3258 * that we should have a look whether we can republish previously failed
3259 * rendezvous service descriptors. */
3260 static int consider_republishing_rend_descriptors = 1;
3262 /** Called when our internal view of the directory has changed, so that we
3263 * might have router descriptors of hidden service directories available that
3264 * we did not have before. */
3265 void
3266 rend_hsdir_routers_changed(void)
3268 consider_republishing_rend_descriptors = 1;
3271 /** Consider republication of v2 rendezvous service descriptors that failed
3272 * previously, but without regenerating descriptor contents.
3274 void
3275 rend_consider_descriptor_republication(void)
3277 int i;
3278 rend_service_t *service;
3280 if (!consider_republishing_rend_descriptors)
3281 return;
3282 consider_republishing_rend_descriptors = 0;
3284 if (!get_options()->PublishHidServDescriptors)
3285 return;
3287 for (i=0; i < smartlist_len(rend_service_list); ++i) {
3288 service = smartlist_get(rend_service_list, i);
3289 if (service->desc && !service->desc->all_uploads_performed) {
3290 /* If we failed in uploading a descriptor last time, try again *without*
3291 * updating the descriptor's contents. */
3292 upload_service_descriptor(service);
3297 /** Log the status of introduction points for all rendezvous services
3298 * at log severity <b>severity</b>.
3300 void
3301 rend_service_dump_stats(int severity)
3303 int i,j;
3304 rend_service_t *service;
3305 rend_intro_point_t *intro;
3306 const char *safe_name;
3307 origin_circuit_t *circ;
3309 for (i=0; i < smartlist_len(rend_service_list); ++i) {
3310 service = smartlist_get(rend_service_list, i);
3311 tor_log(severity, LD_GENERAL, "Service configured in \"%s\":",
3312 service->directory);
3313 for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
3314 intro = smartlist_get(service->intro_nodes, j);
3315 safe_name = safe_str_client(intro->extend_info->nickname);
3317 circ = find_intro_circuit(intro, service->pk_digest);
3318 if (!circ) {
3319 tor_log(severity, LD_GENERAL, " Intro point %d at %s: no circuit",
3320 j, safe_name);
3321 continue;
3323 tor_log(severity, LD_GENERAL, " Intro point %d at %s: circuit is %s",
3324 j, safe_name, circuit_state_to_string(circ->base_.state));
3329 /** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
3330 * 'circ', and look up the port and address based on conn-\>port.
3331 * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
3332 * or 0 for success.
3335 rend_service_set_connection_addr_port(edge_connection_t *conn,
3336 origin_circuit_t *circ)
3338 rend_service_t *service;
3339 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
3340 smartlist_t *matching_ports;
3341 rend_service_port_config_t *chosen_port;
3343 tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
3344 tor_assert(circ->rend_data);
3345 log_debug(LD_REND,"beginning to hunt for addr/port");
3346 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
3347 circ->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
3348 service = rend_service_get_by_pk_digest(
3349 circ->rend_data->rend_pk_digest);
3350 if (!service) {
3351 log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
3352 "rendezvous circuit %u; closing.",
3353 serviceid, (unsigned)circ->base_.n_circ_id);
3354 return -1;
3356 matching_ports = smartlist_new();
3357 SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
3359 if (conn->base_.port == p->virtual_port) {
3360 smartlist_add(matching_ports, p);
3363 chosen_port = smartlist_choose(matching_ports);
3364 smartlist_free(matching_ports);
3365 if (chosen_port) {
3366 tor_addr_copy(&conn->base_.addr, &chosen_port->real_addr);
3367 conn->base_.port = chosen_port->real_port;
3368 return 0;
3370 log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
3371 conn->base_.port,serviceid);
3372 return -1;