1 /* Copyright 2004 Roger Dingledine, Nick Mathewson. */
2 /* See LICENSE for licensing information */
4 const char rendservice_c_id
[] = "$Id$";
8 * \brief The hidden-service side of rendezvous functionality.
13 static circuit_t
*find_intro_circuit(routerinfo_t
*router
, const char *pk_digest
);
15 /** Represents the mapping from a virtual port of a rendezvous service to
16 * a real port on some IP.
18 typedef struct rend_service_port_config_t
{
19 uint16_t virtual_port
;
21 uint32_t real_address
;
22 } rend_service_port_config_t
;
24 /** Try to maintain this many intro points per service if possible. */
25 #define NUM_INTRO_POINTS 3
27 /** If we can't build our intro circuits, don't retry for this long. */
28 #define INTRO_CIRC_RETRY_PERIOD 60*5
29 /** Don't try to build more than this many circuits before giving up
31 #define MAX_INTRO_CIRCS_PER_PERIOD 10
32 /** How many times will a hidden service operator attempt to connect to
33 * a requested rendezvous point before giving up? */
34 #define MAX_REND_FAILURES 3
36 /** Represents a single hidden service running at this OP. */
37 typedef struct rend_service_t
{
38 /** Fields specified in config file */
39 char *directory
; /**< where in the filesystem it stores it */
40 smartlist_t
*ports
; /**< List of rend_service_port_config_t */
41 char *intro_prefer_nodes
; /**< comma-separated list of nicknames */
42 char *intro_exclude_nodes
; /**< comma-separated list of nicknames */
44 crypto_pk_env_t
*private_key
;
45 char service_id
[REND_SERVICE_ID_LEN
+1];
46 char pk_digest
[DIGEST_LEN
];
47 smartlist_t
*intro_nodes
; /**< list of hexdigests for intro points we have,
48 * or are trying to establish. */
49 time_t intro_period_started
;
50 int n_intro_circuits_launched
; /**< count of intro circuits we have
51 * established in this period. */
52 rend_service_descriptor_t
*desc
;
54 time_t next_upload_time
;
57 /** A list of rend_service_t's for services run on this OP.
59 static smartlist_t
*rend_service_list
= NULL
;
61 /** Release the storage held by <b>service</b>.
63 static void rend_service_free(rend_service_t
*service
)
66 tor_free(service
->directory
);
67 SMARTLIST_FOREACH(service
->ports
, void*, p
, tor_free(p
));
68 smartlist_free(service
->ports
);
69 if (service
->private_key
)
70 crypto_free_pk_env(service
->private_key
);
71 tor_free(service
->intro_prefer_nodes
);
72 tor_free(service
->intro_exclude_nodes
);
73 SMARTLIST_FOREACH(service
->intro_nodes
, void*, p
, tor_free(p
));
74 smartlist_free(service
->intro_nodes
);
76 rend_service_descriptor_free(service
->desc
);
80 /** Release all the storage held in rend_service_list, and allocate a new,
81 * empty rend_service_list.
83 static void rend_service_free_all(void)
85 if (!rend_service_list
) {
86 rend_service_list
= smartlist_create();
89 SMARTLIST_FOREACH(rend_service_list
, rend_service_t
*, ptr
,
90 rend_service_free(ptr
));
91 smartlist_free(rend_service_list
);
92 rend_service_list
= smartlist_create();
95 /** Validate <b>service</b> and add it to rend_service_list if possible.
97 static void add_service(rend_service_t
*service
)
100 rend_service_port_config_t
*p
;
103 if (!service
->intro_prefer_nodes
)
104 service
->intro_prefer_nodes
= tor_strdup("");
105 if (!service
->intro_exclude_nodes
)
106 service
->intro_exclude_nodes
= tor_strdup("");
108 if (!smartlist_len(service
->ports
)) {
109 log_fn(LOG_WARN
, "Hidden service with no ports configured; ignoring.");
110 rend_service_free(service
);
112 smartlist_set_capacity(service
->ports
, -1);
113 smartlist_add(rend_service_list
, service
);
114 log_fn(LOG_DEBUG
,"Configuring service with directory %s",service
->directory
);
115 for (i
= 0; i
< smartlist_len(service
->ports
); ++i
) {
116 p
= smartlist_get(service
->ports
, i
);
117 addr
.s_addr
= htonl(p
->real_address
);
118 log_fn(LOG_DEBUG
,"Service maps port %d to %s:%d",
119 p
->virtual_port
, inet_ntoa(addr
), p
->real_port
);
124 /** Parses a real-port to virtual-port mapping and returns a new
125 * rend_service_port_config_t.
127 * The format is: VirtualPort (IP|RealPort|IP:RealPort)?
129 * IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
131 static rend_service_port_config_t
*parse_port_config(const char *string
)
138 rend_service_port_config_t
*result
;
140 virtport
= (int) strtol(string
, &endptr
, 10);
141 if (endptr
== string
) {
142 log_fn(LOG_WARN
, "Missing port in hidden service port configuration");
145 if (virtport
< 1 || virtport
> 65535) {
146 log_fn(LOG_WARN
, "Port out of range in hidden service port configuration");
149 string
= endptr
+ strspn(endptr
, " \t");
151 /* No addr:port part; use default. */
153 addr
= 0x7F000001u
; /* 127.0.0.1 */
154 } else if (strchr(string
, ':') || strchr(string
, '.')) {
155 if (parse_addr_port(string
, NULL
, &addr
, &p
)<0) {
156 log_fn(LOG_WARN
,"Unparseable address in hidden service port configuration");
159 realport
= p
?p
:virtport
;
161 /* No addr:port, no addr -- must be port. */
162 realport
= strtol(string
, &endptr
, 10);
164 log_fn(LOG_WARN
, "Unparseable or missing port in hidden service port configuration.");
167 if (realport
< 1 || realport
> 65535) {
168 log_fn(LOG_WARN
, "Port out of range");
171 addr
= 0x7F000001u
; /* Default to 127.0.0.1 */
174 result
= tor_malloc(sizeof(rend_service_port_config_t
));
175 result
->virtual_port
= virtport
;
176 result
->real_port
= realport
;
177 result
->real_address
= addr
;
181 /** Set up rend_service_list, based on the values of HiddenServiceDir and
182 * HiddenServicePort in <b>options</b>. Return 0 on success and -1 on
183 * failure. (If <b>validate_only</b> is set, parse, warn and return as
184 * normal, but don't actually change the configured services.)
187 int rend_config_services(or_options_t
*options
, int validate_only
)
189 struct config_line_t
*line
;
190 rend_service_t
*service
= NULL
;
191 rend_service_port_config_t
*portcfg
;
194 rend_service_free_all();
196 for (line
= options
->RendConfigLines
; line
; line
= line
->next
) {
197 if (!strcasecmp(line
->key
, "HiddenServiceDir")) {
200 rend_service_free(service
);
202 add_service(service
);
204 service
= tor_malloc_zero(sizeof(rend_service_t
));
205 service
->directory
= tor_strdup(line
->value
);
206 service
->ports
= smartlist_create();
207 service
->intro_nodes
= smartlist_create();
208 service
->intro_period_started
= time(NULL
);
212 log_fn(LOG_WARN
, "HiddenServicePort with no preceding HiddenServiceDir directive");
213 rend_service_free(service
);
216 if (!strcasecmp(line
->key
, "HiddenServicePort")) {
217 portcfg
= parse_port_config(line
->value
);
219 rend_service_free(service
);
222 smartlist_add(service
->ports
, portcfg
);
223 } else if (!strcasecmp(line
->key
, "HiddenServiceNodes")) {
224 if (service
->intro_prefer_nodes
) {
225 log_fn(LOG_WARN
, "Got multiple HiddenServiceNodes lines for a single service");
228 service
->intro_prefer_nodes
= tor_strdup(line
->value
);
230 tor_assert(!strcasecmp(line
->key
, "HiddenServiceExcludeNodes"));
231 if (service
->intro_exclude_nodes
) {
232 log_fn(LOG_WARN
, "Got multiple HiddenServiceExcludedNodes lines for a single service");
235 service
->intro_exclude_nodes
= tor_strdup(line
->value
);
240 rend_service_free(service
);
242 add_service(service
);
248 /** Replace the old value of <b>service</b>-\>desc with one that reflects
249 * the other fields in service.
251 static void rend_service_update_descriptor(rend_service_t
*service
)
253 rend_service_descriptor_t
*d
;
256 routerinfo_t
*router
;
259 rend_service_descriptor_free(service
->desc
);
260 service
->desc
= NULL
;
262 d
= service
->desc
= tor_malloc(sizeof(rend_service_descriptor_t
));
263 d
->pk
= crypto_pk_dup_key(service
->private_key
);
264 d
->timestamp
= time(NULL
);
265 n
= smartlist_len(service
->intro_nodes
);
266 d
->n_intro_points
= 0;
267 d
->intro_points
= tor_malloc(sizeof(char*)*n
);
268 for (i
=0; i
< n
; ++i
) {
269 router
= router_get_by_nickname(smartlist_get(service
->intro_nodes
, i
));
271 log_fn(LOG_WARN
,"Router '%s' not found. Skipping.",
272 (char*)smartlist_get(service
->intro_nodes
, i
));
275 circ
= find_intro_circuit(router
, service
->pk_digest
);
276 if (circ
&& circ
->purpose
== CIRCUIT_PURPOSE_S_INTRO
) {
277 /* We have an entirely established intro circuit. */
278 d
->intro_points
[d
->n_intro_points
++] = tor_strdup(router
->nickname
);
283 /** Load and/or generate private keys for all hidden services. Return 0 on
284 * success, -1 on failure.
286 int rend_service_load_keys(void)
293 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
294 s
= smartlist_get(rend_service_list
,i
);
297 log_fn(LOG_INFO
, "Loading hidden-service keys from '%s'", s
->directory
);
299 /* Check/create directory */
300 if (check_private_dir(s
->directory
, CPD_CREATE
) < 0)
304 if (strlcpy(fname
,s
->directory
,sizeof(fname
)) >= sizeof(fname
) ||
305 strlcat(fname
,"/private_key",sizeof(fname
)) >= sizeof(fname
)) {
306 log_fn(LOG_WARN
, "Directory name too long: '%s'", s
->directory
);
309 s
->private_key
= init_key_from_file(fname
);
313 /* Create service file */
314 if (rend_get_service_id(s
->private_key
, s
->service_id
)<0) {
315 log_fn(LOG_WARN
, "Couldn't encode service ID");
318 if (crypto_pk_get_digest(s
->private_key
, s
->pk_digest
)<0) {
319 log_fn(LOG_WARN
, "Couldn't compute hash of public key");
322 if (strlcpy(fname
,s
->directory
,sizeof(fname
)) >= sizeof(fname
) ||
323 strlcat(fname
,"/hostname",sizeof(fname
)) >= sizeof(fname
)) {
324 log_fn(LOG_WARN
, "Directory name too long: '%s'", s
->directory
);
327 tor_snprintf(buf
, sizeof(buf
),"%s.onion\n", s
->service_id
);
328 if (write_str_to_file(fname
,buf
,0)<0)
334 /** Return the service whose public key has a digest of <b>digest</b>. Return
335 * NULL if no such service exists.
337 static rend_service_t
*
338 rend_service_get_by_pk_digest(const char* digest
)
340 SMARTLIST_FOREACH(rend_service_list
, rend_service_t
*, s
,
341 if (!memcmp(s
->pk_digest
,digest
,DIGEST_LEN
)) return s
);
345 /** Return 1 if any virtual port in <b>service</b> wants a circuit
346 * to have good uptime. Else return 0.
349 rend_service_requires_uptime(rend_service_t
*service
) {
351 rend_service_port_config_t
*p
;
353 for (i
=0; i
< smartlist_len(service
->ports
); ++i
) {
354 p
= smartlist_get(service
->ports
, i
);
355 if (smartlist_string_num_isin(get_options()->LongLivedPorts
, p
->virtual_port
))
365 /** Respond to an INTRODUCE2 cell by launching a circuit to the chosen
369 rend_service_introduce(circuit_t
*circuit
, const char *request
, size_t request_len
)
371 char *ptr
, *rp_nickname
, *r_cookie
;
372 char buf
[RELAY_PAYLOAD_SIZE
];
373 char keys
[DIGEST_LEN
+CPATH_KEY_MATERIAL_LEN
]; /* Holds KH, Df, Db, Kf, Kb */
374 rend_service_t
*service
;
377 crypto_dh_env_t
*dh
= NULL
;
378 circuit_t
*launched
= NULL
;
379 crypt_path_t
*cpath
= NULL
;
380 char serviceid
[REND_SERVICE_ID_LEN
+1];
383 size_t nickname_field_len
;
384 int circ_needs_uptime
;
386 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
387 circuit
->rend_pk_digest
,10);
388 log_fn(LOG_INFO
, "Received INTRODUCE2 cell for service %s on circ %d",
389 serviceid
, circuit
->n_circ_id
);
391 if (circuit
->purpose
!= CIRCUIT_PURPOSE_S_INTRO
) {
392 log_fn(LOG_WARN
, "Got an INTRODUCE2 over a non-introduction circuit %d",
397 /* min key length plus digest length plus nickname length */
398 if (request_len
< DIGEST_LEN
+REND_COOKIE_LEN
+(MAX_NICKNAME_LEN
+1)+
400 log_fn(LOG_WARN
, "Got a truncated INTRODUCE2 cell on circ %d",
405 /* first DIGEST_LEN bytes of request is service pk digest */
406 service
= rend_service_get_by_pk_digest(request
);
408 log_fn(LOG_WARN
, "Got an INTRODUCE2 cell for an unrecognized service %s",
412 if (memcmp(circuit
->rend_pk_digest
, request
, DIGEST_LEN
)) {
413 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1, request
, 10);
414 log_fn(LOG_WARN
, "Got an INTRODUCE2 cell for the wrong service (%s)",
419 keylen
= crypto_pk_keysize(service
->private_key
);
420 if (request_len
< keylen
+DIGEST_LEN
) {
421 log_fn(LOG_WARN
, "PK-encrypted portion of INTRODUCE2 cell was truncated");
424 /* Next N bytes is encrypted with service key */
425 r
= crypto_pk_private_hybrid_decrypt(
426 service
->private_key
,buf
,request
+DIGEST_LEN
,request_len
-DIGEST_LEN
,
427 PK_PKCS1_OAEP_PADDING
,1);
429 log_fn(LOG_WARN
, "Couldn't decrypt INTRODUCE2 cell");
435 nickname_field_len
= MAX_HEX_NICKNAME_LEN
+1;
438 nickname_field_len
= MAX_NICKNAME_LEN
+1;
442 /* XXX when 0.0.9.x is obsolete, change this to reject version != 1. */
443 ptr
=memchr(rp_nickname
,0,nickname_field_len
);
444 if (!ptr
|| ptr
== rp_nickname
) {
445 log_fn(LOG_WARN
, "Couldn't find a null-padded nickname in INTRODUCE2 cell");
448 if ((version
== 0 && !is_legal_nickname(rp_nickname
)) ||
449 (version
== 1 && !is_legal_nickname_or_hexdigest(rp_nickname
))) {
450 log_fn(LOG_WARN
, "Bad nickname in INTRODUCE2 cell.");
453 /* Okay, now we know that a nickname is at the start of the buffer. */
454 ptr
= rp_nickname
+nickname_field_len
;
455 len
-= nickname_field_len
;
456 len
-= rp_nickname
- buf
; /* also remove header space used by version, if any */
457 if (len
!= REND_COOKIE_LEN
+DH_KEY_LEN
) {
458 log_fn(LOG_WARN
, "Bad length %u for INTRODUCE2 cell.", (int)len
);
462 base16_encode(hexcookie
,9,r_cookie
,4);
464 /* Try DH handshake... */
465 dh
= crypto_dh_new();
466 if (!dh
|| crypto_dh_generate_public(dh
)<0) {
467 log_fn(LOG_WARN
, "Couldn't build DH state or generate public key");
470 if (crypto_dh_compute_secret(dh
, ptr
+REND_COOKIE_LEN
, DH_KEY_LEN
, keys
,
471 DIGEST_LEN
+CPATH_KEY_MATERIAL_LEN
)<0) {
472 log_fn(LOG_WARN
, "Couldn't complete DH handshake");
476 circ_needs_uptime
= rend_service_requires_uptime(service
);
478 /* help predict this next time */
479 rep_hist_note_used_hidserv(time(NULL
), circ_needs_uptime
, 1);
481 /* Launch a circuit to alice's chosen rendezvous point.
483 for (i
=0;i
<MAX_REND_FAILURES
;i
++) {
484 launched
= circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_CONNECT_REND
, rp_nickname
,
485 circ_needs_uptime
, 1, 1);
489 if (!launched
) { /* give up */
490 log_fn(LOG_WARN
,"Giving up launching first hop of circuit to rendezvous point '%s' for service %s",
491 rp_nickname
, serviceid
);
495 "Accepted intro; launching circuit to '%s' (cookie %s) for service %s",
496 rp_nickname
, hexcookie
, serviceid
);
497 tor_assert(launched
->build_state
);
498 /* Fill in the circuit's state. */
499 memcpy(launched
->rend_pk_digest
, circuit
->rend_pk_digest
,
501 memcpy(launched
->rend_cookie
, r_cookie
, REND_COOKIE_LEN
);
502 strlcpy(launched
->rend_query
, service
->service_id
,
503 sizeof(launched
->rend_query
));
504 launched
->build_state
->pending_final_cpath
= cpath
=
505 tor_malloc_zero(sizeof(crypt_path_t
));
507 cpath
->handshake_state
= dh
;
509 if (circuit_init_cpath_crypto(cpath
,keys
+DIGEST_LEN
,1)<0)
511 memcpy(cpath
->handshake_digest
, keys
, DIGEST_LEN
);
515 if (dh
) crypto_dh_free(dh
);
516 if (launched
) circuit_mark_for_close(launched
);
520 /** Called when we fail building a rendezvous circuit at some point other
521 * than the last hop: launches a new circuit to the same rendezvous point.
524 rend_service_relaunch_rendezvous(circuit_t
*oldcirc
)
527 cpath_build_state_t
*newstate
, *oldstate
;
529 tor_assert(oldcirc
->purpose
== CIRCUIT_PURPOSE_S_CONNECT_REND
);
531 if (!oldcirc
->build_state
||
532 oldcirc
->build_state
->failure_count
> MAX_REND_FAILURES
) {
533 log_fn(LOG_INFO
,"Attempt to build circuit to %s for rendezvous has failed too many times; giving up.",
534 oldcirc
->build_state
->chosen_exit_name
);
538 oldstate
= oldcirc
->build_state
;
539 tor_assert(oldstate
);
541 if (oldstate
->pending_final_cpath
== NULL
) {
542 log_fn(LOG_INFO
,"Skipping relaunch of circ that failed on its first hop. Initiator will retry.");
546 log_fn(LOG_INFO
,"Reattempting rendezvous circuit to %s",
547 oldstate
->chosen_exit_name
);
549 newcirc
= circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_CONNECT_REND
,
550 oldstate
->chosen_exit_name
, 0, 1, 1);
552 log_fn(LOG_WARN
,"Couldn't relaunch rendezvous circuit to %s",
553 oldstate
->chosen_exit_name
);
556 newstate
= newcirc
->build_state
;
557 tor_assert(newstate
);
558 newstate
->failure_count
= oldstate
->failure_count
+1;
559 newstate
->pending_final_cpath
= oldstate
->pending_final_cpath
;
560 oldstate
->pending_final_cpath
= NULL
;
562 memcpy(newcirc
->rend_query
, oldcirc
->rend_query
, REND_SERVICE_ID_LEN
+1);
563 memcpy(newcirc
->rend_pk_digest
, oldcirc
->rend_pk_digest
, DIGEST_LEN
);
564 memcpy(newcirc
->rend_cookie
, oldcirc
->rend_cookie
, REND_COOKIE_LEN
);
567 /** Launch a circuit to serve as an introduction point for the service
568 * <b>service</b> at the introduction point <b>nickname</b>
571 rend_service_launch_establish_intro(rend_service_t
*service
, const char *nickname
)
575 log_fn(LOG_INFO
, "Launching circuit to introduction point %s for service %s",
576 nickname
, service
->service_id
);
578 rep_hist_note_used_hidserv(time(NULL
), 1, 0);
580 ++service
->n_intro_circuits_launched
;
581 launched
= circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
, nickname
, 1, 0, 1);
583 log_fn(LOG_WARN
, "Can't launch circuit to establish introduction at '%s'",
587 strlcpy(launched
->rend_query
, service
->service_id
,
588 sizeof(launched
->rend_query
));
589 memcpy(launched
->rend_pk_digest
, service
->pk_digest
, DIGEST_LEN
);
594 /** Called when we're done building a circuit to an introduction point:
595 * sends a RELAY_ESTABLISH_INTRO cell.
598 rend_service_intro_has_opened(circuit_t
*circuit
)
600 rend_service_t
*service
;
603 char buf
[RELAY_PAYLOAD_SIZE
];
604 char auth
[DIGEST_LEN
+ 9];
605 char serviceid
[REND_SERVICE_ID_LEN
+1];
607 tor_assert(circuit
->purpose
== CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
);
608 tor_assert(CIRCUIT_IS_ORIGIN(circuit
));
609 tor_assert(circuit
->cpath
);
611 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
612 circuit
->rend_pk_digest
,10);
614 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
616 log_fn(LOG_WARN
, "Unrecognized service ID %s on introduction circuit %d",
617 serviceid
, circuit
->n_circ_id
);
622 "Established circuit %d as introduction point for service %s",
623 circuit
->n_circ_id
, serviceid
);
625 /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
626 len
= crypto_pk_asn1_encode(service
->private_key
, buf
+2,
627 RELAY_PAYLOAD_SIZE
-2);
628 set_uint16(buf
, htons((uint16_t)len
));
630 memcpy(auth
, circuit
->cpath
->prev
->handshake_digest
, DIGEST_LEN
);
631 memcpy(auth
+DIGEST_LEN
, "INTRODUCE", 9);
632 if (crypto_digest(buf
+len
, auth
, DIGEST_LEN
+9))
635 r
= crypto_pk_private_sign_digest(service
->private_key
, buf
+len
, buf
, len
);
637 log_fn(LOG_WARN
, "Couldn't sign introduction request");
642 if (connection_edge_send_command(NULL
, circuit
,RELAY_COMMAND_ESTABLISH_INTRO
,
643 buf
, len
, circuit
->cpath
->prev
)<0) {
645 "Couldn't send introduction request for service %s on circuit %d",
646 serviceid
, circuit
->n_circ_id
);
652 circuit_mark_for_close(circuit
);
655 /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
656 * live introduction point, and note that the service descriptor is
659 rend_service_intro_established(circuit_t
*circuit
, const char *request
, size_t request_len
)
661 rend_service_t
*service
;
663 if (circuit
->purpose
!= CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
) {
664 log_fn(LOG_WARN
, "received INTRO_ESTABLISHED cell on non-intro circuit");
667 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
669 log_fn(LOG_WARN
, "Unknown service on introduction circuit %d",
673 service
->desc_is_dirty
= time(NULL
);
674 circuit
->purpose
= CIRCUIT_PURPOSE_S_INTRO
;
678 circuit_mark_for_close(circuit
);
682 /** Called once a circuit to a rendezvous point is established: sends a
683 * RELAY_COMMAND_RENDEZVOUS1 cell.
686 rend_service_rendezvous_has_opened(circuit_t
*circuit
)
688 rend_service_t
*service
;
689 char buf
[RELAY_PAYLOAD_SIZE
];
691 char serviceid
[REND_SERVICE_ID_LEN
+1];
694 tor_assert(circuit
->purpose
== CIRCUIT_PURPOSE_S_CONNECT_REND
);
695 tor_assert(circuit
->cpath
);
696 tor_assert(circuit
->build_state
);
697 hop
= circuit
->build_state
->pending_final_cpath
;
700 base16_encode(hexcookie
,9,circuit
->rend_cookie
,4);
701 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
702 circuit
->rend_pk_digest
,10);
705 "Done building circuit %d to rendezvous with cookie %s for service %s",
706 circuit
->n_circ_id
, hexcookie
, serviceid
);
708 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
710 log_fn(LOG_WARN
, "Internal error: unrecognized service ID on introduction circuit");
714 /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
715 memcpy(buf
, circuit
->rend_cookie
, REND_COOKIE_LEN
);
716 if (crypto_dh_get_public(hop
->handshake_state
,
717 buf
+REND_COOKIE_LEN
, DH_KEY_LEN
)<0) {
718 log_fn(LOG_WARN
,"Couldn't get DH public key");
721 memcpy(buf
+REND_COOKIE_LEN
+DH_KEY_LEN
, hop
->handshake_digest
,
725 if (connection_edge_send_command(NULL
, circuit
, RELAY_COMMAND_RENDEZVOUS1
,
726 buf
, REND_COOKIE_LEN
+DH_KEY_LEN
+DIGEST_LEN
,
727 circuit
->cpath
->prev
)<0) {
728 log_fn(LOG_WARN
, "Couldn't send RENDEZVOUS1 cell");
732 crypto_dh_free(hop
->handshake_state
);
733 hop
->handshake_state
= NULL
;
735 /* Append the cpath entry. */
736 hop
->state
= CPATH_STATE_OPEN
;
737 /* set the windows to default. these are the windows
738 * that bob thinks alice has.
740 hop
->package_window
= CIRCWINDOW_START
;
741 hop
->deliver_window
= CIRCWINDOW_START
;
743 onion_append_to_cpath(&circuit
->cpath
, hop
);
744 circuit
->build_state
->pending_final_cpath
= NULL
; /* prevent double-free */
746 /* Change the circuit purpose. */
747 circuit
->purpose
= CIRCUIT_PURPOSE_S_REND_JOINED
;
751 circuit_mark_for_close(circuit
);
755 * Manage introduction points
758 /** Return the (possibly non-open) introduction circuit ending at
759 * <b>router</b> for the service whose public key is <b>pk_digest</b>. Return
760 * NULL if no such service is found.
763 find_intro_circuit(routerinfo_t
*router
, const char *pk_digest
)
765 circuit_t
*circ
= NULL
;
768 while ((circ
= circuit_get_next_by_pk_and_purpose(circ
,pk_digest
,
769 CIRCUIT_PURPOSE_S_INTRO
))) {
770 tor_assert(circ
->cpath
);
771 if (circ
->build_state
->chosen_exit_name
&&
772 !strcasecmp(circ
->build_state
->chosen_exit_name
, router
->nickname
)) {
778 while ((circ
= circuit_get_next_by_pk_and_purpose(circ
,pk_digest
,
779 CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
))) {
780 tor_assert(circ
->cpath
);
781 if (circ
->build_state
->chosen_exit_name
&&
782 !strcasecmp(circ
->build_state
->chosen_exit_name
, router
->nickname
)) {
789 /** Encode and sign an up-to-date service descriptor for <b>service</b>,
790 * and upload it to all the dirservers.
793 upload_service_descriptor(rend_service_t
*service
)
798 /* Update the descriptor. */
799 rend_service_update_descriptor(service
);
800 if (rend_encode_service_descriptor(service
->desc
,
801 service
->private_key
,
802 &desc
, &desc_len
)<0) {
803 log_fn(LOG_WARN
, "Couldn't encode service descriptor; not uploading");
807 /* Post it to the dirservers */
808 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC
, desc
, desc_len
);
811 service
->desc_is_dirty
= 0;
814 /* XXXX Make this longer once directories remember service descriptors across
816 #define MAX_SERVICE_PUBLICATION_INTERVAL (15*60)
818 /** For every service, check how many intro points it currently has, and:
819 * - Pick new intro points as necessary.
820 * - Launch circuits to any new intro points.
822 void rend_services_introduce(void) {
824 routerinfo_t
*router
;
825 rend_service_t
*service
;
827 int changed
, prev_intro_nodes
;
828 smartlist_t
*intro_routers
, *exclude_routers
;
831 intro_routers
= smartlist_create();
832 exclude_routers
= smartlist_create();
835 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
836 smartlist_clear(intro_routers
);
837 service
= smartlist_get(rend_service_list
, i
);
841 if (now
> service
->intro_period_started
+INTRO_CIRC_RETRY_PERIOD
) {
842 /* One period has elapsed; we can try building circuits again. */
843 service
->intro_period_started
= now
;
844 service
->n_intro_circuits_launched
= 0;
845 } else if (service
->n_intro_circuits_launched
>=
846 MAX_INTRO_CIRCS_PER_PERIOD
) {
847 /* We have failed too many times in this period; wait for the next
848 * one before we try again. */
852 /* Find out which introduction points we have in progress for this service. */
853 for (j
=0; j
< smartlist_len(service
->intro_nodes
); ++j
) {
854 intro
= smartlist_get(service
->intro_nodes
, j
);
855 router
= router_get_by_nickname(intro
);
856 if (!router
|| !find_intro_circuit(router
,service
->pk_digest
)) {
857 log_fn(LOG_INFO
,"Giving up on %s as intro point for %s.",
858 intro
, service
->service_id
);
860 smartlist_del(service
->intro_nodes
,j
--);
862 service
->desc_is_dirty
= now
;
864 smartlist_add(intro_routers
, router
);
867 /* We have enough intro points, and the intro points we thought we had were
870 if (!changed
&& smartlist_len(service
->intro_nodes
) >= NUM_INTRO_POINTS
) {
871 /* We have all our intro points! Start a fresh period and reset the
873 service
->intro_period_started
= now
;
874 service
->n_intro_circuits_launched
= 0;
878 /* Remember how many introduction circuits we started with. */
879 prev_intro_nodes
= smartlist_len(service
->intro_nodes
);
881 smartlist_add_all(exclude_routers
, intro_routers
);
882 /* The directory is now here. Pick three ORs as intro points. */
883 for (j
=prev_intro_nodes
; j
< NUM_INTRO_POINTS
; ++j
) {
884 router
= router_choose_random_node(service
->intro_prefer_nodes
,
885 service
->intro_exclude_nodes
, exclude_routers
, 1, 0,
886 get_options()->_AllowUnverified
& ALLOW_UNVERIFIED_INTRODUCTION
, 0);
888 log_fn(LOG_WARN
, "Could only establish %d introduction points for %s",
889 smartlist_len(service
->intro_nodes
), service
->service_id
);
893 smartlist_add(intro_routers
, router
);
894 smartlist_add(exclude_routers
, router
);
895 /*XXX009 should strdup the hexdigest, not nickname */
896 smartlist_add(service
->intro_nodes
, tor_strdup(router
->nickname
));
897 log_fn(LOG_INFO
,"Picked router %s as an intro point for %s.", router
->nickname
,
898 service
->service_id
);
901 /* Reset exclude_routers, for the next time around the loop. */
902 smartlist_clear(exclude_routers
);
904 /* If there's no need to launch new circuits, stop here. */
908 /* Establish new introduction points. */
909 for (j
=prev_intro_nodes
; j
< smartlist_len(service
->intro_nodes
); ++j
) {
910 intro
= smartlist_get(service
->intro_nodes
, j
);
911 r
= rend_service_launch_establish_intro(service
, intro
);
913 log_fn(LOG_WARN
, "Error launching circuit to node %s for service %s",
914 intro
, service
->service_id
);
918 smartlist_free(intro_routers
);
919 smartlist_free(exclude_routers
);
922 /** Regenerate and upload rendezvous service descriptors for all
923 * services, if necessary. If the descriptor has been dirty enough
924 * for long enough, definitely upload; else only upload when the
925 * periodic timeout has expired.
927 * For the first upload, pick a random time between now and two periods
928 * from now, and pick it independently for each service.
931 rend_consider_services_upload(time_t now
) {
933 rend_service_t
*service
;
934 int rendpostperiod
= get_options()->RendPostPeriod
;
936 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
937 service
= smartlist_get(rend_service_list
, i
);
938 if (!service
->next_upload_time
) { /* never been uploaded yet */
939 service
->next_upload_time
=
940 now
+ crypto_pseudo_rand_int(2*rendpostperiod
);
942 if (service
->next_upload_time
< now
||
943 (service
->desc_is_dirty
&&
944 service
->desc_is_dirty
< now
-5)) {
945 /* if it's time, or if the directory servers have a wrong service
946 * descriptor and ours has been stable for 5 seconds, upload a
948 upload_service_descriptor(service
);
949 service
->next_upload_time
= now
+ rendpostperiod
;
954 /** Log the status of introduction points for all rendezvous services
955 * at log severity <b>severity</b>.
958 rend_service_dump_stats(int severity
)
961 routerinfo_t
*router
;
962 rend_service_t
*service
;
966 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
967 service
= smartlist_get(rend_service_list
, i
);
968 log(severity
, "Service configured in %s:", service
->directory
);
969 for (j
=0; j
< smartlist_len(service
->intro_nodes
); ++j
) {
970 nickname
= smartlist_get(service
->intro_nodes
, j
);
971 router
= router_get_by_nickname(smartlist_get(service
->intro_nodes
,j
));
973 log(severity
, " Intro point at %s: unrecognized router",nickname
);
976 circ
= find_intro_circuit(router
, service
->pk_digest
);
978 log(severity
, " Intro point at %s: no circuit",nickname
);
981 log(severity
, " Intro point at %s: circuit is %s",nickname
,
982 circuit_state_to_string
[circ
->state
]);
987 /** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
988 * 'circ', and look up the port and address based on conn-\>port.
989 * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
993 rend_service_set_connection_addr_port(connection_t
*conn
, circuit_t
*circ
)
995 rend_service_t
*service
;
997 rend_service_port_config_t
*p
;
998 char serviceid
[REND_SERVICE_ID_LEN
+1];
1000 tor_assert(circ
->purpose
== CIRCUIT_PURPOSE_S_REND_JOINED
);
1001 log_fn(LOG_DEBUG
,"beginning to hunt for addr/port");
1002 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
1003 circ
->rend_pk_digest
,10);
1004 service
= rend_service_get_by_pk_digest(circ
->rend_pk_digest
);
1006 log_fn(LOG_WARN
, "Couldn't find any service associated with pk %s on rendezvous circuit %d; closing",
1007 serviceid
, circ
->n_circ_id
);
1010 for (i
= 0; i
< smartlist_len(service
->ports
); ++i
) {
1011 p
= smartlist_get(service
->ports
, i
);
1012 if (conn
->port
== p
->virtual_port
) {
1013 conn
->addr
= p
->real_address
;
1014 conn
->port
= p
->real_port
;
1018 log_fn(LOG_INFO
, "No virtual port mapping exists for port %d on service %s",
1019 conn
->port
,serviceid
);