Add some "to-be-safe" escaped() wrappers to log statements in rend*.c, though I am...
[tor.git] / src / or / rendservice.c
blob9a63e8cb22280ae94a9daa57b88623113cb83b89
1 /* Copyright 2004-2006 Roger Dingledine, Nick Mathewson. */
2 /* See LICENSE for licensing information */
3 /* $Id$ */
4 const char rendservice_c_id[] =
5 "$Id$";
7 /**
8 * \file rendservice.c
9 * \brief The hidden-service side of rendezvous functionality.
10 **/
12 #include "or.h"
14 static circuit_t *find_intro_circuit(routerinfo_t *router,
15 const char *pk_digest);
17 /** Represents the mapping from a virtual port of a rendezvous service to
18 * a real port on some IP.
20 typedef struct rend_service_port_config_t {
21 uint16_t virtual_port;
22 uint16_t real_port;
23 uint32_t real_addr;
24 } rend_service_port_config_t;
26 /** Try to maintain this many intro points per service if possible. */
27 #define NUM_INTRO_POINTS 3
29 /** If we can't build our intro circuits, don't retry for this long. */
30 #define INTRO_CIRC_RETRY_PERIOD 60*5
31 /** Don't try to build more than this many circuits before giving up
32 * for a while.*/
33 #define MAX_INTRO_CIRCS_PER_PERIOD 10
34 /** How many times will a hidden service operator attempt to connect to
35 * a requested rendezvous point before giving up? */
36 #define MAX_REND_FAILURES 30
37 /** How many seconds should we spend trying to connect to a requested
38 * rendezvous point before giving up? */
39 #define MAX_REND_TIMEOUT 30
41 /** Represents a single hidden service running at this OP. */
42 typedef struct rend_service_t {
43 /** Fields specified in config file */
44 char *directory; /**< where in the filesystem it stores it */
45 smartlist_t *ports; /**< List of rend_service_port_config_t */
46 char *intro_prefer_nodes; /**< comma-separated list of nicknames */
47 char *intro_exclude_nodes; /**< comma-separated list of nicknames */
48 /* Other fields */
49 crypto_pk_env_t *private_key;
50 char service_id[REND_SERVICE_ID_LEN+1];
51 char pk_digest[DIGEST_LEN];
52 smartlist_t *intro_nodes; /**< list of hexdigests for intro points we have,
53 * or are trying to establish. */
54 time_t intro_period_started;
55 int n_intro_circuits_launched; /**< count of intro circuits we have
56 * established in this period. */
57 rend_service_descriptor_t *desc;
58 time_t desc_is_dirty;
59 time_t next_upload_time;
60 } rend_service_t;
62 /** A list of rend_service_t's for services run on this OP.
64 static smartlist_t *rend_service_list = NULL;
66 /** Return the number of rendezvous services we have configured. */
67 int
68 num_rend_services(void)
70 if (!rend_service_list)
71 return 0;
72 return smartlist_len(rend_service_list);
75 /** Release the storage held by <b>service</b>.
77 static void
78 rend_service_free(rend_service_t *service)
80 if (!service) return;
81 tor_free(service->directory);
82 SMARTLIST_FOREACH(service->ports, void*, p, tor_free(p));
83 smartlist_free(service->ports);
84 if (service->private_key)
85 crypto_free_pk_env(service->private_key);
86 tor_free(service->intro_prefer_nodes);
87 tor_free(service->intro_exclude_nodes);
88 SMARTLIST_FOREACH(service->intro_nodes, void*, p, tor_free(p));
89 smartlist_free(service->intro_nodes);
90 if (service->desc)
91 rend_service_descriptor_free(service->desc);
92 tor_free(service);
95 /** Release all the storage held in rend_service_list.
97 void
98 rend_service_free_all(void)
100 if (!rend_service_list) {
101 return;
103 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
104 rend_service_free(ptr));
105 smartlist_free(rend_service_list);
106 rend_service_list = NULL;
109 /** Validate <b>service</b> and add it to rend_service_list if possible.
111 static void
112 add_service(rend_service_t *service)
114 int i;
115 rend_service_port_config_t *p;
116 struct in_addr addr;
118 if (!service->intro_prefer_nodes)
119 service->intro_prefer_nodes = tor_strdup("");
120 if (!service->intro_exclude_nodes)
121 service->intro_exclude_nodes = tor_strdup("");
123 if (!smartlist_len(service->ports)) {
124 log_warn(LD_CONFIG, "Hidden service with no ports configured; ignoring.");
125 rend_service_free(service);
126 } else {
127 smartlist_set_capacity(service->ports, -1);
128 smartlist_add(rend_service_list, service);
129 log_debug(LD_REND,"Configuring service with directory \"%s\"",
130 service->directory);
131 for (i = 0; i < smartlist_len(service->ports); ++i) {
132 char addrbuf[INET_NTOA_BUF_LEN];
133 p = smartlist_get(service->ports, i);
134 addr.s_addr = htonl(p->real_addr);
135 tor_inet_ntoa(&addr, addrbuf, sizeof(addrbuf));
136 log_debug(LD_REND,"Service maps port %d to %s:%d",
137 p->virtual_port, addrbuf, p->real_port);
142 /** Parses a real-port to virtual-port mapping and returns a new
143 * rend_service_port_config_t.
145 * The format is: VirtualPort (IP|RealPort|IP:RealPort)?
147 * IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
149 static rend_service_port_config_t *
150 parse_port_config(const char *string)
152 smartlist_t *sl;
153 int virtport;
154 int realport;
155 uint16_t p;
156 uint32_t addr;
157 const char *addrport;
158 rend_service_port_config_t *result = NULL;
160 sl = smartlist_create();
161 smartlist_split_string(sl, string, " ",
162 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
163 if (smartlist_len(sl) < 1 || smartlist_len(sl) > 2) {
164 log_warn(LD_CONFIG, "Bad syntax in hidden service port configuration.");
165 goto err;
168 virtport = atoi(smartlist_get(sl,0));
169 if (virtport < 1 || virtport > 65535) {
170 log_warn(LD_CONFIG, "Missing or invalid port in hidden service port "
171 "configuration.");
172 goto err;
175 if (smartlist_len(sl) == 1) {
176 /* No addr:port part; use default. */
177 realport = virtport;
178 addr = 0x7F000001u; /* 127.0.0.1 */
179 } else {
180 addrport = smartlist_get(sl,1);
181 if (strchr(addrport, ':') || strchr(addrport, '.')) {
182 if (parse_addr_port(addrport, NULL, &addr, &p)<0) {
183 log_warn(LD_CONFIG,"Unparseable address in hidden service port "
184 "configuration.");
185 goto err;
187 realport = p?p:virtport;
188 } else {
189 /* No addr:port, no addr -- must be port. */
190 realport = atoi(addrport);
191 if (realport < 1 || realport > 65535)
192 goto err;
193 addr = 0x7F000001u; /* Default to 127.0.0.1 */
197 result = tor_malloc(sizeof(rend_service_port_config_t));
198 result->virtual_port = virtport;
199 result->real_port = realport;
200 result->real_addr = addr;
201 err:
202 SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
203 smartlist_free(sl);
204 return result;
207 /** Set up rend_service_list, based on the values of HiddenServiceDir and
208 * HiddenServicePort in <b>options</b>. Return 0 on success and -1 on
209 * failure. (If <b>validate_only</b> is set, parse, warn and return as
210 * normal, but don't actually change the configured services.)
213 rend_config_services(or_options_t *options, int validate_only)
215 config_line_t *line;
216 rend_service_t *service = NULL;
217 rend_service_port_config_t *portcfg;
219 if (!validate_only) {
220 rend_service_free_all();
221 rend_service_list = smartlist_create();
224 for (line = options->RendConfigLines; line; line = line->next) {
225 if (!strcasecmp(line->key, "HiddenServiceDir")) {
226 if (service) {
227 if (validate_only)
228 rend_service_free(service);
229 else
230 add_service(service);
232 service = tor_malloc_zero(sizeof(rend_service_t));
233 service->directory = tor_strdup(line->value);
234 service->ports = smartlist_create();
235 service->intro_nodes = smartlist_create();
236 service->intro_period_started = time(NULL);
237 continue;
239 if (!service) {
240 log_warn(LD_CONFIG, "%s with no preceding HiddenServiceDir directive",
241 line->key);
242 rend_service_free(service);
243 return -1;
245 if (!strcasecmp(line->key, "HiddenServicePort")) {
246 portcfg = parse_port_config(line->value);
247 if (!portcfg) {
248 rend_service_free(service);
249 return -1;
251 smartlist_add(service->ports, portcfg);
252 } else if (!strcasecmp(line->key, "HiddenServiceNodes")) {
253 if (service->intro_prefer_nodes) {
254 log_warn(LD_CONFIG,
255 "Got multiple HiddenServiceNodes lines for a single "
256 "service.");
257 return -1;
259 service->intro_prefer_nodes = tor_strdup(line->value);
260 } else {
261 tor_assert(!strcasecmp(line->key, "HiddenServiceExcludeNodes"));
262 if (service->intro_exclude_nodes) {
263 log_warn(LD_CONFIG,
264 "Got multiple HiddenServiceExcludedNodes lines for "
265 "a single service.");
266 return -1;
268 service->intro_exclude_nodes = tor_strdup(line->value);
271 if (service) {
272 if (validate_only)
273 rend_service_free(service);
274 else
275 add_service(service);
278 return 0;
281 /** Replace the old value of <b>service</b>-\>desc with one that reflects
282 * the other fields in service.
284 static void
285 rend_service_update_descriptor(rend_service_t *service)
287 rend_service_descriptor_t *d;
288 circuit_t *circ;
289 int i,n;
290 routerinfo_t *router;
292 if (service->desc) {
293 rend_service_descriptor_free(service->desc);
294 service->desc = NULL;
296 d = service->desc = tor_malloc(sizeof(rend_service_descriptor_t));
297 d->pk = crypto_pk_dup_key(service->private_key);
298 d->timestamp = time(NULL);
299 d->version = 1;
300 n = smartlist_len(service->intro_nodes);
301 d->n_intro_points = 0;
302 d->intro_points = tor_malloc_zero(sizeof(char*)*n);
303 d->intro_point_extend_info = tor_malloc_zero(sizeof(extend_info_t*)*n);
304 d->protocols = (1<<2) | (1<<0); /* We support protocol 2 and protocol 0. */
305 for (i=0; i < n; ++i) {
306 router = router_get_by_nickname(smartlist_get(service->intro_nodes, i),1);
307 if (!router) {
308 log_info(LD_REND,"Router '%s' not found. Skipping.",
309 (char*)smartlist_get(service->intro_nodes, i));
310 continue;
312 circ = find_intro_circuit(router, service->pk_digest);
313 if (circ && circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
314 /* We have an entirely established intro circuit. */
315 d->intro_points[d->n_intro_points] = tor_strdup(router->nickname);
316 d->intro_point_extend_info[d->n_intro_points] =
317 extend_info_from_router(router);
318 d->n_intro_points++;
323 /** Load and/or generate private keys for all hidden services. Return 0 on
324 * success, -1 on failure.
327 rend_service_load_keys(void)
329 int i;
330 rend_service_t *s;
331 char fname[512];
332 char buf[128];
334 for (i=0; i < smartlist_len(rend_service_list); ++i) {
335 s = smartlist_get(rend_service_list,i);
336 if (s->private_key)
337 continue;
338 log_info(LD_REND, "Loading hidden-service keys from \"%s\"",
339 s->directory);
341 /* Check/create directory */
342 if (check_private_dir(s->directory, CPD_CREATE) < 0)
343 return -1;
345 /* Load key */
346 if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
347 strlcat(fname,"/private_key",sizeof(fname)) >= sizeof(fname)) {
348 log_warn(LD_CONFIG, "Directory name too long: \"%s\".", s->directory);
349 return -1;
351 s->private_key = init_key_from_file(fname);
352 if (!s->private_key)
353 return -1;
355 /* Create service file */
356 if (rend_get_service_id(s->private_key, s->service_id)<0) {
357 log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
358 return -1;
360 if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) {
361 log_warn(LD_BUG, "Bug: Couldn't compute hash of public key.");
362 return -1;
364 if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
365 strlcat(fname,"/hostname",sizeof(fname)) >= sizeof(fname)) {
366 log_warn(LD_CONFIG, "Directory name too long: \"%s\".", s->directory);
367 return -1;
369 tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id);
370 if (write_str_to_file(fname,buf,0)<0)
371 return -1;
373 return 0;
376 /** Return the service whose public key has a digest of <b>digest</b>. Return
377 * NULL if no such service exists.
379 static rend_service_t *
380 rend_service_get_by_pk_digest(const char* digest)
382 SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
383 if (!memcmp(s->pk_digest,digest,DIGEST_LEN)) return s);
384 return NULL;
387 /** Return 1 if any virtual port in <b>service</b> wants a circuit
388 * to have good uptime. Else return 0.
390 static int
391 rend_service_requires_uptime(rend_service_t *service)
393 int i;
394 rend_service_port_config_t *p;
396 for (i=0; i < smartlist_len(service->ports); ++i) {
397 p = smartlist_get(service->ports, i);
398 if (smartlist_string_num_isin(get_options()->LongLivedPorts,
399 p->virtual_port))
400 return 1;
402 return 0;
405 /******
406 * Handle cells
407 ******/
409 /** Respond to an INTRODUCE2 cell by launching a circuit to the chosen
410 * rendezvous point.
413 rend_service_introduce(circuit_t *circuit, const char *request,
414 size_t request_len)
416 char *ptr, *r_cookie;
417 extend_info_t *extend_info = NULL;
418 char buf[RELAY_PAYLOAD_SIZE];
419 char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
420 rend_service_t *service;
421 int r, i;
422 size_t len, keylen;
423 crypto_dh_env_t *dh = NULL;
424 circuit_t *launched = NULL;
425 crypt_path_t *cpath = NULL;
426 char serviceid[REND_SERVICE_ID_LEN+1];
427 char hexcookie[9];
428 int circ_needs_uptime;
430 base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
431 circuit->rend_pk_digest,10);
432 log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %d.",
433 escaped(serviceid), circuit->n_circ_id);
435 if (circuit->purpose != CIRCUIT_PURPOSE_S_INTRO) {
436 log_warn(LD_PROTOCOL,
437 "Got an INTRODUCE2 over a non-introduction circuit %d.",
438 circuit->n_circ_id);
439 return -1;
442 /* min key length plus digest length plus nickname length */
443 if (request_len < DIGEST_LEN+REND_COOKIE_LEN+(MAX_NICKNAME_LEN+1)+
444 DH_KEY_LEN+42) {
445 log_warn(LD_PROTOCOL, "Got a truncated INTRODUCE2 cell on circ %d.",
446 circuit->n_circ_id);
447 return -1;
450 /* first DIGEST_LEN bytes of request is service pk digest */
451 service = rend_service_get_by_pk_digest(request);
452 if (!service) {
453 log_warn(LD_REND, "Got an INTRODUCE2 cell for an unrecognized service %s.",
454 escaped(serviceid));
455 return -1;
457 if (memcmp(circuit->rend_pk_digest, request, DIGEST_LEN)) {
458 base32_encode(serviceid, REND_SERVICE_ID_LEN+1, request, 10);
459 log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).",
460 escaped(serviceid));
461 return -1;
464 keylen = crypto_pk_keysize(service->private_key);
465 if (request_len < keylen+DIGEST_LEN) {
466 log_warn(LD_PROTOCOL,
467 "PK-encrypted portion of INTRODUCE2 cell was truncated.");
468 return -1;
470 /* Next N bytes is encrypted with service key */
471 r = crypto_pk_private_hybrid_decrypt(
472 service->private_key,buf,request+DIGEST_LEN,request_len-DIGEST_LEN,
473 PK_PKCS1_OAEP_PADDING,1);
474 if (r<0) {
475 log_warn(LD_PROTOCOL, "Couldn't decrypt INTRODUCE2 cell.");
476 return -1;
478 len = r;
479 if (*buf == 2) {
480 /* Version 2 INTRODUCE2 cell. */
481 int klen;
482 extend_info = tor_malloc_zero(sizeof(extend_info_t));
483 extend_info->addr = ntohl(get_uint32(buf+1));
484 extend_info->port = ntohs(get_uint16(buf+5));
485 memcpy(extend_info->identity_digest, buf+7, DIGEST_LEN);
486 extend_info->nickname[0] = '$';
487 base16_encode(extend_info->nickname+1, sizeof(extend_info->nickname)-1,
488 extend_info->identity_digest, DIGEST_LEN);
490 klen = ntohs(get_uint16(buf+7+DIGEST_LEN));
491 if ((int)len != 7+DIGEST_LEN+2+klen+20+128) {
492 log_warn(LD_PROTOCOL, "Bad length %u for version 2 INTRODUCE2 cell.",
493 (int)len);
494 goto err;
496 extend_info->onion_key = crypto_pk_asn1_decode(buf+7+DIGEST_LEN+2, klen);
497 if (!extend_info->onion_key) {
498 log_warn(LD_PROTOCOL,
499 "Error decoding onion key in version 2 INTRODUCE2 cell.");
500 goto err;
502 ptr = buf+7+DIGEST_LEN+2+klen;
503 len -= 7+DIGEST_LEN+2+klen;
504 } else {
505 char *rp_nickname;
506 size_t nickname_field_len;
507 routerinfo_t *router;
508 int version;
509 if (*buf == 1) {
510 rp_nickname = buf+1;
511 nickname_field_len = MAX_HEX_NICKNAME_LEN+1;
512 version = 1;
513 } else {
514 nickname_field_len = MAX_NICKNAME_LEN+1;
515 rp_nickname = buf;
516 version = 0;
518 /* XXX when 0.1.0.x is obsolete, change this to reject version < 2. */
519 ptr=memchr(rp_nickname,0,nickname_field_len);
520 if (!ptr || ptr == rp_nickname) {
521 log_warn(LD_PROTOCOL,
522 "Couldn't find a null-padded nickname in INTRODUCE2 cell.");
523 return -1;
525 if ((version == 0 && !is_legal_nickname(rp_nickname)) ||
526 (version == 1 && !is_legal_nickname_or_hexdigest(rp_nickname))) {
527 log_warn(LD_PROTOCOL, "Bad nickname in INTRODUCE2 cell.");
528 return -1;
530 /* Okay, now we know that a nickname is at the start of the buffer. */
531 ptr = rp_nickname+nickname_field_len;
532 len -= nickname_field_len;
533 len -= rp_nickname - buf; /* also remove header space used by version, if
534 * any */
535 router = router_get_by_nickname(rp_nickname, 0);
536 if (!router) {
537 log_info(LD_REND, "Couldn't find router %s named in rendezvous cell.",
538 escaped(rp_nickname));
539 goto err;
542 extend_info = extend_info_from_router(router);
545 if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
546 log_warn(LD_PROTOCOL, "Bad length %u for INTRODUCE2 cell.", (int)len);
547 return -1;
550 r_cookie = ptr;
551 base16_encode(hexcookie,9,r_cookie,4);
553 /* Try DH handshake... */
554 dh = crypto_dh_new();
555 if (!dh || crypto_dh_generate_public(dh)<0) {
556 log_warn(LD_BUG,"Internal error: couldn't build DH state "
557 "or generate public key.");
558 goto err;
560 if (crypto_dh_compute_secret(dh, ptr+REND_COOKIE_LEN, DH_KEY_LEN, keys,
561 DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
562 log_warn(LD_BUG, "Internal error: couldn't complete DH handshake");
563 goto err;
566 circ_needs_uptime = rend_service_requires_uptime(service);
568 /* help predict this next time */
569 rep_hist_note_used_internal(time(NULL), circ_needs_uptime, 1);
571 /* Launch a circuit to alice's chosen rendezvous point.
573 for (i=0;i<MAX_REND_FAILURES;i++) {
574 launched = circuit_launch_by_extend_info(
575 CIRCUIT_PURPOSE_S_CONNECT_REND, extend_info,
576 circ_needs_uptime, 1, 1);
578 if (launched)
579 break;
581 if (!launched) { /* give up */
582 log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous "
583 "point '%s' for service %s.",
584 extend_info->nickname, serviceid);
585 goto err;
587 log_info(LD_REND,
588 "Accepted intro; launching circuit to '%s' "
589 "(cookie %s) for service %s.",
590 extend_info->nickname, hexcookie, serviceid);
591 tor_assert(launched->build_state);
592 /* Fill in the circuit's state. */
593 memcpy(launched->rend_pk_digest, circuit->rend_pk_digest,
594 DIGEST_LEN);
595 memcpy(launched->rend_cookie, r_cookie, REND_COOKIE_LEN);
596 strlcpy(launched->rend_query, service->service_id,
597 sizeof(launched->rend_query));
598 launched->build_state->pending_final_cpath = cpath =
599 tor_malloc_zero(sizeof(crypt_path_t));
600 cpath->magic = CRYPT_PATH_MAGIC;
601 launched->build_state->expiry_time = time(NULL) + MAX_REND_TIMEOUT;
603 cpath->dh_handshake_state = dh;
604 dh = NULL;
605 if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0)
606 goto err;
607 memcpy(cpath->handshake_digest, keys, DIGEST_LEN);
608 if (extend_info) extend_info_free(extend_info);
610 return 0;
611 err:
612 if (dh) crypto_dh_free(dh);
613 if (launched) circuit_mark_for_close(launched, END_CIRC_AT_ORIGIN);
614 if (extend_info) extend_info_free(extend_info);
615 return -1;
618 /** Called when we fail building a rendezvous circuit at some point other
619 * than the last hop: launches a new circuit to the same rendezvous point.
621 void
622 rend_service_relaunch_rendezvous(circuit_t *oldcirc)
624 circuit_t *newcirc;
625 cpath_build_state_t *newstate, *oldstate;
627 tor_assert(oldcirc->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
629 if (!oldcirc->build_state ||
630 oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
631 oldcirc->build_state->expiry_time < time(NULL)) {
632 log_info(LD_REND,
633 "Attempt to build circuit to %s for rendezvous has failed "
634 "too many times or expired; giving up.",
635 oldcirc->build_state ?
636 oldcirc->build_state->chosen_exit->nickname : "*unknown*");
637 return;
640 oldstate = oldcirc->build_state;
641 tor_assert(oldstate);
643 if (oldstate->pending_final_cpath == NULL) {
644 log_info(LD_REND,"Skipping relaunch of circ that failed on its first hop. "
645 "Initiator will retry.");
646 return;
649 log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
650 oldstate->chosen_exit->nickname);
652 newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
653 oldstate->chosen_exit, 0, 1, 1);
654 if (!newcirc) {
655 log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
656 oldstate->chosen_exit->nickname);
657 return;
659 newstate = newcirc->build_state;
660 tor_assert(newstate);
661 newstate->failure_count = oldstate->failure_count+1;
662 newstate->expiry_time = oldstate->expiry_time;
663 newstate->pending_final_cpath = oldstate->pending_final_cpath;
664 oldstate->pending_final_cpath = NULL;
666 memcpy(newcirc->rend_query, oldcirc->rend_query, REND_SERVICE_ID_LEN+1);
667 memcpy(newcirc->rend_pk_digest, oldcirc->rend_pk_digest, DIGEST_LEN);
668 memcpy(newcirc->rend_cookie, oldcirc->rend_cookie, REND_COOKIE_LEN);
671 /** Launch a circuit to serve as an introduction point for the service
672 * <b>service</b> at the introduction point <b>nickname</b>
674 static int
675 rend_service_launch_establish_intro(rend_service_t *service,
676 const char *nickname)
678 circuit_t *launched;
680 log_info(LD_REND,
681 "Launching circuit to introduction point %s for service %s",
682 nickname, service->service_id);
684 rep_hist_note_used_internal(time(NULL), 1, 0);
686 ++service->n_intro_circuits_launched;
687 launched = circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
688 nickname, 1, 0, 1);
689 if (!launched) {
690 log_info(LD_REND,
691 "Can't launch circuit to establish introduction at '%s'.",
692 nickname);
693 return -1;
695 strlcpy(launched->rend_query, service->service_id,
696 sizeof(launched->rend_query));
697 memcpy(launched->rend_pk_digest, service->pk_digest, DIGEST_LEN);
699 if (launched->state == CIRCUIT_STATE_OPEN)
700 rend_service_intro_has_opened(launched);
701 return 0;
704 /** Called when we're done building a circuit to an introduction point:
705 * sends a RELAY_ESTABLISH_INTRO cell.
707 void
708 rend_service_intro_has_opened(circuit_t *circuit)
710 rend_service_t *service;
711 size_t len;
712 int r;
713 char buf[RELAY_PAYLOAD_SIZE];
714 char auth[DIGEST_LEN + 9];
715 char serviceid[REND_SERVICE_ID_LEN+1];
717 tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
718 tor_assert(CIRCUIT_IS_ORIGIN(circuit));
719 tor_assert(circuit->cpath);
721 base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
722 circuit->rend_pk_digest,10);
724 service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
725 if (!service) {
726 log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.",
727 serviceid, circuit->n_circ_id);
728 goto err;
731 log_info(LD_REND,
732 "Established circuit %d as introduction point for service %s",
733 circuit->n_circ_id, serviceid);
735 /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
736 len = crypto_pk_asn1_encode(service->private_key, buf+2,
737 RELAY_PAYLOAD_SIZE-2);
738 set_uint16(buf, htons((uint16_t)len));
739 len += 2;
740 memcpy(auth, circuit->cpath->prev->handshake_digest, DIGEST_LEN);
741 memcpy(auth+DIGEST_LEN, "INTRODUCE", 9);
742 if (crypto_digest(buf+len, auth, DIGEST_LEN+9))
743 goto err;
744 len += 20;
745 r = crypto_pk_private_sign_digest(service->private_key, buf+len, buf, len);
746 if (r<0) {
747 log_warn(LD_BUG, "Internal error: couldn't sign introduction request.");
748 goto err;
750 len += r;
752 if (connection_edge_send_command(NULL, circuit,RELAY_COMMAND_ESTABLISH_INTRO,
753 buf, len, circuit->cpath->prev)<0) {
754 log_info(LD_GENERAL,
755 "Couldn't send introduction request for service %s on circuit %d",
756 serviceid, circuit->n_circ_id);
757 goto err;
760 return;
761 err:
762 circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
765 /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
766 * live introduction point, and note that the service descriptor is
767 * now out-of-date.*/
769 rend_service_intro_established(circuit_t *circuit, const char *request,
770 size_t request_len)
772 rend_service_t *service;
774 if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
775 log_warn(LD_PROTOCOL,
776 "received INTRO_ESTABLISHED cell on non-intro circuit.");
777 goto err;
779 service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
780 if (!service) {
781 log_warn(LD_REND, "Unknown service on introduction circuit %d.",
782 circuit->n_circ_id);
783 goto err;
785 service->desc_is_dirty = time(NULL);
786 circuit->purpose = CIRCUIT_PURPOSE_S_INTRO;
788 return 0;
789 err:
790 circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
791 return -1;
794 /** Called once a circuit to a rendezvous point is established: sends a
795 * RELAY_COMMAND_RENDEZVOUS1 cell.
797 void
798 rend_service_rendezvous_has_opened(circuit_t *circuit)
800 rend_service_t *service;
801 char buf[RELAY_PAYLOAD_SIZE];
802 crypt_path_t *hop;
803 char serviceid[REND_SERVICE_ID_LEN+1];
804 char hexcookie[9];
806 tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
807 tor_assert(circuit->cpath);
808 tor_assert(circuit->build_state);
809 hop = circuit->build_state->pending_final_cpath;
810 tor_assert(hop);
812 base16_encode(hexcookie,9,circuit->rend_cookie,4);
813 base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
814 circuit->rend_pk_digest,10);
816 log_info(LD_REND,
817 "Done building circuit %d to rendezvous with "
818 "cookie %s for service %s",
819 circuit->n_circ_id, hexcookie, serviceid);
821 service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
822 if (!service) {
823 log_warn(LD_GENERAL, "Internal error: unrecognized service ID on "
824 "introduction circuit.");
825 goto err;
828 /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
829 memcpy(buf, circuit->rend_cookie, REND_COOKIE_LEN);
830 if (crypto_dh_get_public(hop->dh_handshake_state,
831 buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
832 log_warn(LD_GENERAL,"Couldn't get DH public key.");
833 goto err;
835 memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->handshake_digest,
836 DIGEST_LEN);
838 /* Send the cell */
839 if (connection_edge_send_command(NULL, circuit, RELAY_COMMAND_RENDEZVOUS1,
840 buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
841 circuit->cpath->prev)<0) {
842 log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
843 goto err;
846 crypto_dh_free(hop->dh_handshake_state);
847 hop->dh_handshake_state = NULL;
849 /* Append the cpath entry. */
850 hop->state = CPATH_STATE_OPEN;
851 /* set the windows to default. these are the windows
852 * that bob thinks alice has.
854 hop->package_window = CIRCWINDOW_START;
855 hop->deliver_window = CIRCWINDOW_START;
857 onion_append_to_cpath(&circuit->cpath, hop);
858 circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
860 /* Change the circuit purpose. */
861 circuit->purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
863 return;
864 err:
865 circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
869 * Manage introduction points
872 /** Return the (possibly non-open) introduction circuit ending at
873 * <b>router</b> for the service whose public key is <b>pk_digest</b>. Return
874 * NULL if no such service is found.
876 static circuit_t *
877 find_intro_circuit(routerinfo_t *router, const char *pk_digest)
879 circuit_t *circ = NULL;
881 tor_assert(router);
882 while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
883 CIRCUIT_PURPOSE_S_INTRO))) {
884 tor_assert(circ->cpath);
885 if (!strcasecmp(circ->build_state->chosen_exit->nickname,
886 router->nickname)) {
887 return circ;
891 circ = NULL;
892 while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
893 CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
894 tor_assert(circ->cpath);
895 if (!strcasecmp(circ->build_state->chosen_exit->nickname,
896 router->nickname)) {
897 return circ;
900 return NULL;
903 /** Encode and sign an up-to-date service descriptor for <b>service</b>,
904 * and upload it to all the dirservers.
906 static void
907 upload_service_descriptor(rend_service_t *service, int version)
909 char *desc;
910 size_t desc_len;
912 /* Update the descriptor. */
913 rend_service_update_descriptor(service);
914 if (rend_encode_service_descriptor(service->desc,
915 version,
916 service->private_key,
917 &desc, &desc_len)<0) {
918 log_warn(LD_BUG, "Internal error: couldn't encode service descriptor; "
919 "not uploading.");
920 return;
923 /* Post it to the dirservers */
924 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC, desc, desc_len);
925 tor_free(desc);
927 service->desc_is_dirty = 0;
930 /* XXXX Make this longer once directories remember service descriptors across
931 * restarts.*/
932 #define MAX_SERVICE_PUBLICATION_INTERVAL (15*60)
934 /** For every service, check how many intro points it currently has, and:
935 * - Pick new intro points as necessary.
936 * - Launch circuits to any new intro points.
938 void
939 rend_services_introduce(void)
941 int i,j,r;
942 routerinfo_t *router;
943 rend_service_t *service;
944 char *intro;
945 int changed, prev_intro_nodes;
946 smartlist_t *intro_routers, *exclude_routers;
947 time_t now;
949 intro_routers = smartlist_create();
950 exclude_routers = smartlist_create();
951 now = time(NULL);
953 for (i=0; i < smartlist_len(rend_service_list); ++i) {
954 smartlist_clear(intro_routers);
955 service = smartlist_get(rend_service_list, i);
957 tor_assert(service);
958 changed = 0;
959 if (now > service->intro_period_started+INTRO_CIRC_RETRY_PERIOD) {
960 /* One period has elapsed; we can try building circuits again. */
961 service->intro_period_started = now;
962 service->n_intro_circuits_launched = 0;
963 } else if (service->n_intro_circuits_launched >=
964 MAX_INTRO_CIRCS_PER_PERIOD) {
965 /* We have failed too many times in this period; wait for the next
966 * one before we try again. */
967 continue;
970 /* Find out which introduction points we have in progress for this
971 service. */
972 for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
973 intro = smartlist_get(service->intro_nodes, j);
974 router = router_get_by_nickname(intro, 0);
975 if (!router || !find_intro_circuit(router,service->pk_digest)) {
976 log_info(LD_REND,"Giving up on %s as intro point for %s.",
977 intro, service->service_id);
978 tor_free(intro);
979 smartlist_del(service->intro_nodes,j--);
980 changed = 1;
981 service->desc_is_dirty = now;
983 smartlist_add(intro_routers, router);
986 /* We have enough intro points, and the intro points we thought we had were
987 * all connected.
989 if (!changed && smartlist_len(service->intro_nodes) >= NUM_INTRO_POINTS) {
990 /* We have all our intro points! Start a fresh period and reset the
991 * circuit count. */
992 service->intro_period_started = now;
993 service->n_intro_circuits_launched = 0;
994 continue;
997 /* Remember how many introduction circuits we started with. */
998 prev_intro_nodes = smartlist_len(service->intro_nodes);
1000 smartlist_add_all(exclude_routers, intro_routers);
1001 /* The directory is now here. Pick three ORs as intro points. */
1002 for (j=prev_intro_nodes; j < NUM_INTRO_POINTS; ++j) {
1003 char *hex_digest;
1004 router = router_choose_random_node(service->intro_prefer_nodes,
1005 service->intro_exclude_nodes, exclude_routers, 1, 0, 0,
1006 get_options()->_AllowUnverified & ALLOW_UNVERIFIED_INTRODUCTION,
1008 if (!router) {
1009 log_warn(LD_REND,
1010 "Could only establish %d introduction points for %s.",
1011 smartlist_len(service->intro_nodes), service->service_id);
1012 break;
1014 changed = 1;
1015 hex_digest = tor_malloc_zero(HEX_DIGEST_LEN+2);
1016 hex_digest[0] = '$';
1017 base16_encode(hex_digest+1, HEX_DIGEST_LEN+1,
1018 router->cache_info.identity_digest,
1019 DIGEST_LEN);
1020 smartlist_add(intro_routers, router);
1021 smartlist_add(exclude_routers, router);
1022 smartlist_add(service->intro_nodes, hex_digest);
1023 log_info(LD_REND, "Picked router %s as an intro point for %s.",
1024 router->nickname, service->service_id);
1027 /* Reset exclude_routers, for the next time around the loop. */
1028 smartlist_clear(exclude_routers);
1030 /* If there's no need to launch new circuits, stop here. */
1031 if (!changed)
1032 continue;
1034 /* Establish new introduction points. */
1035 for (j=prev_intro_nodes; j < smartlist_len(service->intro_nodes); ++j) {
1036 intro = smartlist_get(service->intro_nodes, j);
1037 r = rend_service_launch_establish_intro(service, intro);
1038 if (r<0) {
1039 log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
1040 intro, service->service_id);
1044 smartlist_free(intro_routers);
1045 smartlist_free(exclude_routers);
1048 /** Regenerate and upload rendezvous service descriptors for all
1049 * services, if necessary. If the descriptor has been dirty enough
1050 * for long enough, definitely upload; else only upload when the
1051 * periodic timeout has expired.
1053 * For the first upload, pick a random time between now and two periods
1054 * from now, and pick it independently for each service.
1056 void
1057 rend_consider_services_upload(time_t now)
1059 int i;
1060 rend_service_t *service;
1061 int rendpostperiod = get_options()->RendPostPeriod;
1063 if (!get_options()->PublishHidServDescriptors)
1064 return;
1066 for (i=0; i < smartlist_len(rend_service_list); ++i) {
1067 service = smartlist_get(rend_service_list, i);
1068 if (!service->next_upload_time) { /* never been uploaded yet */
1069 service->next_upload_time =
1070 now + crypto_rand_int(2*rendpostperiod);
1072 if (service->next_upload_time < now ||
1073 (service->desc_is_dirty &&
1074 service->desc_is_dirty < now-5)) {
1075 /* if it's time, or if the directory servers have a wrong service
1076 * descriptor and ours has been stable for 5 seconds, upload a
1077 * new one of each format. */
1078 upload_service_descriptor(service, 0);
1079 // XXXX011 upload_service_descriptor(service, 1);
1080 service->next_upload_time = now + rendpostperiod;
1085 /** Log the status of introduction points for all rendezvous services
1086 * at log severity <b>severity</b>.
1088 void
1089 rend_service_dump_stats(int severity)
1091 int i,j;
1092 routerinfo_t *router;
1093 rend_service_t *service;
1094 char *nickname;
1095 circuit_t *circ;
1097 for (i=0; i < smartlist_len(rend_service_list); ++i) {
1098 service = smartlist_get(rend_service_list, i);
1099 log(severity, LD_GENERAL, "Service configured in \"%s\":",
1100 service->directory);
1101 for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
1102 nickname = smartlist_get(service->intro_nodes, j);
1103 router = router_get_by_nickname(smartlist_get(service->intro_nodes,j),1);
1104 if (!router) {
1105 log(severity, LD_GENERAL, " Intro point at %s: unrecognized router",
1106 nickname);
1107 continue;
1109 circ = find_intro_circuit(router, service->pk_digest);
1110 if (!circ) {
1111 log(severity, LD_GENERAL, " Intro point at %s: no circuit",nickname);
1112 continue;
1114 log(severity, LD_GENERAL, " Intro point at %s: circuit is %s",nickname,
1115 circuit_state_to_string(circ->state));
1120 /** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
1121 * 'circ', and look up the port and address based on conn-\>port.
1122 * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
1123 * or 0 for success.
1126 rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ)
1128 rend_service_t *service;
1129 int i;
1130 rend_service_port_config_t *p;
1131 char serviceid[REND_SERVICE_ID_LEN+1];
1133 tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
1134 log_debug(LD_REND,"beginning to hunt for addr/port");
1135 base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
1136 circ->rend_pk_digest,10);
1137 service = rend_service_get_by_pk_digest(circ->rend_pk_digest);
1138 if (!service) {
1139 log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
1140 "rendezvous circuit %d; closing.",
1141 serviceid, circ->n_circ_id);
1142 return -1;
1144 for (i = 0; i < smartlist_len(service->ports); ++i) {
1145 p = smartlist_get(service->ports, i);
1146 if (conn->port == p->virtual_port) {
1147 conn->addr = p->real_addr;
1148 conn->port = p->real_port;
1149 return 0;
1152 log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
1153 conn->port,serviceid);
1154 return -1;