Merge remote-tracking branch 'origin/maint-0.2.4'
[tor.git] / src / or / rendservice.c
blob0c52552f679e711629e8fd72259c478d7d9b74c8
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 "circuitbuild.h"
14 #include "circuitlist.h"
15 #include "circuituse.h"
16 #include "config.h"
17 #include "directory.h"
18 #include "networkstatus.h"
19 #include "nodelist.h"
20 #include "rendclient.h"
21 #include "rendcommon.h"
22 #include "rendservice.h"
23 #include "router.h"
24 #include "relay.h"
25 #include "rephist.h"
26 #include "replaycache.h"
27 #include "routerlist.h"
28 #include "routerparse.h"
29 #include "routerset.h"
31 static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro,
32 const char *pk_digest);
33 static rend_intro_point_t *find_intro_point(origin_circuit_t *circ);
35 static extend_info_t *find_rp_for_intro(
36 const rend_intro_cell_t *intro,
37 uint8_t *need_free_out, char **err_msg_out);
39 static int intro_point_accepted_intro_count(rend_intro_point_t *intro);
40 static int intro_point_should_expire_now(rend_intro_point_t *intro,
41 time_t now);
42 struct rend_service_t;
43 static int rend_service_load_keys(struct rend_service_t *s);
44 static int rend_service_load_auth_keys(struct rend_service_t *s,
45 const char *hfname);
47 static ssize_t rend_service_parse_intro_for_v0_or_v1(
48 rend_intro_cell_t *intro,
49 const uint8_t *buf,
50 size_t plaintext_len,
51 char **err_msg_out);
52 static ssize_t rend_service_parse_intro_for_v2(
53 rend_intro_cell_t *intro,
54 const uint8_t *buf,
55 size_t plaintext_len,
56 char **err_msg_out);
57 static ssize_t rend_service_parse_intro_for_v3(
58 rend_intro_cell_t *intro,
59 const uint8_t *buf,
60 size_t plaintext_len,
61 char **err_msg_out);
63 /** Represents the mapping from a virtual port of a rendezvous service to
64 * a real port on some IP.
66 typedef struct rend_service_port_config_t {
67 uint16_t virtual_port;
68 uint16_t real_port;
69 tor_addr_t real_addr;
70 } rend_service_port_config_t;
72 /** Try to maintain this many intro points per service by default. */
73 #define NUM_INTRO_POINTS_DEFAULT 3
74 /** Maintain no more than this many intro points per hidden service. */
75 #define NUM_INTRO_POINTS_MAX 10
77 /** If we can't build our intro circuits, don't retry for this long. */
78 #define INTRO_CIRC_RETRY_PERIOD (60*5)
79 /** Don't try to build more than this many circuits before giving up
80 * for a while.*/
81 #define MAX_INTRO_CIRCS_PER_PERIOD 10
82 /** How many times will a hidden service operator attempt to connect to
83 * a requested rendezvous point before giving up? */
84 #define MAX_REND_FAILURES 30
85 /** How many seconds should we spend trying to connect to a requested
86 * rendezvous point before giving up? */
87 #define MAX_REND_TIMEOUT 30
89 /** How many seconds should we wait for new HS descriptors to reach
90 * our clients before we close an expiring intro point? */
91 #define INTRO_POINT_EXPIRATION_GRACE_PERIOD (5*60)
93 /** Represents a single hidden service running at this OP. */
94 typedef struct rend_service_t {
95 /* Fields specified in config file */
96 char *directory; /**< where in the filesystem it stores it */
97 smartlist_t *ports; /**< List of rend_service_port_config_t */
98 rend_auth_type_t auth_type; /**< Client authorization type or 0 if no client
99 * authorization is performed. */
100 smartlist_t *clients; /**< List of rend_authorized_client_t's of
101 * clients that may access our service. Can be NULL
102 * if no client authorization is performed. */
103 /* Other fields */
104 crypto_pk_t *private_key; /**< Permanent hidden-service key. */
105 char service_id[REND_SERVICE_ID_LEN_BASE32+1]; /**< Onion address without
106 * '.onion' */
107 char pk_digest[DIGEST_LEN]; /**< Hash of permanent hidden-service key. */
108 smartlist_t *intro_nodes; /**< List of rend_intro_point_t's we have,
109 * or are trying to establish. */
110 time_t intro_period_started; /**< Start of the current period to build
111 * introduction points. */
112 int n_intro_circuits_launched; /**< Count of intro circuits we have
113 * established in this period. */
114 unsigned int n_intro_points_wanted; /**< Number of intro points this
115 * service wants to have open. */
116 rend_service_descriptor_t *desc; /**< Current hidden service descriptor. */
117 time_t desc_is_dirty; /**< Time at which changes to the hidden service
118 * descriptor content occurred, or 0 if it's
119 * up-to-date. */
120 time_t next_upload_time; /**< Scheduled next hidden service descriptor
121 * upload time. */
122 /** Replay cache for Diffie-Hellman values of INTRODUCE2 cells, to
123 * detect repeats. Clients may send INTRODUCE1 cells for the same
124 * rendezvous point through two or more different introduction points;
125 * when they do, this keeps us from launching multiple simultaneous attempts
126 * to connect to the same rend point. */
127 replaycache_t *accepted_intro_dh_parts;
128 } rend_service_t;
130 /** A list of rend_service_t's for services run on this OP.
132 static smartlist_t *rend_service_list = NULL;
134 /** Return the number of rendezvous services we have configured. */
136 num_rend_services(void)
138 if (!rend_service_list)
139 return 0;
140 return smartlist_len(rend_service_list);
143 /** Return a string identifying <b>service</b>, suitable for use in a
144 * log message. The result does not need to be freed, but may be
145 * overwritten by the next call to this function. */
146 static const char *
147 rend_service_describe_for_log(rend_service_t *service)
149 /* XXX024 Use this function throughout rendservice.c. */
150 /* XXX024 Return a more useful description? */
151 return safe_str_client(service->service_id);
154 /** Helper: free storage held by a single service authorized client entry. */
155 static void
156 rend_authorized_client_free(rend_authorized_client_t *client)
158 if (!client)
159 return;
160 if (client->client_key)
161 crypto_pk_free(client->client_key);
162 tor_strclear(client->client_name);
163 tor_free(client->client_name);
164 memwipe(client->descriptor_cookie, 0, sizeof(client->descriptor_cookie));
165 tor_free(client);
168 /** Helper for strmap_free. */
169 static void
170 rend_authorized_client_strmap_item_free(void *authorized_client)
172 rend_authorized_client_free(authorized_client);
175 /** Release the storage held by <b>service</b>.
177 static void
178 rend_service_free(rend_service_t *service)
180 if (!service)
181 return;
183 tor_free(service->directory);
184 SMARTLIST_FOREACH(service->ports, void*, p, tor_free(p));
185 smartlist_free(service->ports);
186 if (service->private_key)
187 crypto_pk_free(service->private_key);
188 if (service->intro_nodes) {
189 SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro,
190 rend_intro_point_free(intro););
191 smartlist_free(service->intro_nodes);
194 rend_service_descriptor_free(service->desc);
195 if (service->clients) {
196 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, c,
197 rend_authorized_client_free(c););
198 smartlist_free(service->clients);
200 if (service->accepted_intro_dh_parts) {
201 replaycache_free(service->accepted_intro_dh_parts);
203 tor_free(service);
206 /** Release all the storage held in rend_service_list.
208 void
209 rend_service_free_all(void)
211 if (!rend_service_list)
212 return;
214 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
215 rend_service_free(ptr));
216 smartlist_free(rend_service_list);
217 rend_service_list = NULL;
220 /** Validate <b>service</b> and add it to rend_service_list if possible.
222 static void
223 rend_add_service(rend_service_t *service)
225 int i;
226 rend_service_port_config_t *p;
228 service->intro_nodes = smartlist_new();
230 if (service->auth_type != REND_NO_AUTH &&
231 smartlist_len(service->clients) == 0) {
232 log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no "
233 "clients; ignoring.",
234 escaped(service->directory));
235 rend_service_free(service);
236 return;
239 if (!smartlist_len(service->ports)) {
240 log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured; "
241 "ignoring.",
242 escaped(service->directory));
243 rend_service_free(service);
244 } else {
245 int dupe = 0;
246 /* XXX This duplicate check has two problems:
248 * a) It's O(n^2), but the same comment from the bottom of
249 * rend_config_services() should apply.
251 * b) We only compare directory paths as strings, so we can't
252 * detect two distinct paths that specify the same directory
253 * (which can arise from symlinks, case-insensitivity, bind
254 * mounts, etc.).
256 * It also can't detect that two separate Tor instances are trying
257 * to use the same HiddenServiceDir; for that, we would need a
258 * lock file. But this is enough to detect a simple mistake that
259 * at least one person has actually made.
261 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
262 dupe = dupe ||
263 !strcmp(ptr->directory, service->directory));
264 if (dupe) {
265 log_warn(LD_REND, "Another hidden service is already configured for "
266 "directory %s, ignoring.", service->directory);
267 rend_service_free(service);
268 return;
270 smartlist_add(rend_service_list, service);
271 log_debug(LD_REND,"Configuring service with directory \"%s\"",
272 service->directory);
273 for (i = 0; i < smartlist_len(service->ports); ++i) {
274 p = smartlist_get(service->ports, i);
275 log_debug(LD_REND,"Service maps port %d to %s",
276 p->virtual_port, fmt_addrport(&p->real_addr, p->real_port));
281 /** Parses a real-port to virtual-port mapping and returns a new
282 * rend_service_port_config_t.
284 * The format is: VirtualPort (IP|RealPort|IP:RealPort)?
286 * IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
288 static rend_service_port_config_t *
289 parse_port_config(const char *string)
291 smartlist_t *sl;
292 int virtport;
293 int realport;
294 uint16_t p;
295 tor_addr_t addr;
296 const char *addrport;
297 rend_service_port_config_t *result = NULL;
299 sl = smartlist_new();
300 smartlist_split_string(sl, string, " ",
301 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
302 if (smartlist_len(sl) < 1 || smartlist_len(sl) > 2) {
303 log_warn(LD_CONFIG, "Bad syntax in hidden service port configuration.");
304 goto err;
307 virtport = (int)tor_parse_long(smartlist_get(sl,0), 10, 1, 65535, NULL,NULL);
308 if (!virtport) {
309 log_warn(LD_CONFIG, "Missing or invalid port %s in hidden service port "
310 "configuration", escaped(smartlist_get(sl,0)));
311 goto err;
314 if (smartlist_len(sl) == 1) {
315 /* No addr:port part; use default. */
316 realport = virtport;
317 tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */
318 } else {
319 addrport = smartlist_get(sl,1);
320 if (strchr(addrport, ':') || strchr(addrport, '.')) {
321 if (tor_addr_port_lookup(addrport, &addr, &p)<0) {
322 log_warn(LD_CONFIG,"Unparseable address in hidden service port "
323 "configuration.");
324 goto err;
326 realport = p?p:virtport;
327 } else {
328 /* No addr:port, no addr -- must be port. */
329 realport = (int)tor_parse_long(addrport, 10, 1, 65535, NULL, NULL);
330 if (!realport) {
331 log_warn(LD_CONFIG,"Unparseable or out-of-range port %s in hidden "
332 "service port configuration.", escaped(addrport));
333 goto err;
335 tor_addr_from_ipv4h(&addr, 0x7F000001u); /* Default to 127.0.0.1 */
339 result = tor_malloc(sizeof(rend_service_port_config_t));
340 result->virtual_port = virtport;
341 result->real_port = realport;
342 tor_addr_copy(&result->real_addr, &addr);
343 err:
344 SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
345 smartlist_free(sl);
346 return result;
349 /** Set up rend_service_list, based on the values of HiddenServiceDir and
350 * HiddenServicePort in <b>options</b>. Return 0 on success and -1 on
351 * failure. (If <b>validate_only</b> is set, parse, warn and return as
352 * normal, but don't actually change the configured services.)
355 rend_config_services(const or_options_t *options, int validate_only)
357 config_line_t *line;
358 rend_service_t *service = NULL;
359 rend_service_port_config_t *portcfg;
360 smartlist_t *old_service_list = NULL;
362 if (!validate_only) {
363 old_service_list = rend_service_list;
364 rend_service_list = smartlist_new();
367 for (line = options->RendConfigLines; line; line = line->next) {
368 if (!strcasecmp(line->key, "HiddenServiceDir")) {
369 if (service) { /* register the one we just finished parsing */
370 if (validate_only)
371 rend_service_free(service);
372 else
373 rend_add_service(service);
375 service = tor_malloc_zero(sizeof(rend_service_t));
376 service->directory = tor_strdup(line->value);
377 service->ports = smartlist_new();
378 service->intro_period_started = time(NULL);
379 service->n_intro_points_wanted = NUM_INTRO_POINTS_DEFAULT;
380 continue;
382 if (!service) {
383 log_warn(LD_CONFIG, "%s with no preceding HiddenServiceDir directive",
384 line->key);
385 rend_service_free(service);
386 return -1;
388 if (!strcasecmp(line->key, "HiddenServicePort")) {
389 portcfg = parse_port_config(line->value);
390 if (!portcfg) {
391 rend_service_free(service);
392 return -1;
394 smartlist_add(service->ports, portcfg);
395 } else if (!strcasecmp(line->key, "HiddenServiceAuthorizeClient")) {
396 /* Parse auth type and comma-separated list of client names and add a
397 * rend_authorized_client_t for each client to the service's list
398 * of authorized clients. */
399 smartlist_t *type_names_split, *clients;
400 const char *authname;
401 int num_clients;
402 if (service->auth_type != REND_NO_AUTH) {
403 log_warn(LD_CONFIG, "Got multiple HiddenServiceAuthorizeClient "
404 "lines for a single service.");
405 rend_service_free(service);
406 return -1;
408 type_names_split = smartlist_new();
409 smartlist_split_string(type_names_split, line->value, " ", 0, 2);
410 if (smartlist_len(type_names_split) < 1) {
411 log_warn(LD_BUG, "HiddenServiceAuthorizeClient has no value. This "
412 "should have been prevented when parsing the "
413 "configuration.");
414 smartlist_free(type_names_split);
415 rend_service_free(service);
416 return -1;
418 authname = smartlist_get(type_names_split, 0);
419 if (!strcasecmp(authname, "basic")) {
420 service->auth_type = REND_BASIC_AUTH;
421 } else if (!strcasecmp(authname, "stealth")) {
422 service->auth_type = REND_STEALTH_AUTH;
423 } else {
424 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
425 "unrecognized auth-type '%s'. Only 'basic' or 'stealth' "
426 "are recognized.",
427 (char *) smartlist_get(type_names_split, 0));
428 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
429 smartlist_free(type_names_split);
430 rend_service_free(service);
431 return -1;
433 service->clients = smartlist_new();
434 if (smartlist_len(type_names_split) < 2) {
435 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
436 "auth-type '%s', but no client names.",
437 service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth");
438 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
439 smartlist_free(type_names_split);
440 continue;
442 clients = smartlist_new();
443 smartlist_split_string(clients, smartlist_get(type_names_split, 1),
444 ",", SPLIT_SKIP_SPACE, 0);
445 SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
446 smartlist_free(type_names_split);
447 /* Remove duplicate client names. */
448 num_clients = smartlist_len(clients);
449 smartlist_sort_strings(clients);
450 smartlist_uniq_strings(clients);
451 if (smartlist_len(clients) < num_clients) {
452 log_info(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
453 "duplicate client name(s); removing.",
454 num_clients - smartlist_len(clients));
455 num_clients = smartlist_len(clients);
457 SMARTLIST_FOREACH_BEGIN(clients, const char *, client_name)
459 rend_authorized_client_t *client;
460 size_t len = strlen(client_name);
461 if (len < 1 || len > REND_CLIENTNAME_MAX_LEN) {
462 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
463 "illegal client name: '%s'. Length must be "
464 "between 1 and %d characters.",
465 client_name, REND_CLIENTNAME_MAX_LEN);
466 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
467 smartlist_free(clients);
468 rend_service_free(service);
469 return -1;
471 if (strspn(client_name, REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
472 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
473 "illegal client name: '%s'. Valid "
474 "characters are [A-Za-z0-9+_-].",
475 client_name);
476 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
477 smartlist_free(clients);
478 rend_service_free(service);
479 return -1;
481 client = tor_malloc_zero(sizeof(rend_authorized_client_t));
482 client->client_name = tor_strdup(client_name);
483 smartlist_add(service->clients, client);
484 log_debug(LD_REND, "Adding client name '%s'", client_name);
486 SMARTLIST_FOREACH_END(client_name);
487 SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
488 smartlist_free(clients);
489 /* Ensure maximum number of clients. */
490 if ((service->auth_type == REND_BASIC_AUTH &&
491 smartlist_len(service->clients) > 512) ||
492 (service->auth_type == REND_STEALTH_AUTH &&
493 smartlist_len(service->clients) > 16)) {
494 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
495 "client authorization entries, but only a "
496 "maximum of %d entries is allowed for "
497 "authorization type '%s'.",
498 smartlist_len(service->clients),
499 service->auth_type == REND_BASIC_AUTH ? 512 : 16,
500 service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth");
501 rend_service_free(service);
502 return -1;
504 } else {
505 tor_assert(!strcasecmp(line->key, "HiddenServiceVersion"));
506 if (strcmp(line->value, "2")) {
507 log_warn(LD_CONFIG,
508 "The only supported HiddenServiceVersion is 2.");
509 rend_service_free(service);
510 return -1;
514 if (service) {
515 if (validate_only)
516 rend_service_free(service);
517 else
518 rend_add_service(service);
521 /* If this is a reload and there were hidden services configured before,
522 * keep the introduction points that are still needed and close the
523 * other ones. */
524 if (old_service_list && !validate_only) {
525 smartlist_t *surviving_services = smartlist_new();
526 circuit_t *circ;
528 /* Copy introduction points to new services. */
529 /* XXXX This is O(n^2), but it's only called on reconfigure, so it's
530 * probably ok? */
531 SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, new) {
532 SMARTLIST_FOREACH_BEGIN(old_service_list, rend_service_t *, old) {
533 if (!strcmp(old->directory, new->directory)) {
534 smartlist_add_all(new->intro_nodes, old->intro_nodes);
535 smartlist_clear(old->intro_nodes);
536 smartlist_add(surviving_services, old);
537 break;
539 } SMARTLIST_FOREACH_END(old);
540 } SMARTLIST_FOREACH_END(new);
542 /* Close introduction circuits of services we don't serve anymore. */
543 /* XXXX it would be nicer if we had a nicer abstraction to use here,
544 * so we could just iterate over the list of services to close, but
545 * once again, this isn't critical-path code. */
546 TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) {
547 if (!circ->marked_for_close &&
548 circ->state == CIRCUIT_STATE_OPEN &&
549 (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
550 circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
551 origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
552 int keep_it = 0;
553 tor_assert(oc->rend_data);
554 SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
555 if (tor_memeq(ptr->pk_digest, oc->rend_data->rend_pk_digest,
556 DIGEST_LEN)) {
557 keep_it = 1;
558 break;
561 if (keep_it)
562 continue;
563 log_info(LD_REND, "Closing intro point %s for service %s.",
564 safe_str_client(extend_info_describe(
565 oc->build_state->chosen_exit)),
566 oc->rend_data->onion_address);
567 circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
568 /* XXXX Is there another reason we should use here? */
571 smartlist_free(surviving_services);
572 SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr,
573 rend_service_free(ptr));
574 smartlist_free(old_service_list);
577 return 0;
580 /** Replace the old value of <b>service</b>-\>desc with one that reflects
581 * the other fields in service.
583 static void
584 rend_service_update_descriptor(rend_service_t *service)
586 rend_service_descriptor_t *d;
587 origin_circuit_t *circ;
588 int i;
590 rend_service_descriptor_free(service->desc);
591 service->desc = NULL;
593 d = service->desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
594 d->pk = crypto_pk_dup_key(service->private_key);
595 d->timestamp = time(NULL);
596 d->timestamp -= d->timestamp % 3600; /* Round down to nearest hour */
597 d->intro_nodes = smartlist_new();
598 /* Support intro protocols 2 and 3. */
599 d->protocols = (1 << 2) + (1 << 3);
601 for (i = 0; i < smartlist_len(service->intro_nodes); ++i) {
602 rend_intro_point_t *intro_svc = smartlist_get(service->intro_nodes, i);
603 rend_intro_point_t *intro_desc;
605 /* This intro point won't be listed in the descriptor... */
606 intro_svc->listed_in_last_desc = 0;
608 if (intro_svc->time_expiring != -1) {
609 /* This intro point is expiring. Don't list it. */
610 continue;
613 circ = find_intro_circuit(intro_svc, service->pk_digest);
614 if (!circ || circ->base_.purpose != CIRCUIT_PURPOSE_S_INTRO) {
615 /* This intro point's circuit isn't finished yet. Don't list it. */
616 continue;
619 /* ...unless this intro point is listed in the descriptor. */
620 intro_svc->listed_in_last_desc = 1;
622 /* We have an entirely established intro circuit. Publish it in
623 * our descriptor. */
624 intro_desc = tor_malloc_zero(sizeof(rend_intro_point_t));
625 intro_desc->extend_info = extend_info_dup(intro_svc->extend_info);
626 if (intro_svc->intro_key)
627 intro_desc->intro_key = crypto_pk_dup_key(intro_svc->intro_key);
628 smartlist_add(d->intro_nodes, intro_desc);
630 if (intro_svc->time_published == -1) {
631 /* We are publishing this intro point in a descriptor for the
632 * first time -- note the current time in the service's copy of
633 * the intro point. */
634 intro_svc->time_published = time(NULL);
639 /** Load and/or generate private keys for all hidden services, possibly
640 * including keys for client authorization. Return 0 on success, -1 on
641 * failure. */
643 rend_service_load_all_keys(void)
645 SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, s) {
646 if (s->private_key)
647 continue;
648 log_info(LD_REND, "Loading hidden-service keys from \"%s\"",
649 s->directory);
651 if (rend_service_load_keys(s) < 0)
652 return -1;
653 } SMARTLIST_FOREACH_END(s);
655 return 0;
658 /** Load and/or generate private keys for the hidden service <b>s</b>,
659 * possibly including keys for client authorization. Return 0 on success, -1
660 * on failure. */
661 static int
662 rend_service_load_keys(rend_service_t *s)
664 char fname[512];
665 char buf[128];
667 /* Check/create directory */
668 if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0)
669 return -1;
671 /* Load key */
672 if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
673 strlcat(fname,PATH_SEPARATOR"private_key",sizeof(fname))
674 >= sizeof(fname)) {
675 log_warn(LD_CONFIG, "Directory name too long to store key file: \"%s\".",
676 s->directory);
677 return -1;
679 s->private_key = init_key_from_file(fname, 1, LOG_ERR);
680 if (!s->private_key)
681 return -1;
683 /* Create service file */
684 if (rend_get_service_id(s->private_key, s->service_id)<0) {
685 log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
686 return -1;
688 if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) {
689 log_warn(LD_BUG, "Couldn't compute hash of public key.");
690 return -1;
692 if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
693 strlcat(fname,PATH_SEPARATOR"hostname",sizeof(fname))
694 >= sizeof(fname)) {
695 log_warn(LD_CONFIG, "Directory name too long to store hostname file:"
696 " \"%s\".", s->directory);
697 return -1;
700 tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id);
701 if (write_str_to_file(fname,buf,0)<0) {
702 log_warn(LD_CONFIG, "Could not write onion address to hostname file.");
703 memwipe(buf, 0, sizeof(buf));
704 return -1;
706 memwipe(buf, 0, sizeof(buf));
708 /* If client authorization is configured, load or generate keys. */
709 if (s->auth_type != REND_NO_AUTH) {
710 if (rend_service_load_auth_keys(s, fname) < 0)
711 return -1;
714 return 0;
717 /** Load and/or generate client authorization keys for the hidden service
718 * <b>s</b>, which stores its hostname in <b>hfname</b>. Return 0 on success,
719 * -1 on failure. */
720 static int
721 rend_service_load_auth_keys(rend_service_t *s, const char *hfname)
723 int r = 0;
724 char cfname[512];
725 char *client_keys_str = NULL;
726 strmap_t *parsed_clients = strmap_new();
727 FILE *cfile, *hfile;
728 open_file_t *open_cfile = NULL, *open_hfile = NULL;
729 char extended_desc_cookie[REND_DESC_COOKIE_LEN+1];
730 char desc_cook_out[3*REND_DESC_COOKIE_LEN_BASE64+1];
731 char service_id[16+1];
732 char buf[1500];
734 /* Load client keys and descriptor cookies, if available. */
735 if (tor_snprintf(cfname, sizeof(cfname), "%s"PATH_SEPARATOR"client_keys",
736 s->directory)<0) {
737 log_warn(LD_CONFIG, "Directory name too long to store client keys "
738 "file: \"%s\".", s->directory);
739 goto err;
741 client_keys_str = read_file_to_str(cfname, RFTS_IGNORE_MISSING, NULL);
742 if (client_keys_str) {
743 if (rend_parse_client_keys(parsed_clients, client_keys_str) < 0) {
744 log_warn(LD_CONFIG, "Previously stored client_keys file could not "
745 "be parsed.");
746 goto err;
747 } else {
748 log_info(LD_CONFIG, "Parsed %d previously stored client entries.",
749 strmap_size(parsed_clients));
753 /* Prepare client_keys and hostname files. */
754 if (!(cfile = start_writing_to_stdio_file(cfname,
755 OPEN_FLAGS_REPLACE | O_TEXT,
756 0600, &open_cfile))) {
757 log_warn(LD_CONFIG, "Could not open client_keys file %s",
758 escaped(cfname));
759 goto err;
762 if (!(hfile = start_writing_to_stdio_file(hfname,
763 OPEN_FLAGS_REPLACE | O_TEXT,
764 0600, &open_hfile))) {
765 log_warn(LD_CONFIG, "Could not open hostname file %s", escaped(hfname));
766 goto err;
769 /* Either use loaded keys for configured clients or generate new
770 * ones if a client is new. */
771 SMARTLIST_FOREACH_BEGIN(s->clients, rend_authorized_client_t *, client) {
772 rend_authorized_client_t *parsed =
773 strmap_get(parsed_clients, client->client_name);
774 int written;
775 size_t len;
776 /* Copy descriptor cookie from parsed entry or create new one. */
777 if (parsed) {
778 memcpy(client->descriptor_cookie, parsed->descriptor_cookie,
779 REND_DESC_COOKIE_LEN);
780 } else {
781 crypto_rand(client->descriptor_cookie, REND_DESC_COOKIE_LEN);
783 if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
784 client->descriptor_cookie,
785 REND_DESC_COOKIE_LEN) < 0) {
786 log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
787 goto err;
789 /* Copy client key from parsed entry or create new one if required. */
790 if (parsed && parsed->client_key) {
791 client->client_key = crypto_pk_dup_key(parsed->client_key);
792 } else if (s->auth_type == REND_STEALTH_AUTH) {
793 /* Create private key for client. */
794 crypto_pk_t *prkey = NULL;
795 if (!(prkey = crypto_pk_new())) {
796 log_warn(LD_BUG,"Error constructing client key");
797 goto err;
799 if (crypto_pk_generate_key(prkey)) {
800 log_warn(LD_BUG,"Error generating client key");
801 crypto_pk_free(prkey);
802 goto err;
804 if (crypto_pk_check_key(prkey) <= 0) {
805 log_warn(LD_BUG,"Generated client key seems invalid");
806 crypto_pk_free(prkey);
807 goto err;
809 client->client_key = prkey;
811 /* Add entry to client_keys file. */
812 desc_cook_out[strlen(desc_cook_out)-1] = '\0'; /* Remove newline. */
813 written = tor_snprintf(buf, sizeof(buf),
814 "client-name %s\ndescriptor-cookie %s\n",
815 client->client_name, desc_cook_out);
816 if (written < 0) {
817 log_warn(LD_BUG, "Could not write client entry.");
818 goto err;
820 if (client->client_key) {
821 char *client_key_out = NULL;
822 if (crypto_pk_write_private_key_to_string(client->client_key,
823 &client_key_out, &len) != 0) {
824 log_warn(LD_BUG, "Internal error: "
825 "crypto_pk_write_private_key_to_string() failed.");
826 goto err;
828 if (rend_get_service_id(client->client_key, service_id)<0) {
829 log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
831 * len is string length, not buffer length, but last byte is NUL
832 * anyway.
834 memwipe(client_key_out, 0, len);
835 tor_free(client_key_out);
836 goto err;
838 written = tor_snprintf(buf + written, sizeof(buf) - written,
839 "client-key\n%s", client_key_out);
840 memwipe(client_key_out, 0, len);
841 tor_free(client_key_out);
842 if (written < 0) {
843 log_warn(LD_BUG, "Could not write client entry.");
844 goto err;
848 if (fputs(buf, cfile) < 0) {
849 log_warn(LD_FS, "Could not append client entry to file: %s",
850 strerror(errno));
851 goto err;
854 /* Add line to hostname file. */
855 if (s->auth_type == REND_BASIC_AUTH) {
856 /* Remove == signs (newline has been removed above). */
857 desc_cook_out[strlen(desc_cook_out)-2] = '\0';
858 tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
859 s->service_id, desc_cook_out, client->client_name);
860 } else {
861 memcpy(extended_desc_cookie, client->descriptor_cookie,
862 REND_DESC_COOKIE_LEN);
863 extended_desc_cookie[REND_DESC_COOKIE_LEN] =
864 ((int)s->auth_type - 1) << 4;
865 if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
866 extended_desc_cookie,
867 REND_DESC_COOKIE_LEN+1) < 0) {
868 log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
869 goto err;
871 desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove A= and
872 newline. */
873 tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
874 service_id, desc_cook_out, client->client_name);
877 if (fputs(buf, hfile)<0) {
878 log_warn(LD_FS, "Could not append host entry to file: %s",
879 strerror(errno));
880 goto err;
882 } SMARTLIST_FOREACH_END(client);
884 finish_writing_to_file(open_cfile);
885 finish_writing_to_file(open_hfile);
887 goto done;
888 err:
889 r = -1;
890 if (open_cfile)
891 abort_writing_to_file(open_cfile);
892 if (open_hfile)
893 abort_writing_to_file(open_hfile);
894 done:
895 if (client_keys_str) {
896 tor_strclear(client_keys_str);
897 tor_free(client_keys_str);
899 strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
901 memwipe(cfname, 0, sizeof(cfname));
903 /* Clear stack buffers that held key-derived material. */
904 memwipe(buf, 0, sizeof(buf));
905 memwipe(desc_cook_out, 0, sizeof(desc_cook_out));
906 memwipe(service_id, 0, sizeof(service_id));
907 memwipe(extended_desc_cookie, 0, sizeof(extended_desc_cookie));
909 return r;
912 /** Return the service whose public key has a digest of <b>digest</b>, or
913 * NULL if no such service exists.
915 static rend_service_t *
916 rend_service_get_by_pk_digest(const char* digest)
918 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
919 if (tor_memeq(s->pk_digest,digest,DIGEST_LEN))
920 return s);
921 return NULL;
924 /** Return 1 if any virtual port in <b>service</b> wants a circuit
925 * to have good uptime. Else return 0.
927 static int
928 rend_service_requires_uptime(rend_service_t *service)
930 int i;
931 rend_service_port_config_t *p;
933 for (i=0; i < smartlist_len(service->ports); ++i) {
934 p = smartlist_get(service->ports, i);
935 if (smartlist_contains_int_as_string(get_options()->LongLivedPorts,
936 p->virtual_port))
937 return 1;
939 return 0;
942 /** Check client authorization of a given <b>descriptor_cookie</b> for
943 * <b>service</b>. Return 1 for success and 0 for failure. */
944 static int
945 rend_check_authorization(rend_service_t *service,
946 const char *descriptor_cookie)
948 rend_authorized_client_t *auth_client = NULL;
949 tor_assert(service);
950 tor_assert(descriptor_cookie);
951 if (!service->clients) {
952 log_warn(LD_BUG, "Can't check authorization for a service that has no "
953 "authorized clients configured.");
954 return 0;
957 /* Look up client authorization by descriptor cookie. */
958 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, client, {
959 if (tor_memeq(client->descriptor_cookie, descriptor_cookie,
960 REND_DESC_COOKIE_LEN)) {
961 auth_client = client;
962 break;
965 if (!auth_client) {
966 char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64];
967 base64_encode(descriptor_cookie_base64, sizeof(descriptor_cookie_base64),
968 descriptor_cookie, REND_DESC_COOKIE_LEN);
969 log_info(LD_REND, "No authorization found for descriptor cookie '%s'! "
970 "Dropping cell!",
971 descriptor_cookie_base64);
972 return 0;
975 /* Allow the request. */
976 log_debug(LD_REND, "Client %s authorized for service %s.",
977 auth_client->client_name, service->service_id);
978 return 1;
981 /** Called when <b>intro</b> will soon be removed from
982 * <b>service</b>'s list of intro points. */
983 static void
984 rend_service_note_removing_intro_point(rend_service_t *service,
985 rend_intro_point_t *intro)
987 time_t now = time(NULL);
989 /* Don't process an intro point twice here. */
990 if (intro->rend_service_note_removing_intro_point_called) {
991 return;
992 } else {
993 intro->rend_service_note_removing_intro_point_called = 1;
996 /* Update service->n_intro_points_wanted based on how long intro
997 * lasted and how many introductions it handled. */
998 if (intro->time_published == -1) {
999 /* This intro point was never used. Don't change
1000 * n_intro_points_wanted. */
1001 } else {
1002 /* We want to increase the number of introduction points service
1003 * operates if intro was heavily used, or decrease the number of
1004 * intro points if intro was lightly used.
1006 * We consider an intro point's target 'usage' to be
1007 * INTRO_POINT_LIFETIME_INTRODUCTIONS introductions in
1008 * INTRO_POINT_LIFETIME_MIN_SECONDS seconds. To calculate intro's
1009 * fraction of target usage, we divide the fraction of
1010 * _LIFETIME_INTRODUCTIONS introductions that it has handled by
1011 * the fraction of _LIFETIME_MIN_SECONDS for which it existed.
1013 * Then we multiply that fraction of desired usage by a fudge
1014 * factor of 1.5, to decide how many new introduction points
1015 * should ideally replace intro (which is now closed or soon to be
1016 * closed). In theory, assuming that introduction load is
1017 * distributed equally across all intro points and ignoring the
1018 * fact that different intro points are established and closed at
1019 * different times, that number of intro points should bring all
1020 * of our intro points exactly to our target usage.
1022 * Then we clamp that number to a number of intro points we might
1023 * be willing to replace this intro point with and turn it into an
1024 * integer. then we clamp it again to the number of new intro
1025 * points we could establish now, then we adjust
1026 * service->n_intro_points_wanted and let rend_services_introduce
1027 * create the new intro points we want (if any).
1029 const double intro_point_usage =
1030 intro_point_accepted_intro_count(intro) /
1031 (double)(now - intro->time_published);
1032 const double intro_point_target_usage =
1033 INTRO_POINT_LIFETIME_INTRODUCTIONS /
1034 (double)INTRO_POINT_LIFETIME_MIN_SECONDS;
1035 const double fractional_n_intro_points_wanted_to_replace_this_one =
1036 (1.5 * (intro_point_usage / intro_point_target_usage));
1037 unsigned int n_intro_points_wanted_to_replace_this_one;
1038 unsigned int n_intro_points_wanted_now;
1039 unsigned int n_intro_points_really_wanted_now;
1040 int n_intro_points_really_replacing_this_one;
1042 if (fractional_n_intro_points_wanted_to_replace_this_one >
1043 NUM_INTRO_POINTS_MAX) {
1044 n_intro_points_wanted_to_replace_this_one = NUM_INTRO_POINTS_MAX;
1045 } else if (fractional_n_intro_points_wanted_to_replace_this_one < 0) {
1046 n_intro_points_wanted_to_replace_this_one = 0;
1047 } else {
1048 n_intro_points_wanted_to_replace_this_one = (unsigned)
1049 fractional_n_intro_points_wanted_to_replace_this_one;
1052 n_intro_points_wanted_now =
1053 service->n_intro_points_wanted +
1054 n_intro_points_wanted_to_replace_this_one - 1;
1056 if (n_intro_points_wanted_now < NUM_INTRO_POINTS_DEFAULT) {
1057 /* XXXX This should be NUM_INTRO_POINTS_MIN instead. Perhaps
1058 * another use of NUM_INTRO_POINTS_DEFAULT should be, too. */
1059 n_intro_points_really_wanted_now = NUM_INTRO_POINTS_DEFAULT;
1060 } else if (n_intro_points_wanted_now > NUM_INTRO_POINTS_MAX) {
1061 n_intro_points_really_wanted_now = NUM_INTRO_POINTS_MAX;
1062 } else {
1063 n_intro_points_really_wanted_now = n_intro_points_wanted_now;
1066 n_intro_points_really_replacing_this_one =
1067 n_intro_points_really_wanted_now - service->n_intro_points_wanted + 1;
1069 log_info(LD_REND, "Replacing closing intro point for service %s "
1070 "with %d new intro points (wanted %g replacements); "
1071 "service will now try to have %u intro points",
1072 rend_service_describe_for_log(service),
1073 n_intro_points_really_replacing_this_one,
1074 fractional_n_intro_points_wanted_to_replace_this_one,
1075 n_intro_points_really_wanted_now);
1077 service->n_intro_points_wanted = n_intro_points_really_wanted_now;
1081 /******
1082 * Handle cells
1083 ******/
1085 /** Respond to an INTRODUCE2 cell by launching a circuit to the chosen
1086 * rendezvous point.
1089 rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
1090 size_t request_len)
1092 /* Global status stuff */
1093 int status = 0, result;
1094 const or_options_t *options = get_options();
1095 char *err_msg = NULL;
1096 const char *stage_descr = NULL;
1097 int reason = END_CIRC_REASON_TORPROTOCOL;
1098 /* Service/circuit/key stuff we can learn before parsing */
1099 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
1100 rend_service_t *service = NULL;
1101 rend_intro_point_t *intro_point = NULL;
1102 crypto_pk_t *intro_key = NULL;
1103 /* Parsed cell */
1104 rend_intro_cell_t *parsed_req = NULL;
1105 /* Rendezvous point */
1106 extend_info_t *rp = NULL;
1108 * We need to look up and construct the extend_info_t for v0 and v1,
1109 * but all the info is in the cell and it's constructed by the parser
1110 * for v2 and v3, so freeing it would be a double-free. Use this to
1111 * keep track of whether we should free it.
1113 uint8_t need_rp_free = 0;
1114 /* XXX not handled yet */
1115 char buf[RELAY_PAYLOAD_SIZE];
1116 char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
1117 int i;
1118 crypto_dh_t *dh = NULL;
1119 origin_circuit_t *launched = NULL;
1120 crypt_path_t *cpath = NULL;
1121 char hexcookie[9];
1122 int circ_needs_uptime;
1123 time_t now = time(NULL);
1124 time_t elapsed;
1125 int replay;
1127 /* Do some initial validation and logging before we parse the cell */
1128 if (circuit->base_.purpose != CIRCUIT_PURPOSE_S_INTRO) {
1129 log_warn(LD_PROTOCOL,
1130 "Got an INTRODUCE2 over a non-introduction circuit %u.",
1131 (unsigned) circuit->base_.n_circ_id);
1132 goto err;
1135 #ifndef NON_ANONYMOUS_MODE_ENABLED
1136 tor_assert(!(circuit->build_state->onehop_tunnel));
1137 #endif
1138 tor_assert(circuit->rend_data);
1140 /* We'll use this in a bazillion log messages */
1141 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
1142 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
1144 /* look up service depending on circuit. */
1145 service =
1146 rend_service_get_by_pk_digest(circuit->rend_data->rend_pk_digest);
1147 if (!service) {
1148 log_warn(LD_BUG,
1149 "Internal error: Got an INTRODUCE2 cell on an intro "
1150 "circ for an unrecognized service %s.",
1151 escaped(serviceid));
1152 goto err;
1155 intro_point = find_intro_point(circuit);
1156 if (intro_point == NULL) {
1157 log_warn(LD_BUG,
1158 "Internal error: Got an INTRODUCE2 cell on an "
1159 "intro circ (for service %s) with no corresponding "
1160 "rend_intro_point_t.",
1161 escaped(serviceid));
1162 goto err;
1165 log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %u.",
1166 escaped(serviceid), (unsigned)circuit->base_.n_circ_id);
1168 /* use intro key instead of service key. */
1169 intro_key = circuit->intro_key;
1171 tor_free(err_msg);
1172 stage_descr = NULL;
1174 stage_descr = "early parsing";
1175 /* Early parsing pass (get pk, ciphertext); type 2 is INTRODUCE2 */
1176 parsed_req =
1177 rend_service_begin_parse_intro(request, request_len, 2, &err_msg);
1178 if (!parsed_req) {
1179 goto log_error;
1180 } else if (err_msg) {
1181 log_info(LD_REND, "%s on circ %u.", err_msg,
1182 (unsigned)circuit->base_.n_circ_id);
1183 tor_free(err_msg);
1186 stage_descr = "early validation";
1187 /* Early validation of pk/ciphertext part */
1188 result = rend_service_validate_intro_early(parsed_req, &err_msg);
1189 if (result < 0) {
1190 goto log_error;
1191 } else if (err_msg) {
1192 log_info(LD_REND, "%s on circ %u.", err_msg,
1193 (unsigned)circuit->base_.n_circ_id);
1194 tor_free(err_msg);
1197 /* make sure service replay caches are present */
1198 if (!service->accepted_intro_dh_parts) {
1199 service->accepted_intro_dh_parts =
1200 replaycache_new(REND_REPLAY_TIME_INTERVAL,
1201 REND_REPLAY_TIME_INTERVAL);
1204 if (!intro_point->accepted_intro_rsa_parts) {
1205 intro_point->accepted_intro_rsa_parts = replaycache_new(0, 0);
1208 /* check for replay of PK-encrypted portion. */
1209 replay = replaycache_add_test_and_elapsed(
1210 intro_point->accepted_intro_rsa_parts,
1211 parsed_req->ciphertext, parsed_req->ciphertext_len,
1212 &elapsed);
1214 if (replay) {
1215 log_warn(LD_REND,
1216 "Possible replay detected! We received an "
1217 "INTRODUCE2 cell with same PK-encrypted part %d "
1218 "seconds ago. Dropping cell.",
1219 (int)elapsed);
1220 goto err;
1223 stage_descr = "decryption";
1224 /* Now try to decrypt it */
1225 result = rend_service_decrypt_intro(parsed_req, intro_key, &err_msg);
1226 if (result < 0) {
1227 goto log_error;
1228 } else if (err_msg) {
1229 log_info(LD_REND, "%s on circ %u.", err_msg,
1230 (unsigned)circuit->base_.n_circ_id);
1231 tor_free(err_msg);
1234 stage_descr = "late parsing";
1235 /* Parse the plaintext */
1236 result = rend_service_parse_intro_plaintext(parsed_req, &err_msg);
1237 if (result < 0) {
1238 goto log_error;
1239 } else if (err_msg) {
1240 log_info(LD_REND, "%s on circ %u.", err_msg,
1241 (unsigned)circuit->base_.n_circ_id);
1242 tor_free(err_msg);
1245 stage_descr = "late validation";
1246 /* Validate the parsed plaintext parts */
1247 result = rend_service_validate_intro_late(parsed_req, &err_msg);
1248 if (result < 0) {
1249 goto log_error;
1250 } else if (err_msg) {
1251 log_info(LD_REND, "%s on circ %u.", err_msg,
1252 (unsigned)circuit->base_.n_circ_id);
1253 tor_free(err_msg);
1255 stage_descr = NULL;
1257 /* Increment INTRODUCE2 counter */
1258 ++(intro_point->accepted_introduce2_count);
1260 /* Find the rendezvous point */
1261 rp = find_rp_for_intro(parsed_req, &need_rp_free, &err_msg);
1262 if (!rp)
1263 goto log_error;
1265 /* Check if we'd refuse to talk to this router */
1266 if (options->StrictNodes &&
1267 routerset_contains_extendinfo(options->ExcludeNodes, rp)) {
1268 log_warn(LD_REND, "Client asked to rendezvous at a relay that we "
1269 "exclude, and StrictNodes is set. Refusing service.");
1270 reason = END_CIRC_REASON_INTERNAL; /* XXX might leak why we refused */
1271 goto err;
1274 base16_encode(hexcookie, 9, (const char *)(parsed_req->rc), 4);
1276 /* Check whether there is a past request with the same Diffie-Hellman,
1277 * part 1. */
1278 replay = replaycache_add_test_and_elapsed(
1279 service->accepted_intro_dh_parts,
1280 parsed_req->dh, DH_KEY_LEN,
1281 &elapsed);
1283 if (replay) {
1284 /* A Tor client will send a new INTRODUCE1 cell with the same rend
1285 * cookie and DH public key as its previous one if its intro circ
1286 * times out while in state CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT .
1287 * If we received the first INTRODUCE1 cell (the intro-point relay
1288 * converts it into an INTRODUCE2 cell), we are already trying to
1289 * connect to that rend point (and may have already succeeded);
1290 * drop this cell. */
1291 log_info(LD_REND, "We received an "
1292 "INTRODUCE2 cell with same first part of "
1293 "Diffie-Hellman handshake %d seconds ago. Dropping "
1294 "cell.",
1295 (int) elapsed);
1296 goto err;
1299 /* If the service performs client authorization, check included auth data. */
1300 if (service->clients) {
1301 if (parsed_req->version == 3 && parsed_req->u.v3.auth_len > 0) {
1302 if (rend_check_authorization(service,
1303 (const char*)parsed_req->u.v3.auth_data)) {
1304 log_info(LD_REND, "Authorization data in INTRODUCE2 cell are valid.");
1305 } else {
1306 log_info(LD_REND, "The authorization data that are contained in "
1307 "the INTRODUCE2 cell are invalid. Dropping cell.");
1308 reason = END_CIRC_REASON_CONNECTFAILED;
1309 goto err;
1311 } else {
1312 log_info(LD_REND, "INTRODUCE2 cell does not contain authentication "
1313 "data, but we require client authorization. Dropping cell.");
1314 reason = END_CIRC_REASON_CONNECTFAILED;
1315 goto err;
1319 /* Try DH handshake... */
1320 dh = crypto_dh_new(DH_TYPE_REND);
1321 if (!dh || crypto_dh_generate_public(dh)<0) {
1322 log_warn(LD_BUG,"Internal error: couldn't build DH state "
1323 "or generate public key.");
1324 reason = END_CIRC_REASON_INTERNAL;
1325 goto err;
1327 if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh,
1328 (char *)(parsed_req->dh),
1329 DH_KEY_LEN, keys,
1330 DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
1331 log_warn(LD_BUG, "Internal error: couldn't complete DH handshake");
1332 reason = END_CIRC_REASON_INTERNAL;
1333 goto err;
1336 circ_needs_uptime = rend_service_requires_uptime(service);
1338 /* help predict this next time */
1339 rep_hist_note_used_internal(now, circ_needs_uptime, 1);
1341 /* Launch a circuit to alice's chosen rendezvous point.
1343 for (i=0;i<MAX_REND_FAILURES;i++) {
1344 int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL;
1345 if (circ_needs_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
1346 launched = circuit_launch_by_extend_info(
1347 CIRCUIT_PURPOSE_S_CONNECT_REND, rp, flags);
1349 if (launched)
1350 break;
1352 if (!launched) { /* give up */
1353 log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous "
1354 "point %s for service %s.",
1355 safe_str_client(extend_info_describe(rp)),
1356 serviceid);
1357 reason = END_CIRC_REASON_CONNECTFAILED;
1358 goto err;
1360 log_info(LD_REND,
1361 "Accepted intro; launching circuit to %s "
1362 "(cookie %s) for service %s.",
1363 safe_str_client(extend_info_describe(rp)),
1364 hexcookie, serviceid);
1365 tor_assert(launched->build_state);
1366 /* Fill in the circuit's state. */
1367 launched->rend_data = tor_malloc_zero(sizeof(rend_data_t));
1368 memcpy(launched->rend_data->rend_pk_digest,
1369 circuit->rend_data->rend_pk_digest,
1370 DIGEST_LEN);
1371 memcpy(launched->rend_data->rend_cookie, parsed_req->rc, REND_COOKIE_LEN);
1372 strlcpy(launched->rend_data->onion_address, service->service_id,
1373 sizeof(launched->rend_data->onion_address));
1375 launched->build_state->service_pending_final_cpath_ref =
1376 tor_malloc_zero(sizeof(crypt_path_reference_t));
1377 launched->build_state->service_pending_final_cpath_ref->refcount = 1;
1379 launched->build_state->service_pending_final_cpath_ref->cpath = cpath =
1380 tor_malloc_zero(sizeof(crypt_path_t));
1381 cpath->magic = CRYPT_PATH_MAGIC;
1382 launched->build_state->expiry_time = now + MAX_REND_TIMEOUT;
1384 cpath->rend_dh_handshake_state = dh;
1385 dh = NULL;
1386 if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0)
1387 goto err;
1388 memcpy(cpath->rend_circ_nonce, keys, DIGEST_LEN);
1390 goto done;
1392 log_error:
1393 if (!err_msg) {
1394 if (stage_descr) {
1395 tor_asprintf(&err_msg,
1396 "unknown %s error for INTRODUCE2", stage_descr);
1397 } else {
1398 err_msg = tor_strdup("unknown error for INTRODUCE2");
1402 log_warn(LD_REND, "%s on circ %u", err_msg,
1403 (unsigned)circuit->base_.n_circ_id);
1404 err:
1405 status = -1;
1406 if (dh) crypto_dh_free(dh);
1407 if (launched) {
1408 circuit_mark_for_close(TO_CIRCUIT(launched), reason);
1410 tor_free(err_msg);
1412 done:
1413 memwipe(keys, 0, sizeof(keys));
1414 memwipe(buf, 0, sizeof(buf));
1415 memwipe(serviceid, 0, sizeof(serviceid));
1416 memwipe(hexcookie, 0, sizeof(hexcookie));
1418 /* Free the parsed cell */
1419 if (parsed_req) {
1420 rend_service_free_intro(parsed_req);
1421 parsed_req = NULL;
1424 /* Free rp if we must */
1425 if (need_rp_free) extend_info_free(rp);
1427 return status;
1430 /** Given a parsed and decrypted INTRODUCE2, find the rendezvous point or
1431 * return NULL and an error string if we can't.
1434 static extend_info_t *
1435 find_rp_for_intro(const rend_intro_cell_t *intro,
1436 uint8_t *need_free_out, char **err_msg_out)
1438 extend_info_t *rp = NULL;
1439 char *err_msg = NULL;
1440 const char *rp_nickname = NULL;
1441 const node_t *node = NULL;
1442 uint8_t need_free = 0;
1444 if (!intro || !need_free_out) {
1445 if (err_msg_out)
1446 err_msg = tor_strdup("Bad parameters to find_rp_for_intro()");
1448 goto err;
1451 if (intro->version == 0 || intro->version == 1) {
1452 if (intro->version == 1) rp_nickname = (const char *)(intro->u.v1.rp);
1453 else rp_nickname = (const char *)(intro->u.v0.rp);
1455 node = node_get_by_nickname(rp_nickname, 0);
1456 if (!node) {
1457 if (err_msg_out) {
1458 tor_asprintf(&err_msg,
1459 "Couldn't find router %s named in INTRODUCE2 cell",
1460 escaped_safe_str_client(rp_nickname));
1463 goto err;
1466 rp = extend_info_from_node(node, 0);
1467 if (!rp) {
1468 if (err_msg_out) {
1469 tor_asprintf(&err_msg,
1470 "Could build extend_info_t for router %s named "
1471 "in INTRODUCE2 cell",
1472 escaped_safe_str_client(rp_nickname));
1475 goto err;
1476 } else {
1477 need_free = 1;
1479 } else if (intro->version == 2) {
1480 rp = intro->u.v2.extend_info;
1481 } else if (intro->version == 3) {
1482 rp = intro->u.v3.extend_info;
1483 } else {
1484 if (err_msg_out) {
1485 tor_asprintf(&err_msg,
1486 "Unknown version %d in INTRODUCE2 cell",
1487 (int)(intro->version));
1490 goto err;
1493 goto done;
1495 err:
1496 if (err_msg_out) *err_msg_out = err_msg;
1497 else tor_free(err_msg);
1499 done:
1500 if (rp && need_free_out) *need_free_out = need_free;
1502 return rp;
1505 /** Remove unnecessary parts from a rend_intro_cell_t - the ciphertext if
1506 * already decrypted, the plaintext too if already parsed
1509 void
1510 rend_service_compact_intro(rend_intro_cell_t *request)
1512 if (!request) return;
1514 if ((request->plaintext && request->plaintext_len > 0) ||
1515 request->parsed) {
1516 tor_free(request->ciphertext);
1517 request->ciphertext_len = 0;
1520 if (request->parsed) {
1521 tor_free(request->plaintext);
1522 request->plaintext_len = 0;
1526 /** Free a parsed INTRODUCE1 or INTRODUCE2 cell that was allocated by
1527 * rend_service_parse_intro().
1529 void
1530 rend_service_free_intro(rend_intro_cell_t *request)
1532 if (!request) {
1533 log_info(LD_BUG, "rend_service_free_intro() called with NULL request!");
1534 return;
1537 /* Free ciphertext */
1538 tor_free(request->ciphertext);
1539 request->ciphertext_len = 0;
1541 /* Have plaintext? */
1542 if (request->plaintext) {
1543 /* Zero it out just to be safe */
1544 memwipe(request->plaintext, 0, request->plaintext_len);
1545 tor_free(request->plaintext);
1546 request->plaintext_len = 0;
1549 /* Have parsed plaintext? */
1550 if (request->parsed) {
1551 switch (request->version) {
1552 case 0:
1553 case 1:
1555 * Nothing more to do; these formats have no further pointers
1556 * in them.
1558 break;
1559 case 2:
1560 extend_info_free(request->u.v2.extend_info);
1561 request->u.v2.extend_info = NULL;
1562 break;
1563 case 3:
1564 if (request->u.v3.auth_data) {
1565 memwipe(request->u.v3.auth_data, 0, request->u.v3.auth_len);
1566 tor_free(request->u.v3.auth_data);
1569 extend_info_free(request->u.v3.extend_info);
1570 request->u.v3.extend_info = NULL;
1571 break;
1572 default:
1573 log_info(LD_BUG,
1574 "rend_service_free_intro() saw unknown protocol "
1575 "version %d.",
1576 request->version);
1580 /* Zero it out to make sure sensitive stuff doesn't hang around in memory */
1581 memwipe(request, 0, sizeof(*request));
1583 tor_free(request);
1586 /** Parse an INTRODUCE1 or INTRODUCE2 cell into a newly allocated
1587 * rend_intro_cell_t structure. Free it with rend_service_free_intro()
1588 * when finished. The type parameter should be 1 or 2 to indicate whether
1589 * this is INTRODUCE1 or INTRODUCE2. This parses only the non-encrypted
1590 * parts; after this, call rend_service_decrypt_intro() with a key, then
1591 * rend_service_parse_intro_plaintext() to finish parsing. The optional
1592 * err_msg_out parameter is set to a string suitable for log output
1593 * if parsing fails. This function does some validation, but only
1594 * that which depends solely on the contents of the cell and the
1595 * key; it can be unit-tested. Further validation is done in
1596 * rend_service_validate_intro().
1599 rend_intro_cell_t *
1600 rend_service_begin_parse_intro(const uint8_t *request,
1601 size_t request_len,
1602 uint8_t type,
1603 char **err_msg_out)
1605 rend_intro_cell_t *rv = NULL;
1606 char *err_msg = NULL;
1608 if (!request || request_len <= 0) goto err;
1609 if (!(type == 1 || type == 2)) goto err;
1611 /* First, check that the cell is long enough to be a sensible INTRODUCE */
1613 /* min key length plus digest length plus nickname length */
1614 if (request_len <
1615 (DIGEST_LEN + REND_COOKIE_LEN + (MAX_NICKNAME_LEN + 1) +
1616 DH_KEY_LEN + 42)) {
1617 if (err_msg_out) {
1618 tor_asprintf(&err_msg,
1619 "got a truncated INTRODUCE%d cell",
1620 (int)type);
1622 goto err;
1625 /* Allocate a new parsed cell structure */
1626 rv = tor_malloc_zero(sizeof(*rv));
1628 /* Set the type */
1629 rv->type = type;
1631 /* Copy in the ID */
1632 memcpy(rv->pk, request, DIGEST_LEN);
1634 /* Copy in the ciphertext */
1635 rv->ciphertext = tor_malloc(request_len - DIGEST_LEN);
1636 memcpy(rv->ciphertext, request + DIGEST_LEN, request_len - DIGEST_LEN);
1637 rv->ciphertext_len = request_len - DIGEST_LEN;
1639 goto done;
1641 err:
1642 if (rv) rend_service_free_intro(rv);
1643 rv = NULL;
1644 if (err_msg_out && !err_msg) {
1645 tor_asprintf(&err_msg,
1646 "unknown INTRODUCE%d error",
1647 (int)type);
1650 done:
1651 if (err_msg_out) *err_msg_out = err_msg;
1652 else tor_free(err_msg);
1654 return rv;
1657 /** Parse the version-specific parts of a v0 or v1 INTRODUCE1 or INTRODUCE2
1658 * cell
1661 static ssize_t
1662 rend_service_parse_intro_for_v0_or_v1(
1663 rend_intro_cell_t *intro,
1664 const uint8_t *buf,
1665 size_t plaintext_len,
1666 char **err_msg_out)
1668 const char *rp_nickname, *endptr;
1669 size_t nickname_field_len, ver_specific_len;
1671 if (intro->version == 1) {
1672 ver_specific_len = MAX_HEX_NICKNAME_LEN + 2;
1673 rp_nickname = ((const char *)buf) + 1;
1674 nickname_field_len = MAX_HEX_NICKNAME_LEN + 1;
1675 } else if (intro->version == 0) {
1676 ver_specific_len = MAX_NICKNAME_LEN + 1;
1677 rp_nickname = (const char *)buf;
1678 nickname_field_len = MAX_NICKNAME_LEN + 1;
1679 } else {
1680 if (err_msg_out)
1681 tor_asprintf(err_msg_out,
1682 "rend_service_parse_intro_for_v0_or_v1() called with "
1683 "bad version %d on INTRODUCE%d cell (this is a bug)",
1684 intro->version,
1685 (int)(intro->type));
1686 goto err;
1689 if (plaintext_len < ver_specific_len) {
1690 if (err_msg_out)
1691 tor_asprintf(err_msg_out,
1692 "short plaintext of encrypted part in v1 INTRODUCE%d "
1693 "cell (%lu bytes, needed %lu)",
1694 (int)(intro->type),
1695 (unsigned long)plaintext_len,
1696 (unsigned long)ver_specific_len);
1697 goto err;
1700 endptr = memchr(rp_nickname, 0, nickname_field_len);
1701 if (!endptr || endptr == rp_nickname) {
1702 if (err_msg_out) {
1703 tor_asprintf(err_msg_out,
1704 "couldn't find a nul-padded nickname in "
1705 "INTRODUCE%d cell",
1706 (int)(intro->type));
1708 goto err;
1711 if ((intro->version == 0 &&
1712 !is_legal_nickname(rp_nickname)) ||
1713 (intro->version == 1 &&
1714 !is_legal_nickname_or_hexdigest(rp_nickname))) {
1715 if (err_msg_out) {
1716 tor_asprintf(err_msg_out,
1717 "bad nickname in INTRODUCE%d cell",
1718 (int)(intro->type));
1720 goto err;
1723 if (intro->version == 1) {
1724 memcpy(intro->u.v1.rp, rp_nickname, endptr - rp_nickname + 1);
1725 } else {
1726 memcpy(intro->u.v0.rp, rp_nickname, endptr - rp_nickname + 1);
1729 return ver_specific_len;
1731 err:
1732 return -1;
1735 /** Parse the version-specific parts of a v2 INTRODUCE1 or INTRODUCE2 cell
1738 static ssize_t
1739 rend_service_parse_intro_for_v2(
1740 rend_intro_cell_t *intro,
1741 const uint8_t *buf,
1742 size_t plaintext_len,
1743 char **err_msg_out)
1745 unsigned int klen;
1746 extend_info_t *extend_info = NULL;
1747 ssize_t ver_specific_len;
1750 * We accept version 3 too so that the v3 parser can call this with
1751 * and adjusted buffer for the latter part of a v3 cell, which is
1752 * identical to a v2 cell.
1754 if (!(intro->version == 2 ||
1755 intro->version == 3)) {
1756 if (err_msg_out)
1757 tor_asprintf(err_msg_out,
1758 "rend_service_parse_intro_for_v2() called with "
1759 "bad version %d on INTRODUCE%d cell (this is a bug)",
1760 intro->version,
1761 (int)(intro->type));
1762 goto err;
1765 /* 7 == version, IP and port, DIGEST_LEN == id, 2 == key length */
1766 if (plaintext_len < 7 + DIGEST_LEN + 2) {
1767 if (err_msg_out) {
1768 tor_asprintf(err_msg_out,
1769 "truncated plaintext of encrypted parted of "
1770 "version %d INTRODUCE%d cell",
1771 intro->version,
1772 (int)(intro->type));
1775 goto err;
1778 extend_info = tor_malloc_zero(sizeof(extend_info_t));
1779 tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf + 1));
1780 extend_info->port = ntohs(get_uint16(buf + 5));
1781 memcpy(extend_info->identity_digest, buf + 7, DIGEST_LEN);
1782 extend_info->nickname[0] = '$';
1783 base16_encode(extend_info->nickname + 1, sizeof(extend_info->nickname) - 1,
1784 extend_info->identity_digest, DIGEST_LEN);
1785 klen = ntohs(get_uint16(buf + 7 + DIGEST_LEN));
1787 /* 7 == version, IP and port, DIGEST_LEN == id, 2 == key length */
1788 if (plaintext_len < 7 + DIGEST_LEN + 2 + klen) {
1789 if (err_msg_out) {
1790 tor_asprintf(err_msg_out,
1791 "truncated plaintext of encrypted parted of "
1792 "version %d INTRODUCE%d cell",
1793 intro->version,
1794 (int)(intro->type));
1797 goto err;
1800 extend_info->onion_key =
1801 crypto_pk_asn1_decode((const char *)(buf + 7 + DIGEST_LEN + 2), klen);
1802 if (!extend_info->onion_key) {
1803 if (err_msg_out) {
1804 tor_asprintf(err_msg_out,
1805 "error decoding onion key in version %d "
1806 "INTRODUCE%d cell",
1807 intro->version,
1808 (intro->type));
1811 goto err;
1814 ver_specific_len = 7+DIGEST_LEN+2+klen;
1816 if (intro->version == 2) intro->u.v2.extend_info = extend_info;
1817 else intro->u.v3.extend_info = extend_info;
1819 return ver_specific_len;
1821 err:
1822 extend_info_free(extend_info);
1824 return -1;
1827 /** Parse the version-specific parts of a v3 INTRODUCE1 or INTRODUCE2 cell
1830 static ssize_t
1831 rend_service_parse_intro_for_v3(
1832 rend_intro_cell_t *intro,
1833 const uint8_t *buf,
1834 size_t plaintext_len,
1835 char **err_msg_out)
1837 ssize_t adjust, v2_ver_specific_len, ts_offset;
1839 /* This should only be called on v3 cells */
1840 if (intro->version != 3) {
1841 if (err_msg_out)
1842 tor_asprintf(err_msg_out,
1843 "rend_service_parse_intro_for_v3() called with "
1844 "bad version %d on INTRODUCE%d cell (this is a bug)",
1845 intro->version,
1846 (int)(intro->type));
1847 goto err;
1851 * Check that we have at least enough to get auth_len:
1853 * 1 octet for version, 1 for auth_type, 2 for auth_len
1855 if (plaintext_len < 4) {
1856 if (err_msg_out) {
1857 tor_asprintf(err_msg_out,
1858 "truncated plaintext of encrypted parted of "
1859 "version %d INTRODUCE%d cell",
1860 intro->version,
1861 (int)(intro->type));
1864 goto err;
1868 * The rend_client_send_introduction() function over in rendclient.c is
1869 * broken (i.e., fails to match the spec) in such a way that we can't
1870 * change it without breaking the protocol. Specifically, it doesn't
1871 * emit auth_len when auth-type is REND_NO_AUTH, so everything is off
1872 * by two bytes after that. Calculate ts_offset and do everything from
1873 * the timestamp on relative to that to handle this dain bramage.
1876 intro->u.v3.auth_type = buf[1];
1877 if (intro->u.v3.auth_type != REND_NO_AUTH) {
1878 intro->u.v3.auth_len = ntohs(get_uint16(buf + 2));
1879 ts_offset = 4 + intro->u.v3.auth_len;
1880 } else {
1881 intro->u.v3.auth_len = 0;
1882 ts_offset = 2;
1885 /* Check that auth len makes sense for this auth type */
1886 if (intro->u.v3.auth_type == REND_BASIC_AUTH ||
1887 intro->u.v3.auth_type == REND_STEALTH_AUTH) {
1888 if (intro->u.v3.auth_len != REND_DESC_COOKIE_LEN) {
1889 if (err_msg_out) {
1890 tor_asprintf(err_msg_out,
1891 "wrong auth data size %d for INTRODUCE%d cell, "
1892 "should be %d",
1893 (int)(intro->u.v3.auth_len),
1894 (int)(intro->type),
1895 REND_DESC_COOKIE_LEN);
1898 goto err;
1902 /* Check that we actually have everything up through the timestamp */
1903 if (plaintext_len < (size_t)(ts_offset)+4) {
1904 if (err_msg_out) {
1905 tor_asprintf(err_msg_out,
1906 "truncated plaintext of encrypted parted of "
1907 "version %d INTRODUCE%d cell",
1908 intro->version,
1909 (int)(intro->type));
1912 goto err;
1915 if (intro->u.v3.auth_type != REND_NO_AUTH &&
1916 intro->u.v3.auth_len > 0) {
1917 /* Okay, we can go ahead and copy auth_data */
1918 intro->u.v3.auth_data = tor_malloc(intro->u.v3.auth_len);
1920 * We know we had an auth_len field in this case, so 4 is
1921 * always right.
1923 memcpy(intro->u.v3.auth_data, buf + 4, intro->u.v3.auth_len);
1927 * From here on, the format is as in v2, so we call the v2 parser with
1928 * adjusted buffer and length. We are 4 + ts_offset octets in, but the
1929 * v2 parser expects to skip over a version byte at the start, so we
1930 * adjust by 3 + ts_offset.
1932 adjust = 3 + ts_offset;
1934 v2_ver_specific_len =
1935 rend_service_parse_intro_for_v2(intro,
1936 buf + adjust, plaintext_len - adjust,
1937 err_msg_out);
1939 /* Success in v2 parser */
1940 if (v2_ver_specific_len >= 0) return v2_ver_specific_len + adjust;
1941 /* Failure in v2 parser; it will have provided an err_msg */
1942 else return v2_ver_specific_len;
1944 err:
1945 return -1;
1948 /** Table of parser functions for version-specific parts of an INTRODUCE2
1949 * cell.
1952 static ssize_t
1953 (*intro_version_handlers[])(
1954 rend_intro_cell_t *,
1955 const uint8_t *,
1956 size_t,
1957 char **) =
1958 { rend_service_parse_intro_for_v0_or_v1,
1959 rend_service_parse_intro_for_v0_or_v1,
1960 rend_service_parse_intro_for_v2,
1961 rend_service_parse_intro_for_v3 };
1963 /** Decrypt the encrypted part of an INTRODUCE1 or INTRODUCE2 cell,
1964 * return 0 if successful, or < 0 and write an error message to
1965 * *err_msg_out if provided.
1969 rend_service_decrypt_intro(
1970 rend_intro_cell_t *intro,
1971 crypto_pk_t *key,
1972 char **err_msg_out)
1974 char *err_msg = NULL;
1975 uint8_t key_digest[DIGEST_LEN];
1976 char service_id[REND_SERVICE_ID_LEN_BASE32+1];
1977 ssize_t key_len;
1978 uint8_t buf[RELAY_PAYLOAD_SIZE];
1979 int result, status = 0;
1981 if (!intro || !key) {
1982 if (err_msg_out) {
1983 err_msg =
1984 tor_strdup("rend_service_decrypt_intro() called with bad "
1985 "parameters");
1988 status = -2;
1989 goto err;
1992 /* Make sure we have ciphertext */
1993 if (!(intro->ciphertext) || intro->ciphertext_len <= 0) {
1994 if (err_msg_out) {
1995 tor_asprintf(&err_msg,
1996 "rend_intro_cell_t was missing ciphertext for "
1997 "INTRODUCE%d cell",
1998 (int)(intro->type));
2000 status = -3;
2001 goto err;
2004 /* Check that this cell actually matches this service key */
2006 /* first DIGEST_LEN bytes of request is intro or service pk digest */
2007 crypto_pk_get_digest(key, (char *)key_digest);
2008 if (tor_memneq(key_digest, intro->pk, DIGEST_LEN)) {
2009 if (err_msg_out) {
2010 base32_encode(service_id, REND_SERVICE_ID_LEN_BASE32 + 1,
2011 (char*)(intro->pk), REND_SERVICE_ID_LEN);
2012 tor_asprintf(&err_msg,
2013 "got an INTRODUCE%d cell for the wrong service (%s)",
2014 (int)(intro->type),
2015 escaped(service_id));
2018 status = -4;
2019 goto err;
2022 /* Make sure the encrypted part is long enough to decrypt */
2024 key_len = crypto_pk_keysize(key);
2025 if (intro->ciphertext_len < key_len) {
2026 if (err_msg_out) {
2027 tor_asprintf(&err_msg,
2028 "got an INTRODUCE%d cell with a truncated PK-encrypted "
2029 "part",
2030 (int)(intro->type));
2033 status = -5;
2034 goto err;
2037 /* Decrypt the encrypted part */
2039 note_crypto_pk_op(REND_SERVER);
2040 result =
2041 crypto_pk_private_hybrid_decrypt(
2042 key, (char *)buf, sizeof(buf),
2043 (const char *)(intro->ciphertext), intro->ciphertext_len,
2044 PK_PKCS1_OAEP_PADDING, 1);
2045 if (result < 0) {
2046 if (err_msg_out) {
2047 tor_asprintf(&err_msg,
2048 "couldn't decrypt INTRODUCE%d cell",
2049 (int)(intro->type));
2051 status = -6;
2052 goto err;
2054 intro->plaintext_len = result;
2055 intro->plaintext = tor_malloc(intro->plaintext_len);
2056 memcpy(intro->plaintext, buf, intro->plaintext_len);
2058 goto done;
2060 err:
2061 if (err_msg_out && !err_msg) {
2062 tor_asprintf(&err_msg,
2063 "unknown INTRODUCE%d error decrypting encrypted part",
2064 (int)(intro->type));
2066 if (status >= 0) status = -1;
2068 done:
2069 if (err_msg_out) *err_msg_out = err_msg;
2070 else tor_free(err_msg);
2072 /* clean up potentially sensitive material */
2073 memwipe(buf, 0, sizeof(buf));
2074 memwipe(key_digest, 0, sizeof(key_digest));
2075 memwipe(service_id, 0, sizeof(service_id));
2077 return status;
2080 /** Parse the plaintext of the encrypted part of an INTRODUCE1 or
2081 * INTRODUCE2 cell, return 0 if successful, or < 0 and write an error
2082 * message to *err_msg_out if provided.
2086 rend_service_parse_intro_plaintext(
2087 rend_intro_cell_t *intro,
2088 char **err_msg_out)
2090 char *err_msg = NULL;
2091 ssize_t ver_specific_len, ver_invariant_len;
2092 uint8_t version;
2093 int status = 0;
2095 if (!intro) {
2096 if (err_msg_out) {
2097 err_msg =
2098 tor_strdup("rend_service_parse_intro_plaintext() called with NULL "
2099 "rend_intro_cell_t");
2102 status = -2;
2103 goto err;
2106 /* Check that we have plaintext */
2107 if (!(intro->plaintext) || intro->plaintext_len <= 0) {
2108 if (err_msg_out) {
2109 err_msg = tor_strdup("rend_intro_cell_t was missing plaintext");
2111 status = -3;
2112 goto err;
2115 /* In all formats except v0, the first byte is a version number */
2116 version = intro->plaintext[0];
2118 /* v0 has no version byte (stupid...), so handle it as a fallback */
2119 if (version > 3) version = 0;
2121 /* Copy the version into the parsed cell structure */
2122 intro->version = version;
2124 /* Call the version-specific parser from the table */
2125 ver_specific_len =
2126 intro_version_handlers[version](intro,
2127 intro->plaintext, intro->plaintext_len,
2128 &err_msg);
2129 if (ver_specific_len < 0) {
2130 status = -4;
2131 goto err;
2134 /** The rendezvous cookie and Diffie-Hellman stuff are version-invariant
2135 * and at the end of the plaintext of the encrypted part of the cell.
2138 ver_invariant_len = intro->plaintext_len - ver_specific_len;
2139 if (ver_invariant_len < REND_COOKIE_LEN + DH_KEY_LEN) {
2140 tor_asprintf(&err_msg,
2141 "decrypted plaintext of INTRODUCE%d cell was truncated (%ld bytes)",
2142 (int)(intro->type),
2143 (long)(intro->plaintext_len));
2144 status = -5;
2145 goto err;
2146 } else if (ver_invariant_len > REND_COOKIE_LEN + DH_KEY_LEN) {
2147 tor_asprintf(&err_msg,
2148 "decrypted plaintext of INTRODUCE%d cell was too long (%ld bytes)",
2149 (int)(intro->type),
2150 (long)(intro->plaintext_len));
2151 status = -6;
2152 } else {
2153 memcpy(intro->rc,
2154 intro->plaintext + ver_specific_len,
2155 REND_COOKIE_LEN);
2156 memcpy(intro->dh,
2157 intro->plaintext + ver_specific_len + REND_COOKIE_LEN,
2158 DH_KEY_LEN);
2161 /* Flag it as being fully parsed */
2162 intro->parsed = 1;
2164 goto done;
2166 err:
2167 if (err_msg_out && !err_msg) {
2168 tor_asprintf(&err_msg,
2169 "unknown INTRODUCE%d error parsing encrypted part",
2170 (int)(intro->type));
2172 if (status >= 0) status = -1;
2174 done:
2175 if (err_msg_out) *err_msg_out = err_msg;
2176 else tor_free(err_msg);
2178 return status;
2181 /** Do validity checks on a parsed intro cell before decryption; some of
2182 * these are not done in rend_service_begin_parse_intro() itself because
2183 * they depend on a lot of other state and would make it hard to unit test.
2184 * Returns >= 0 if successful or < 0 if the intro cell is invalid, and
2185 * optionally writes out an error message for logging. If an err_msg
2186 * pointer is provided, it is the caller's responsibility to free any
2187 * provided message.
2191 rend_service_validate_intro_early(const rend_intro_cell_t *intro,
2192 char **err_msg_out)
2194 int status = 0;
2196 if (!intro) {
2197 if (err_msg_out)
2198 *err_msg_out =
2199 tor_strdup("NULL intro cell passed to "
2200 "rend_service_validate_intro_early()");
2202 status = -1;
2203 goto err;
2206 /* TODO */
2208 err:
2209 return status;
2212 /** Do validity checks on a parsed intro cell after decryption; some of
2213 * these are not done in rend_service_parse_intro_plaintext() itself because
2214 * they depend on a lot of other state and would make it hard to unit test.
2215 * Returns >= 0 if successful or < 0 if the intro cell is invalid, and
2216 * optionally writes out an error message for logging. If an err_msg
2217 * pointer is provided, it is the caller's responsibility to free any
2218 * provided message.
2222 rend_service_validate_intro_late(const rend_intro_cell_t *intro,
2223 char **err_msg_out)
2225 int status = 0;
2227 if (!intro) {
2228 if (err_msg_out)
2229 *err_msg_out =
2230 tor_strdup("NULL intro cell passed to "
2231 "rend_service_validate_intro_late()");
2233 status = -1;
2234 goto err;
2237 if (intro->version == 3 && intro->parsed) {
2238 if (!(intro->u.v3.auth_type == REND_NO_AUTH ||
2239 intro->u.v3.auth_type == REND_BASIC_AUTH ||
2240 intro->u.v3.auth_type == REND_STEALTH_AUTH)) {
2241 /* This is an informative message, not an error, as in the old code */
2242 if (err_msg_out)
2243 tor_asprintf(err_msg_out,
2244 "unknown authorization type %d",
2245 intro->u.v3.auth_type);
2249 err:
2250 return status;
2253 /** Called when we fail building a rendezvous circuit at some point other
2254 * than the last hop: launches a new circuit to the same rendezvous point.
2256 void
2257 rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
2259 origin_circuit_t *newcirc;
2260 cpath_build_state_t *newstate, *oldstate;
2262 tor_assert(oldcirc->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
2264 /* Don't relaunch the same rend circ twice. */
2265 if (oldcirc->hs_service_side_rend_circ_has_been_relaunched) {
2266 log_info(LD_REND, "Rendezvous circuit to %s has already been relaunched; "
2267 "not relaunching it again.",
2268 oldcirc->build_state ?
2269 safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
2270 : "*unknown*");
2271 return;
2273 oldcirc->hs_service_side_rend_circ_has_been_relaunched = 1;
2275 if (!oldcirc->build_state ||
2276 oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
2277 oldcirc->build_state->expiry_time < time(NULL)) {
2278 log_info(LD_REND,
2279 "Attempt to build circuit to %s for rendezvous has failed "
2280 "too many times or expired; giving up.",
2281 oldcirc->build_state ?
2282 safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
2283 : "*unknown*");
2284 return;
2287 oldstate = oldcirc->build_state;
2288 tor_assert(oldstate);
2290 if (oldstate->service_pending_final_cpath_ref == NULL) {
2291 log_info(LD_REND,"Skipping relaunch of circ that failed on its first hop. "
2292 "Initiator will retry.");
2293 return;
2296 log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
2297 safe_str(extend_info_describe(oldstate->chosen_exit)));
2299 newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
2300 oldstate->chosen_exit,
2301 CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
2303 if (!newcirc) {
2304 log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
2305 safe_str(extend_info_describe(oldstate->chosen_exit)));
2306 return;
2308 newstate = newcirc->build_state;
2309 tor_assert(newstate);
2310 newstate->failure_count = oldstate->failure_count+1;
2311 newstate->expiry_time = oldstate->expiry_time;
2312 newstate->service_pending_final_cpath_ref =
2313 oldstate->service_pending_final_cpath_ref;
2314 ++(newstate->service_pending_final_cpath_ref->refcount);
2316 newcirc->rend_data = rend_data_dup(oldcirc->rend_data);
2319 /** Launch a circuit to serve as an introduction point for the service
2320 * <b>service</b> at the introduction point <b>nickname</b>
2322 static int
2323 rend_service_launch_establish_intro(rend_service_t *service,
2324 rend_intro_point_t *intro)
2326 origin_circuit_t *launched;
2328 log_info(LD_REND,
2329 "Launching circuit to introduction point %s for service %s",
2330 safe_str_client(extend_info_describe(intro->extend_info)),
2331 service->service_id);
2333 rep_hist_note_used_internal(time(NULL), 1, 0);
2335 ++service->n_intro_circuits_launched;
2336 launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
2337 intro->extend_info,
2338 CIRCLAUNCH_NEED_UPTIME|CIRCLAUNCH_IS_INTERNAL);
2340 if (!launched) {
2341 log_info(LD_REND,
2342 "Can't launch circuit to establish introduction at %s.",
2343 safe_str_client(extend_info_describe(intro->extend_info)));
2344 return -1;
2347 if (tor_memneq(intro->extend_info->identity_digest,
2348 launched->build_state->chosen_exit->identity_digest, DIGEST_LEN)) {
2349 char cann[HEX_DIGEST_LEN+1], orig[HEX_DIGEST_LEN+1];
2350 base16_encode(cann, sizeof(cann),
2351 launched->build_state->chosen_exit->identity_digest,
2352 DIGEST_LEN);
2353 base16_encode(orig, sizeof(orig),
2354 intro->extend_info->identity_digest, DIGEST_LEN);
2355 log_info(LD_REND, "The intro circuit we just cannibalized ends at $%s, "
2356 "but we requested an intro circuit to $%s. Updating "
2357 "our service.", cann, orig);
2358 extend_info_free(intro->extend_info);
2359 intro->extend_info = extend_info_dup(launched->build_state->chosen_exit);
2362 launched->rend_data = tor_malloc_zero(sizeof(rend_data_t));
2363 strlcpy(launched->rend_data->onion_address, service->service_id,
2364 sizeof(launched->rend_data->onion_address));
2365 memcpy(launched->rend_data->rend_pk_digest, service->pk_digest, DIGEST_LEN);
2366 launched->intro_key = crypto_pk_dup_key(intro->intro_key);
2367 if (launched->base_.state == CIRCUIT_STATE_OPEN)
2368 rend_service_intro_has_opened(launched);
2369 return 0;
2372 /** Return the number of introduction points that are or have been
2373 * established for the given service address in <b>query</b>. */
2374 static int
2375 count_established_intro_points(const char *query)
2377 int num_ipos = 0;
2378 circuit_t *circ;
2379 TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) {
2380 if (!circ->marked_for_close &&
2381 circ->state == CIRCUIT_STATE_OPEN &&
2382 (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
2383 circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
2384 origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
2385 if (oc->rend_data &&
2386 !rend_cmp_service_ids(query, oc->rend_data->onion_address))
2387 num_ipos++;
2390 return num_ipos;
2393 /** Called when we're done building a circuit to an introduction point:
2394 * sends a RELAY_ESTABLISH_INTRO cell.
2396 void
2397 rend_service_intro_has_opened(origin_circuit_t *circuit)
2399 rend_service_t *service;
2400 size_t len;
2401 int r;
2402 char buf[RELAY_PAYLOAD_SIZE];
2403 char auth[DIGEST_LEN + 9];
2404 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2405 int reason = END_CIRC_REASON_TORPROTOCOL;
2406 crypto_pk_t *intro_key;
2408 tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
2409 #ifndef NON_ANONYMOUS_MODE_ENABLED
2410 tor_assert(!(circuit->build_state->onehop_tunnel));
2411 #endif
2412 tor_assert(circuit->cpath);
2413 tor_assert(circuit->rend_data);
2415 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
2416 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
2418 service = rend_service_get_by_pk_digest(
2419 circuit->rend_data->rend_pk_digest);
2420 if (!service) {
2421 log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %u.",
2422 serviceid, (unsigned)circuit->base_.n_circ_id);
2423 reason = END_CIRC_REASON_NOSUCHSERVICE;
2424 goto err;
2427 /* If we already have enough introduction circuits for this service,
2428 * redefine this one as a general circuit or close it, depending. */
2429 if (count_established_intro_points(serviceid) >
2430 (int)service->n_intro_points_wanted) { /* XXX023 remove cast */
2431 const or_options_t *options = get_options();
2432 if (options->ExcludeNodes) {
2433 /* XXXX in some future version, we can test whether the transition is
2434 allowed or not given the actual nodes in the circuit. But for now,
2435 this case, we might as well close the thing. */
2436 log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
2437 "circuit, but we already have enough. Closing it.");
2438 reason = END_CIRC_REASON_NONE;
2439 goto err;
2440 } else {
2441 tor_assert(circuit->build_state->is_internal);
2442 log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
2443 "circuit, but we already have enough. Redefining purpose to "
2444 "general; leaving as internal.");
2446 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_C_GENERAL);
2449 rend_data_t *rend_data = circuit->rend_data;
2450 circuit->rend_data = NULL;
2451 rend_data_free(rend_data);
2454 crypto_pk_t *intro_key = circuit->intro_key;
2455 circuit->intro_key = NULL;
2456 crypto_pk_free(intro_key);
2459 circuit_has_opened(circuit);
2460 goto done;
2464 log_info(LD_REND,
2465 "Established circuit %u as introduction point for service %s",
2466 (unsigned)circuit->base_.n_circ_id, serviceid);
2468 /* Use the intro key instead of the service key in ESTABLISH_INTRO. */
2469 intro_key = circuit->intro_key;
2470 /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
2471 r = crypto_pk_asn1_encode(intro_key, buf+2,
2472 RELAY_PAYLOAD_SIZE-2);
2473 if (r < 0) {
2474 log_warn(LD_BUG, "Internal error; failed to establish intro point.");
2475 reason = END_CIRC_REASON_INTERNAL;
2476 goto err;
2478 len = r;
2479 set_uint16(buf, htons((uint16_t)len));
2480 len += 2;
2481 memcpy(auth, circuit->cpath->prev->rend_circ_nonce, DIGEST_LEN);
2482 memcpy(auth+DIGEST_LEN, "INTRODUCE", 9);
2483 if (crypto_digest(buf+len, auth, DIGEST_LEN+9))
2484 goto err;
2485 len += 20;
2486 note_crypto_pk_op(REND_SERVER);
2487 r = crypto_pk_private_sign_digest(intro_key, buf+len, sizeof(buf)-len,
2488 buf, len);
2489 if (r<0) {
2490 log_warn(LD_BUG, "Internal error: couldn't sign introduction request.");
2491 reason = END_CIRC_REASON_INTERNAL;
2492 goto err;
2494 len += r;
2496 if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
2497 RELAY_COMMAND_ESTABLISH_INTRO,
2498 buf, len, circuit->cpath->prev)<0) {
2499 log_info(LD_GENERAL,
2500 "Couldn't send introduction request for service %s on circuit %u",
2501 serviceid, (unsigned)circuit->base_.n_circ_id);
2502 reason = END_CIRC_REASON_INTERNAL;
2503 goto err;
2506 /* We've attempted to use this circuit */
2507 pathbias_count_use_attempt(circuit);
2509 goto done;
2511 err:
2512 circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
2513 done:
2514 memwipe(buf, 0, sizeof(buf));
2515 memwipe(auth, 0, sizeof(auth));
2516 memwipe(serviceid, 0, sizeof(serviceid));
2518 return;
2521 /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
2522 * live introduction point, and note that the service descriptor is
2523 * now out-of-date. */
2525 rend_service_intro_established(origin_circuit_t *circuit,
2526 const uint8_t *request,
2527 size_t request_len)
2529 rend_service_t *service;
2530 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2531 (void) request;
2532 (void) request_len;
2534 if (circuit->base_.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
2535 log_warn(LD_PROTOCOL,
2536 "received INTRO_ESTABLISHED cell on non-intro circuit.");
2537 goto err;
2539 tor_assert(circuit->rend_data);
2540 service = rend_service_get_by_pk_digest(
2541 circuit->rend_data->rend_pk_digest);
2542 if (!service) {
2543 log_warn(LD_REND, "Unknown service on introduction circuit %u.",
2544 (unsigned)circuit->base_.n_circ_id);
2545 goto err;
2547 service->desc_is_dirty = time(NULL);
2548 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_INTRO);
2550 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32 + 1,
2551 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
2552 log_info(LD_REND,
2553 "Received INTRO_ESTABLISHED cell on circuit %u for service %s",
2554 (unsigned)circuit->base_.n_circ_id, serviceid);
2556 /* Getting a valid INTRODUCE_ESTABLISHED means we've successfully
2557 * used the circ */
2558 pathbias_mark_use_success(circuit);
2560 return 0;
2561 err:
2562 circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
2563 return -1;
2566 /** Called once a circuit to a rendezvous point is established: sends a
2567 * RELAY_COMMAND_RENDEZVOUS1 cell.
2569 void
2570 rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
2572 rend_service_t *service;
2573 char buf[RELAY_PAYLOAD_SIZE];
2574 crypt_path_t *hop;
2575 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2576 char hexcookie[9];
2577 int reason;
2579 tor_assert(circuit->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
2580 tor_assert(circuit->cpath);
2581 tor_assert(circuit->build_state);
2582 #ifndef NON_ANONYMOUS_MODE_ENABLED
2583 tor_assert(!(circuit->build_state->onehop_tunnel));
2584 #endif
2585 tor_assert(circuit->rend_data);
2587 /* Declare the circuit dirty to avoid reuse, and for path-bias */
2588 if (!circuit->base_.timestamp_dirty)
2589 circuit->base_.timestamp_dirty = time(NULL);
2591 /* This may be redundant */
2592 pathbias_count_use_attempt(circuit);
2594 hop = circuit->build_state->service_pending_final_cpath_ref->cpath;
2596 base16_encode(hexcookie,9,circuit->rend_data->rend_cookie,4);
2597 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
2598 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
2600 log_info(LD_REND,
2601 "Done building circuit %u to rendezvous with "
2602 "cookie %s for service %s",
2603 (unsigned)circuit->base_.n_circ_id, hexcookie, serviceid);
2605 /* Clear the 'in-progress HS circ has timed out' flag for
2606 * consistency with what happens on the client side; this line has
2607 * no effect on Tor's behaviour. */
2608 circuit->hs_circ_has_timed_out = 0;
2610 /* If hop is NULL, another rend circ has already connected to this
2611 * rend point. Close this circ. */
2612 if (hop == NULL) {
2613 log_info(LD_REND, "Another rend circ has already reached this rend point; "
2614 "closing this rend circ.");
2615 reason = END_CIRC_REASON_NONE;
2616 goto err;
2619 /* Remove our final cpath element from the reference, so that no
2620 * other circuit will try to use it. Store it in
2621 * pending_final_cpath for now to ensure that it will be freed if
2622 * our rendezvous attempt fails. */
2623 circuit->build_state->pending_final_cpath = hop;
2624 circuit->build_state->service_pending_final_cpath_ref->cpath = NULL;
2626 service = rend_service_get_by_pk_digest(
2627 circuit->rend_data->rend_pk_digest);
2628 if (!service) {
2629 log_warn(LD_GENERAL, "Internal error: unrecognized service ID on "
2630 "rendezvous circuit.");
2631 reason = END_CIRC_REASON_INTERNAL;
2632 goto err;
2635 /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
2636 memcpy(buf, circuit->rend_data->rend_cookie, REND_COOKIE_LEN);
2637 if (crypto_dh_get_public(hop->rend_dh_handshake_state,
2638 buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
2639 log_warn(LD_GENERAL,"Couldn't get DH public key.");
2640 reason = END_CIRC_REASON_INTERNAL;
2641 goto err;
2643 memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->rend_circ_nonce,
2644 DIGEST_LEN);
2646 /* Send the cell */
2647 if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
2648 RELAY_COMMAND_RENDEZVOUS1,
2649 buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
2650 circuit->cpath->prev)<0) {
2651 log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
2652 reason = END_CIRC_REASON_INTERNAL;
2653 goto err;
2656 crypto_dh_free(hop->rend_dh_handshake_state);
2657 hop->rend_dh_handshake_state = NULL;
2659 /* Append the cpath entry. */
2660 hop->state = CPATH_STATE_OPEN;
2661 /* set the windows to default. these are the windows
2662 * that bob thinks alice has.
2664 hop->package_window = circuit_initial_package_window();
2665 hop->deliver_window = CIRCWINDOW_START;
2667 onion_append_to_cpath(&circuit->cpath, hop);
2668 circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
2670 /* Change the circuit purpose. */
2671 circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_REND_JOINED);
2673 goto done;
2675 err:
2676 circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
2677 done:
2678 memwipe(buf, 0, sizeof(buf));
2679 memwipe(serviceid, 0, sizeof(serviceid));
2680 memwipe(hexcookie, 0, sizeof(hexcookie));
2682 return;
2686 * Manage introduction points
2689 /** Return the (possibly non-open) introduction circuit ending at
2690 * <b>intro</b> for the service whose public key is <b>pk_digest</b>.
2691 * (<b>desc_version</b> is ignored). Return NULL if no such service is
2692 * found.
2694 static origin_circuit_t *
2695 find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
2697 origin_circuit_t *circ = NULL;
2699 tor_assert(intro);
2700 while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
2701 CIRCUIT_PURPOSE_S_INTRO))) {
2702 if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
2703 intro->extend_info->identity_digest, DIGEST_LEN) &&
2704 circ->rend_data) {
2705 return circ;
2709 circ = NULL;
2710 while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
2711 CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
2712 if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
2713 intro->extend_info->identity_digest, DIGEST_LEN) &&
2714 circ->rend_data) {
2715 return circ;
2718 return NULL;
2721 /** Return a pointer to the rend_intro_point_t corresponding to the
2722 * service-side introduction circuit <b>circ</b>. */
2723 static rend_intro_point_t *
2724 find_intro_point(origin_circuit_t *circ)
2726 const char *serviceid;
2727 rend_service_t *service = NULL;
2729 tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
2730 TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO);
2731 tor_assert(circ->rend_data);
2732 serviceid = circ->rend_data->onion_address;
2734 SMARTLIST_FOREACH(rend_service_list, rend_service_t *, s,
2735 if (tor_memeq(s->service_id, serviceid, REND_SERVICE_ID_LEN_BASE32)) {
2736 service = s;
2737 break;
2740 if (service == NULL) return NULL;
2742 SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro_point,
2743 if (crypto_pk_eq_keys(intro_point->intro_key, circ->intro_key)) {
2744 return intro_point;
2747 return NULL;
2750 /** Determine the responsible hidden service directories for the
2751 * rend_encoded_v2_service_descriptor_t's in <b>descs</b> and upload them;
2752 * <b>service_id</b> and <b>seconds_valid</b> are only passed for logging
2753 * purposes. */
2754 static void
2755 directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
2756 smartlist_t *descs, const char *service_id,
2757 int seconds_valid)
2759 int i, j, failed_upload = 0;
2760 smartlist_t *responsible_dirs = smartlist_new();
2761 smartlist_t *successful_uploads = smartlist_new();
2762 routerstatus_t *hs_dir;
2763 for (i = 0; i < smartlist_len(descs); i++) {
2764 rend_encoded_v2_service_descriptor_t *desc = smartlist_get(descs, i);
2765 /* Determine responsible dirs. */
2766 if (hid_serv_get_responsible_directories(responsible_dirs,
2767 desc->desc_id) < 0) {
2768 log_warn(LD_REND, "Could not determine the responsible hidden service "
2769 "directories to post descriptors to.");
2770 smartlist_free(responsible_dirs);
2771 smartlist_free(successful_uploads);
2772 return;
2774 for (j = 0; j < smartlist_len(responsible_dirs); j++) {
2775 char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
2776 char *hs_dir_ip;
2777 const node_t *node;
2778 hs_dir = smartlist_get(responsible_dirs, j);
2779 if (smartlist_contains_digest(renddesc->successful_uploads,
2780 hs_dir->identity_digest))
2781 /* Don't upload descriptor if we succeeded in doing so last time. */
2782 continue;
2783 node = node_get_by_id(hs_dir->identity_digest);
2784 if (!node || !node_has_descriptor(node)) {
2785 log_info(LD_REND, "Not launching upload for for v2 descriptor to "
2786 "hidden service directory %s; we don't have its "
2787 "router descriptor. Queuing for later upload.",
2788 safe_str_client(routerstatus_describe(hs_dir)));
2789 failed_upload = -1;
2790 continue;
2792 /* Send publish request. */
2793 directory_initiate_command_routerstatus(hs_dir,
2794 DIR_PURPOSE_UPLOAD_RENDDESC_V2,
2795 ROUTER_PURPOSE_GENERAL,
2796 DIRIND_ANONYMOUS, NULL,
2797 desc->desc_str,
2798 strlen(desc->desc_str), 0);
2799 base32_encode(desc_id_base32, sizeof(desc_id_base32),
2800 desc->desc_id, DIGEST_LEN);
2801 hs_dir_ip = tor_dup_ip(hs_dir->addr);
2802 log_info(LD_REND, "Launching upload for v2 descriptor for "
2803 "service '%s' with descriptor ID '%s' with validity "
2804 "of %d seconds to hidden service directory '%s' on "
2805 "%s:%d.",
2806 safe_str_client(service_id),
2807 safe_str_client(desc_id_base32),
2808 seconds_valid,
2809 hs_dir->nickname,
2810 hs_dir_ip,
2811 hs_dir->or_port);
2812 tor_free(hs_dir_ip);
2813 /* Remember successful upload to this router for next time. */
2814 if (!smartlist_contains_digest(successful_uploads,
2815 hs_dir->identity_digest))
2816 smartlist_add(successful_uploads, hs_dir->identity_digest);
2818 smartlist_clear(responsible_dirs);
2820 if (!failed_upload) {
2821 if (renddesc->successful_uploads) {
2822 SMARTLIST_FOREACH(renddesc->successful_uploads, char *, c, tor_free(c););
2823 smartlist_free(renddesc->successful_uploads);
2824 renddesc->successful_uploads = NULL;
2826 renddesc->all_uploads_performed = 1;
2827 } else {
2828 /* Remember which routers worked this time, so that we don't upload the
2829 * descriptor to them again. */
2830 if (!renddesc->successful_uploads)
2831 renddesc->successful_uploads = smartlist_new();
2832 SMARTLIST_FOREACH(successful_uploads, const char *, c, {
2833 if (!smartlist_contains_digest(renddesc->successful_uploads, c)) {
2834 char *hsdir_id = tor_memdup(c, DIGEST_LEN);
2835 smartlist_add(renddesc->successful_uploads, hsdir_id);
2839 smartlist_free(responsible_dirs);
2840 smartlist_free(successful_uploads);
2843 /** Encode and sign an up-to-date service descriptor for <b>service</b>,
2844 * and upload it/them to the responsible hidden service directories.
2846 static void
2847 upload_service_descriptor(rend_service_t *service)
2849 time_t now = time(NULL);
2850 int rendpostperiod;
2851 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
2852 int uploaded = 0;
2854 rendpostperiod = get_options()->RendPostPeriod;
2856 /* Upload descriptor? */
2857 if (get_options()->PublishHidServDescriptors) {
2858 networkstatus_t *c = networkstatus_get_latest_consensus();
2859 if (c && smartlist_len(c->routerstatus_list) > 0) {
2860 int seconds_valid, i, j, num_descs;
2861 smartlist_t *descs = smartlist_new();
2862 smartlist_t *client_cookies = smartlist_new();
2863 /* Either upload a single descriptor (including replicas) or one
2864 * descriptor for each authorized client in case of authorization
2865 * type 'stealth'. */
2866 num_descs = service->auth_type == REND_STEALTH_AUTH ?
2867 smartlist_len(service->clients) : 1;
2868 for (j = 0; j < num_descs; j++) {
2869 crypto_pk_t *client_key = NULL;
2870 rend_authorized_client_t *client = NULL;
2871 smartlist_clear(client_cookies);
2872 switch (service->auth_type) {
2873 case REND_NO_AUTH:
2874 /* Do nothing here. */
2875 break;
2876 case REND_BASIC_AUTH:
2877 SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *,
2878 cl, smartlist_add(client_cookies, cl->descriptor_cookie));
2879 break;
2880 case REND_STEALTH_AUTH:
2881 client = smartlist_get(service->clients, j);
2882 client_key = client->client_key;
2883 smartlist_add(client_cookies, client->descriptor_cookie);
2884 break;
2886 /* Encode the current descriptor. */
2887 seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
2888 now, 0,
2889 service->auth_type,
2890 client_key,
2891 client_cookies);
2892 if (seconds_valid < 0) {
2893 log_warn(LD_BUG, "Internal error: couldn't encode service "
2894 "descriptor; not uploading.");
2895 smartlist_free(descs);
2896 smartlist_free(client_cookies);
2897 return;
2899 /* Post the current descriptors to the hidden service directories. */
2900 rend_get_service_id(service->desc->pk, serviceid);
2901 log_info(LD_REND, "Launching upload for hidden service %s",
2902 serviceid);
2903 directory_post_to_hs_dir(service->desc, descs, serviceid,
2904 seconds_valid);
2905 /* Free memory for descriptors. */
2906 for (i = 0; i < smartlist_len(descs); i++)
2907 rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
2908 smartlist_clear(descs);
2909 /* Update next upload time. */
2910 if (seconds_valid - REND_TIME_PERIOD_OVERLAPPING_V2_DESCS
2911 > rendpostperiod)
2912 service->next_upload_time = now + rendpostperiod;
2913 else if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS)
2914 service->next_upload_time = now + seconds_valid + 1;
2915 else
2916 service->next_upload_time = now + seconds_valid -
2917 REND_TIME_PERIOD_OVERLAPPING_V2_DESCS + 1;
2918 /* Post also the next descriptors, if necessary. */
2919 if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS) {
2920 seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
2921 now, 1,
2922 service->auth_type,
2923 client_key,
2924 client_cookies);
2925 if (seconds_valid < 0) {
2926 log_warn(LD_BUG, "Internal error: couldn't encode service "
2927 "descriptor; not uploading.");
2928 smartlist_free(descs);
2929 smartlist_free(client_cookies);
2930 return;
2932 directory_post_to_hs_dir(service->desc, descs, serviceid,
2933 seconds_valid);
2934 /* Free memory for descriptors. */
2935 for (i = 0; i < smartlist_len(descs); i++)
2936 rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
2937 smartlist_clear(descs);
2940 smartlist_free(descs);
2941 smartlist_free(client_cookies);
2942 uploaded = 1;
2943 log_info(LD_REND, "Successfully uploaded v2 rend descriptors!");
2947 /* If not uploaded, try again in one minute. */
2948 if (!uploaded)
2949 service->next_upload_time = now + 60;
2951 /* Unmark dirty flag of this service. */
2952 service->desc_is_dirty = 0;
2955 /** Return the number of INTRODUCE2 cells this hidden service has received
2956 * from this intro point. */
2957 static int
2958 intro_point_accepted_intro_count(rend_intro_point_t *intro)
2960 return intro->accepted_introduce2_count;
2963 /** Return non-zero iff <b>intro</b> should 'expire' now (i.e. we
2964 * should stop publishing it in new descriptors and eventually close
2965 * it). */
2966 static int
2967 intro_point_should_expire_now(rend_intro_point_t *intro,
2968 time_t now)
2970 tor_assert(intro != NULL);
2972 if (intro->time_published == -1) {
2973 /* Don't expire an intro point if we haven't even published it yet. */
2974 return 0;
2977 if (intro->time_expiring != -1) {
2978 /* We've already started expiring this intro point. *Don't* let
2979 * this function's result 'flap'. */
2980 return 1;
2983 if (intro_point_accepted_intro_count(intro) >=
2984 INTRO_POINT_LIFETIME_INTRODUCTIONS) {
2985 /* This intro point has been used too many times. Expire it now. */
2986 return 1;
2989 if (intro->time_to_expire == -1) {
2990 /* This intro point has been published, but we haven't picked an
2991 * expiration time for it. Pick one now. */
2992 int intro_point_lifetime_seconds =
2993 INTRO_POINT_LIFETIME_MIN_SECONDS +
2994 crypto_rand_int(INTRO_POINT_LIFETIME_MAX_SECONDS -
2995 INTRO_POINT_LIFETIME_MIN_SECONDS);
2997 /* Start the expiration timer now, rather than when the intro
2998 * point was first published. There shouldn't be much of a time
2999 * difference. */
3000 intro->time_to_expire = now + intro_point_lifetime_seconds;
3002 return 0;
3005 /* This intro point has a time to expire set already. Use it. */
3006 return (now >= intro->time_to_expire);
3009 /** For every service, check how many intro points it currently has, and:
3010 * - Pick new intro points as necessary.
3011 * - Launch circuits to any new intro points.
3013 void
3014 rend_services_introduce(void)
3016 int i,j,r;
3017 const node_t *node;
3018 rend_service_t *service;
3019 rend_intro_point_t *intro;
3020 int intro_point_set_changed, prev_intro_nodes;
3021 unsigned int n_intro_points_unexpired;
3022 unsigned int n_intro_points_to_open;
3023 smartlist_t *intro_nodes;
3024 time_t now;
3025 const or_options_t *options = get_options();
3027 intro_nodes = smartlist_new();
3028 now = time(NULL);
3030 for (i=0; i < smartlist_len(rend_service_list); ++i) {
3031 smartlist_clear(intro_nodes);
3032 service = smartlist_get(rend_service_list, i);
3034 tor_assert(service);
3036 /* intro_point_set_changed becomes non-zero iff the set of intro
3037 * points to be published in service's descriptor has changed. */
3038 intro_point_set_changed = 0;
3040 /* n_intro_points_unexpired collects the number of non-expiring
3041 * intro points we have, so that we know how many new intro
3042 * circuits we need to launch for this service. */
3043 n_intro_points_unexpired = 0;
3045 if (now > service->intro_period_started+INTRO_CIRC_RETRY_PERIOD) {
3046 /* One period has elapsed; we can try building circuits again. */
3047 service->intro_period_started = now;
3048 service->n_intro_circuits_launched = 0;
3049 } else if (service->n_intro_circuits_launched >=
3050 MAX_INTRO_CIRCS_PER_PERIOD) {
3051 /* We have failed too many times in this period; wait for the next
3052 * one before we try again. */
3053 continue;
3056 /* Find out which introduction points we have in progress for this
3057 service. */
3058 SMARTLIST_FOREACH_BEGIN(service->intro_nodes, rend_intro_point_t *,
3059 intro) {
3060 origin_circuit_t *intro_circ =
3061 find_intro_circuit(intro, service->pk_digest);
3063 if (intro->time_expiring + INTRO_POINT_EXPIRATION_GRACE_PERIOD > now) {
3064 /* This intro point has completely expired. Remove it, and
3065 * mark the circuit for close if it's still alive. */
3066 if (intro_circ != NULL &&
3067 intro_circ->base_.purpose != CIRCUIT_PURPOSE_PATH_BIAS_TESTING) {
3068 circuit_mark_for_close(TO_CIRCUIT(intro_circ),
3069 END_CIRC_REASON_FINISHED);
3071 rend_intro_point_free(intro);
3072 intro = NULL; /* SMARTLIST_DEL_CURRENT takes a name, not a value. */
3073 SMARTLIST_DEL_CURRENT(service->intro_nodes, intro);
3074 /* We don't need to set intro_point_set_changed here, because
3075 * this intro point wouldn't have been published in a current
3076 * descriptor anyway. */
3077 continue;
3080 node = node_get_by_id(intro->extend_info->identity_digest);
3081 if (!node || !intro_circ) {
3082 int removing_this_intro_point_changes_the_intro_point_set = 1;
3083 log_info(LD_REND, "Giving up on %s as intro point for %s"
3084 " (circuit disappeared).",
3085 safe_str_client(extend_info_describe(intro->extend_info)),
3086 safe_str_client(service->service_id));
3087 rend_service_note_removing_intro_point(service, intro);
3088 if (intro->time_expiring != -1) {
3089 log_info(LD_REND, "We were already expiring the intro point; "
3090 "no need to mark the HS descriptor as dirty over this.");
3091 removing_this_intro_point_changes_the_intro_point_set = 0;
3092 } else if (intro->listed_in_last_desc) {
3093 log_info(LD_REND, "The intro point we are giving up on was "
3094 "included in the last published descriptor. "
3095 "Marking current descriptor as dirty.");
3096 service->desc_is_dirty = now;
3098 rend_intro_point_free(intro);
3099 intro = NULL; /* SMARTLIST_DEL_CURRENT takes a name, not a value. */
3100 SMARTLIST_DEL_CURRENT(service->intro_nodes, intro);
3101 if (removing_this_intro_point_changes_the_intro_point_set)
3102 intro_point_set_changed = 1;
3105 if (intro != NULL && intro_point_should_expire_now(intro, now)) {
3106 log_info(LD_REND, "Expiring %s as intro point for %s.",
3107 safe_str_client(extend_info_describe(intro->extend_info)),
3108 safe_str_client(service->service_id));
3110 rend_service_note_removing_intro_point(service, intro);
3112 /* The polite (and generally Right) way to expire an intro
3113 * point is to establish a new one to replace it, publish a
3114 * new descriptor that doesn't list any expiring intro points,
3115 * and *then*, once our upload attempts for the new descriptor
3116 * have ended (whether in success or failure), close the
3117 * expiring intro points.
3119 * Unfortunately, we can't find out when the new descriptor
3120 * has actually been uploaded, so we'll have to settle for a
3121 * five-minute timer. Start it. XXXX024 This sucks. */
3122 intro->time_expiring = now;
3124 intro_point_set_changed = 1;
3127 if (intro != NULL && intro->time_expiring == -1)
3128 ++n_intro_points_unexpired;
3130 if (node)
3131 smartlist_add(intro_nodes, (void*)node);
3132 } SMARTLIST_FOREACH_END(intro);
3134 if (!intro_point_set_changed &&
3135 (n_intro_points_unexpired >= service->n_intro_points_wanted)) {
3136 continue;
3139 /* Remember how many introduction circuits we started with.
3141 * prev_intro_nodes serves a different purpose than
3142 * n_intro_points_unexpired -- this variable tells us where our
3143 * previously-created intro points end and our new ones begin in
3144 * the intro-point list, so we don't have to launch the circuits
3145 * at the same time as we create the intro points they correspond
3146 * to. XXXX This is daft. */
3147 prev_intro_nodes = smartlist_len(service->intro_nodes);
3149 /* We have enough directory information to start establishing our
3150 * intro points. We want to end up with n_intro_points_wanted
3151 * intro points, but if we're just starting, we launch two extra
3152 * circuits and use the first n_intro_points_wanted that complete.
3154 * The ones after the first three will be converted to 'general'
3155 * internal circuits in rend_service_intro_has_opened(), and then
3156 * we'll drop them from the list of intro points next time we
3157 * go through the above "find out which introduction points we have
3158 * in progress" loop. */
3159 n_intro_points_to_open = (service->n_intro_points_wanted +
3160 (prev_intro_nodes == 0 ? 2 : 0));
3161 for (j = (int)n_intro_points_unexpired;
3162 j < (int)n_intro_points_to_open;
3163 ++j) { /* XXXX remove casts */
3164 router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
3165 if (get_options()->AllowInvalid_ & ALLOW_INVALID_INTRODUCTION)
3166 flags |= CRN_ALLOW_INVALID;
3167 node = router_choose_random_node(intro_nodes,
3168 options->ExcludeNodes, flags);
3169 if (!node) {
3170 log_warn(LD_REND,
3171 "Could only establish %d introduction points for %s; "
3172 "wanted %u.",
3173 smartlist_len(service->intro_nodes), service->service_id,
3174 n_intro_points_to_open);
3175 break;
3177 intro_point_set_changed = 1;
3178 smartlist_add(intro_nodes, (void*)node);
3179 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
3180 intro->extend_info = extend_info_from_node(node, 0);
3181 intro->intro_key = crypto_pk_new();
3182 tor_assert(!crypto_pk_generate_key(intro->intro_key));
3183 intro->time_published = -1;
3184 intro->time_to_expire = -1;
3185 intro->time_expiring = -1;
3186 smartlist_add(service->intro_nodes, intro);
3187 log_info(LD_REND, "Picked router %s as an intro point for %s.",
3188 safe_str_client(node_describe(node)),
3189 safe_str_client(service->service_id));
3192 /* If there's no need to launch new circuits, stop here. */
3193 if (!intro_point_set_changed)
3194 continue;
3196 /* Establish new introduction points. */
3197 for (j=prev_intro_nodes; j < smartlist_len(service->intro_nodes); ++j) {
3198 intro = smartlist_get(service->intro_nodes, j);
3199 r = rend_service_launch_establish_intro(service, intro);
3200 if (r<0) {
3201 log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
3202 safe_str_client(extend_info_describe(intro->extend_info)),
3203 safe_str_client(service->service_id));
3207 smartlist_free(intro_nodes);
3210 /** Regenerate and upload rendezvous service descriptors for all
3211 * services, if necessary. If the descriptor has been dirty enough
3212 * for long enough, definitely upload; else only upload when the
3213 * periodic timeout has expired.
3215 * For the first upload, pick a random time between now and two periods
3216 * from now, and pick it independently for each service.
3218 void
3219 rend_consider_services_upload(time_t now)
3221 int i;
3222 rend_service_t *service;
3223 int rendpostperiod = get_options()->RendPostPeriod;
3225 if (!get_options()->PublishHidServDescriptors)
3226 return;
3228 for (i=0; i < smartlist_len(rend_service_list); ++i) {
3229 service = smartlist_get(rend_service_list, i);
3230 if (!service->next_upload_time) { /* never been uploaded yet */
3231 /* The fixed lower bound of 30 seconds ensures that the descriptor
3232 * is stable before being published. See comment below. */
3233 service->next_upload_time =
3234 now + 30 + crypto_rand_int(2*rendpostperiod);
3236 if (service->next_upload_time < now ||
3237 (service->desc_is_dirty &&
3238 service->desc_is_dirty < now-30)) {
3239 /* if it's time, or if the directory servers have a wrong service
3240 * descriptor and ours has been stable for 30 seconds, upload a
3241 * new one of each format. */
3242 rend_service_update_descriptor(service);
3243 upload_service_descriptor(service);
3248 /** True if the list of available router descriptors might have changed so
3249 * that we should have a look whether we can republish previously failed
3250 * rendezvous service descriptors. */
3251 static int consider_republishing_rend_descriptors = 1;
3253 /** Called when our internal view of the directory has changed, so that we
3254 * might have router descriptors of hidden service directories available that
3255 * we did not have before. */
3256 void
3257 rend_hsdir_routers_changed(void)
3259 consider_republishing_rend_descriptors = 1;
3262 /** Consider republication of v2 rendezvous service descriptors that failed
3263 * previously, but without regenerating descriptor contents.
3265 void
3266 rend_consider_descriptor_republication(void)
3268 int i;
3269 rend_service_t *service;
3271 if (!consider_republishing_rend_descriptors)
3272 return;
3273 consider_republishing_rend_descriptors = 0;
3275 if (!get_options()->PublishHidServDescriptors)
3276 return;
3278 for (i=0; i < smartlist_len(rend_service_list); ++i) {
3279 service = smartlist_get(rend_service_list, i);
3280 if (service->desc && !service->desc->all_uploads_performed) {
3281 /* If we failed in uploading a descriptor last time, try again *without*
3282 * updating the descriptor's contents. */
3283 upload_service_descriptor(service);
3288 /** Log the status of introduction points for all rendezvous services
3289 * at log severity <b>severity</b>.
3291 void
3292 rend_service_dump_stats(int severity)
3294 int i,j;
3295 rend_service_t *service;
3296 rend_intro_point_t *intro;
3297 const char *safe_name;
3298 origin_circuit_t *circ;
3300 for (i=0; i < smartlist_len(rend_service_list); ++i) {
3301 service = smartlist_get(rend_service_list, i);
3302 tor_log(severity, LD_GENERAL, "Service configured in \"%s\":",
3303 service->directory);
3304 for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
3305 intro = smartlist_get(service->intro_nodes, j);
3306 safe_name = safe_str_client(intro->extend_info->nickname);
3308 circ = find_intro_circuit(intro, service->pk_digest);
3309 if (!circ) {
3310 tor_log(severity, LD_GENERAL, " Intro point %d at %s: no circuit",
3311 j, safe_name);
3312 continue;
3314 tor_log(severity, LD_GENERAL, " Intro point %d at %s: circuit is %s",
3315 j, safe_name, circuit_state_to_string(circ->base_.state));
3320 /** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
3321 * 'circ', and look up the port and address based on conn-\>port.
3322 * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
3323 * or 0 for success.
3326 rend_service_set_connection_addr_port(edge_connection_t *conn,
3327 origin_circuit_t *circ)
3329 rend_service_t *service;
3330 char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
3331 smartlist_t *matching_ports;
3332 rend_service_port_config_t *chosen_port;
3334 tor_assert(circ->base_.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
3335 tor_assert(circ->rend_data);
3336 log_debug(LD_REND,"beginning to hunt for addr/port");
3337 base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
3338 circ->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
3339 service = rend_service_get_by_pk_digest(
3340 circ->rend_data->rend_pk_digest);
3341 if (!service) {
3342 log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
3343 "rendezvous circuit %u; closing.",
3344 serviceid, (unsigned)circ->base_.n_circ_id);
3345 return -1;
3347 matching_ports = smartlist_new();
3348 SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
3350 if (conn->base_.port == p->virtual_port) {
3351 smartlist_add(matching_ports, p);
3354 chosen_port = smartlist_choose(matching_ports);
3355 smartlist_free(matching_ports);
3356 if (chosen_port) {
3357 tor_addr_copy(&conn->base_.addr, &chosen_port->real_addr);
3358 conn->base_.port = chosen_port->real_port;
3359 return 0;
3361 log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
3362 conn->base_.port,serviceid);
3363 return -1;