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 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
= NULL
;
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 char addrbuf
[INET_NTOA_BUF_LEN
];
117 p
= smartlist_get(service
->ports
, i
);
118 addr
.s_addr
= htonl(p
->real_address
);
119 tor_inet_ntoa(&addr
, addrbuf
, sizeof(addrbuf
));
120 log_fn(LOG_DEBUG
,"Service maps port %d to %s:%d",
121 p
->virtual_port
, addrbuf
, p
->real_port
);
126 /** Parses a real-port to virtual-port mapping and returns a new
127 * rend_service_port_config_t.
129 * The format is: VirtualPort (IP|RealPort|IP:RealPort)?
131 * IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
133 static rend_service_port_config_t
*parse_port_config(const char *string
)
140 rend_service_port_config_t
*result
;
142 virtport
= (int) strtol(string
, &endptr
, 10);
143 if (endptr
== string
) {
144 log_fn(LOG_WARN
, "Missing port in hidden service port configuration");
147 if (virtport
< 1 || virtport
> 65535) {
148 log_fn(LOG_WARN
, "Port out of range in hidden service port configuration");
151 string
= endptr
+ strspn(endptr
, " \t");
153 /* No addr:port part; use default. */
155 addr
= 0x7F000001u
; /* 127.0.0.1 */
156 } else if (strchr(string
, ':') || strchr(string
, '.')) {
157 if (parse_addr_port(string
, NULL
, &addr
, &p
)<0) {
158 log_fn(LOG_WARN
,"Unparseable address in hidden service port configuration");
161 realport
= p
?p
:virtport
;
163 /* No addr:port, no addr -- must be port. */
164 realport
= strtol(string
, &endptr
, 10);
166 log_fn(LOG_WARN
, "Unparseable or missing port in hidden service port configuration.");
169 if (realport
< 1 || realport
> 65535) {
170 log_fn(LOG_WARN
, "Port out of range");
173 addr
= 0x7F000001u
; /* Default to 127.0.0.1 */
176 result
= tor_malloc(sizeof(rend_service_port_config_t
));
177 result
->virtual_port
= virtport
;
178 result
->real_port
= realport
;
179 result
->real_address
= addr
;
183 /** Set up rend_service_list, based on the values of HiddenServiceDir and
184 * HiddenServicePort in <b>options</b>. Return 0 on success and -1 on
185 * failure. (If <b>validate_only</b> is set, parse, warn and return as
186 * normal, but don't actually change the configured services.)
189 int rend_config_services(or_options_t
*options
, int validate_only
)
191 struct config_line_t
*line
;
192 rend_service_t
*service
= NULL
;
193 rend_service_port_config_t
*portcfg
;
195 if (!validate_only
) {
196 rend_service_free_all();
197 rend_service_list
= smartlist_create();
200 for (line
= options
->RendConfigLines
; line
; line
= line
->next
) {
201 if (!strcasecmp(line
->key
, "HiddenServiceDir")) {
204 rend_service_free(service
);
206 add_service(service
);
208 service
= tor_malloc_zero(sizeof(rend_service_t
));
209 service
->directory
= tor_strdup(line
->value
);
210 service
->ports
= smartlist_create();
211 service
->intro_nodes
= smartlist_create();
212 service
->intro_period_started
= time(NULL
);
216 log_fn(LOG_WARN
, "HiddenServicePort with no preceding HiddenServiceDir directive");
217 rend_service_free(service
);
220 if (!strcasecmp(line
->key
, "HiddenServicePort")) {
221 portcfg
= parse_port_config(line
->value
);
223 rend_service_free(service
);
226 smartlist_add(service
->ports
, portcfg
);
227 } else if (!strcasecmp(line
->key
, "HiddenServiceNodes")) {
228 if (service
->intro_prefer_nodes
) {
229 log_fn(LOG_WARN
, "Got multiple HiddenServiceNodes lines for a single service");
232 service
->intro_prefer_nodes
= tor_strdup(line
->value
);
234 tor_assert(!strcasecmp(line
->key
, "HiddenServiceExcludeNodes"));
235 if (service
->intro_exclude_nodes
) {
236 log_fn(LOG_WARN
, "Got multiple HiddenServiceExcludedNodes lines for a single service");
239 service
->intro_exclude_nodes
= tor_strdup(line
->value
);
244 rend_service_free(service
);
246 add_service(service
);
252 /** Replace the old value of <b>service</b>-\>desc with one that reflects
253 * the other fields in service.
255 static void rend_service_update_descriptor(rend_service_t
*service
)
257 rend_service_descriptor_t
*d
;
260 routerinfo_t
*router
;
263 rend_service_descriptor_free(service
->desc
);
264 service
->desc
= NULL
;
266 d
= service
->desc
= tor_malloc(sizeof(rend_service_descriptor_t
));
267 d
->pk
= crypto_pk_dup_key(service
->private_key
);
268 d
->timestamp
= time(NULL
);
269 n
= smartlist_len(service
->intro_nodes
);
270 d
->n_intro_points
= 0;
271 d
->intro_points
= tor_malloc(sizeof(char*)*n
);
272 for (i
=0; i
< n
; ++i
) {
273 router
= router_get_by_nickname(smartlist_get(service
->intro_nodes
, i
));
275 log_fn(LOG_WARN
,"Router '%s' not found. Skipping.",
276 (char*)smartlist_get(service
->intro_nodes
, i
));
279 circ
= find_intro_circuit(router
, service
->pk_digest
);
280 if (circ
&& circ
->purpose
== CIRCUIT_PURPOSE_S_INTRO
) {
281 /* We have an entirely established intro circuit. */
282 d
->intro_points
[d
->n_intro_points
++] = tor_strdup(router
->nickname
);
287 /** Load and/or generate private keys for all hidden services. Return 0 on
288 * success, -1 on failure.
290 int rend_service_load_keys(void)
297 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
298 s
= smartlist_get(rend_service_list
,i
);
301 log_fn(LOG_INFO
, "Loading hidden-service keys from '%s'", s
->directory
);
303 /* Check/create directory */
304 if (check_private_dir(s
->directory
, CPD_CREATE
) < 0)
308 if (strlcpy(fname
,s
->directory
,sizeof(fname
)) >= sizeof(fname
) ||
309 strlcat(fname
,"/private_key",sizeof(fname
)) >= sizeof(fname
)) {
310 log_fn(LOG_WARN
, "Directory name too long: '%s'", s
->directory
);
313 s
->private_key
= init_key_from_file(fname
);
317 /* Create service file */
318 if (rend_get_service_id(s
->private_key
, s
->service_id
)<0) {
319 log_fn(LOG_WARN
, "Couldn't encode service ID");
322 if (crypto_pk_get_digest(s
->private_key
, s
->pk_digest
)<0) {
323 log_fn(LOG_WARN
, "Couldn't compute hash of public key");
326 if (strlcpy(fname
,s
->directory
,sizeof(fname
)) >= sizeof(fname
) ||
327 strlcat(fname
,"/hostname",sizeof(fname
)) >= sizeof(fname
)) {
328 log_fn(LOG_WARN
, "Directory name too long: '%s'", s
->directory
);
331 tor_snprintf(buf
, sizeof(buf
),"%s.onion\n", s
->service_id
);
332 if (write_str_to_file(fname
,buf
,0)<0)
338 /** Return the service whose public key has a digest of <b>digest</b>. Return
339 * NULL if no such service exists.
341 static rend_service_t
*
342 rend_service_get_by_pk_digest(const char* digest
)
344 SMARTLIST_FOREACH(rend_service_list
, rend_service_t
*, s
,
345 if (!memcmp(s
->pk_digest
,digest
,DIGEST_LEN
)) return s
);
349 /** Return 1 if any virtual port in <b>service</b> wants a circuit
350 * to have good uptime. Else return 0.
353 rend_service_requires_uptime(rend_service_t
*service
) {
355 rend_service_port_config_t
*p
;
357 for (i
=0; i
< smartlist_len(service
->ports
); ++i
) {
358 p
= smartlist_get(service
->ports
, i
);
359 if (smartlist_string_num_isin(get_options()->LongLivedPorts
, p
->virtual_port
))
369 /** Respond to an INTRODUCE2 cell by launching a circuit to the chosen
373 rend_service_introduce(circuit_t
*circuit
, const char *request
, size_t request_len
)
375 char *ptr
, *rp_nickname
, *r_cookie
;
376 char buf
[RELAY_PAYLOAD_SIZE
];
377 char keys
[DIGEST_LEN
+CPATH_KEY_MATERIAL_LEN
]; /* Holds KH, Df, Db, Kf, Kb */
378 rend_service_t
*service
;
381 crypto_dh_env_t
*dh
= NULL
;
382 circuit_t
*launched
= NULL
;
383 crypt_path_t
*cpath
= NULL
;
384 char serviceid
[REND_SERVICE_ID_LEN
+1];
387 size_t nickname_field_len
;
388 int circ_needs_uptime
;
390 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
391 circuit
->rend_pk_digest
,10);
392 log_fn(LOG_INFO
, "Received INTRODUCE2 cell for service %s on circ %d",
393 serviceid
, circuit
->n_circ_id
);
395 if (circuit
->purpose
!= CIRCUIT_PURPOSE_S_INTRO
) {
396 log_fn(LOG_WARN
, "Got an INTRODUCE2 over a non-introduction circuit %d",
401 /* min key length plus digest length plus nickname length */
402 if (request_len
< DIGEST_LEN
+REND_COOKIE_LEN
+(MAX_NICKNAME_LEN
+1)+
404 log_fn(LOG_WARN
, "Got a truncated INTRODUCE2 cell on circ %d",
409 /* first DIGEST_LEN bytes of request is service pk digest */
410 service
= rend_service_get_by_pk_digest(request
);
412 log_fn(LOG_WARN
, "Got an INTRODUCE2 cell for an unrecognized service %s",
416 if (memcmp(circuit
->rend_pk_digest
, request
, DIGEST_LEN
)) {
417 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1, request
, 10);
418 log_fn(LOG_WARN
, "Got an INTRODUCE2 cell for the wrong service (%s)",
423 keylen
= crypto_pk_keysize(service
->private_key
);
424 if (request_len
< keylen
+DIGEST_LEN
) {
425 log_fn(LOG_WARN
, "PK-encrypted portion of INTRODUCE2 cell was truncated");
428 /* Next N bytes is encrypted with service key */
429 r
= crypto_pk_private_hybrid_decrypt(
430 service
->private_key
,buf
,request
+DIGEST_LEN
,request_len
-DIGEST_LEN
,
431 PK_PKCS1_OAEP_PADDING
,1);
433 log_fn(LOG_WARN
, "Couldn't decrypt INTRODUCE2 cell");
439 nickname_field_len
= MAX_HEX_NICKNAME_LEN
+1;
442 nickname_field_len
= MAX_NICKNAME_LEN
+1;
446 /* XXX when 0.0.9.x is obsolete, change this to reject version != 1. */
447 ptr
=memchr(rp_nickname
,0,nickname_field_len
);
448 if (!ptr
|| ptr
== rp_nickname
) {
449 log_fn(LOG_WARN
, "Couldn't find a null-padded nickname in INTRODUCE2 cell");
452 if ((version
== 0 && !is_legal_nickname(rp_nickname
)) ||
453 (version
== 1 && !is_legal_nickname_or_hexdigest(rp_nickname
))) {
454 log_fn(LOG_WARN
, "Bad nickname in INTRODUCE2 cell.");
457 /* Okay, now we know that a nickname is at the start of the buffer. */
458 ptr
= rp_nickname
+nickname_field_len
;
459 len
-= nickname_field_len
;
460 len
-= rp_nickname
- buf
; /* also remove header space used by version, if any */
461 if (len
!= REND_COOKIE_LEN
+DH_KEY_LEN
) {
462 log_fn(LOG_WARN
, "Bad length %u for INTRODUCE2 cell.", (int)len
);
466 base16_encode(hexcookie
,9,r_cookie
,4);
468 /* Try DH handshake... */
469 dh
= crypto_dh_new();
470 if (!dh
|| crypto_dh_generate_public(dh
)<0) {
471 log_fn(LOG_WARN
, "Couldn't build DH state or generate public key");
474 if (crypto_dh_compute_secret(dh
, ptr
+REND_COOKIE_LEN
, DH_KEY_LEN
, keys
,
475 DIGEST_LEN
+CPATH_KEY_MATERIAL_LEN
)<0) {
476 log_fn(LOG_WARN
, "Couldn't complete DH handshake");
480 circ_needs_uptime
= rend_service_requires_uptime(service
);
482 /* help predict this next time */
483 rep_hist_note_used_hidserv(time(NULL
), circ_needs_uptime
, 1);
485 /* Launch a circuit to alice's chosen rendezvous point.
487 for (i
=0;i
<MAX_REND_FAILURES
;i
++) {
488 launched
= circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_CONNECT_REND
, rp_nickname
,
489 circ_needs_uptime
, 1, 1);
493 if (!launched
) { /* give up */
494 log_fn(LOG_WARN
,"Giving up launching first hop of circuit to rendezvous point '%s' for service %s",
495 rp_nickname
, serviceid
);
499 "Accepted intro; launching circuit to '%s' (cookie %s) for service %s",
500 rp_nickname
, hexcookie
, serviceid
);
501 tor_assert(launched
->build_state
);
502 /* Fill in the circuit's state. */
503 memcpy(launched
->rend_pk_digest
, circuit
->rend_pk_digest
,
505 memcpy(launched
->rend_cookie
, r_cookie
, REND_COOKIE_LEN
);
506 strlcpy(launched
->rend_query
, service
->service_id
,
507 sizeof(launched
->rend_query
));
508 launched
->build_state
->pending_final_cpath
= cpath
=
509 tor_malloc_zero(sizeof(crypt_path_t
));
511 cpath
->handshake_state
= dh
;
513 if (circuit_init_cpath_crypto(cpath
,keys
+DIGEST_LEN
,1)<0)
515 memcpy(cpath
->handshake_digest
, keys
, DIGEST_LEN
);
519 if (dh
) crypto_dh_free(dh
);
520 if (launched
) circuit_mark_for_close(launched
);
524 /** Called when we fail building a rendezvous circuit at some point other
525 * than the last hop: launches a new circuit to the same rendezvous point.
528 rend_service_relaunch_rendezvous(circuit_t
*oldcirc
)
531 cpath_build_state_t
*newstate
, *oldstate
;
533 tor_assert(oldcirc
->purpose
== CIRCUIT_PURPOSE_S_CONNECT_REND
);
535 if (!oldcirc
->build_state
||
536 oldcirc
->build_state
->failure_count
> MAX_REND_FAILURES
) {
537 log_fn(LOG_INFO
,"Attempt to build circuit to %s for rendezvous has failed too many times; giving up.",
538 oldcirc
->build_state
->chosen_exit_name
);
542 oldstate
= oldcirc
->build_state
;
543 tor_assert(oldstate
);
545 if (oldstate
->pending_final_cpath
== NULL
) {
546 log_fn(LOG_INFO
,"Skipping relaunch of circ that failed on its first hop. Initiator will retry.");
550 log_fn(LOG_INFO
,"Reattempting rendezvous circuit to %s",
551 oldstate
->chosen_exit_name
);
553 newcirc
= circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_CONNECT_REND
,
554 oldstate
->chosen_exit_name
, 0, 1, 1);
556 log_fn(LOG_WARN
,"Couldn't relaunch rendezvous circuit to %s",
557 oldstate
->chosen_exit_name
);
560 newstate
= newcirc
->build_state
;
561 tor_assert(newstate
);
562 newstate
->failure_count
= oldstate
->failure_count
+1;
563 newstate
->pending_final_cpath
= oldstate
->pending_final_cpath
;
564 oldstate
->pending_final_cpath
= NULL
;
566 memcpy(newcirc
->rend_query
, oldcirc
->rend_query
, REND_SERVICE_ID_LEN
+1);
567 memcpy(newcirc
->rend_pk_digest
, oldcirc
->rend_pk_digest
, DIGEST_LEN
);
568 memcpy(newcirc
->rend_cookie
, oldcirc
->rend_cookie
, REND_COOKIE_LEN
);
571 /** Launch a circuit to serve as an introduction point for the service
572 * <b>service</b> at the introduction point <b>nickname</b>
575 rend_service_launch_establish_intro(rend_service_t
*service
, const char *nickname
)
579 log_fn(LOG_INFO
, "Launching circuit to introduction point %s for service %s",
580 nickname
, service
->service_id
);
582 rep_hist_note_used_hidserv(time(NULL
), 1, 0);
584 ++service
->n_intro_circuits_launched
;
585 launched
= circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
, nickname
, 1, 0, 1);
587 log_fn(LOG_WARN
, "Can't launch circuit to establish introduction at '%s'",
591 strlcpy(launched
->rend_query
, service
->service_id
,
592 sizeof(launched
->rend_query
));
593 memcpy(launched
->rend_pk_digest
, service
->pk_digest
, DIGEST_LEN
);
598 /** Called when we're done building a circuit to an introduction point:
599 * sends a RELAY_ESTABLISH_INTRO cell.
602 rend_service_intro_has_opened(circuit_t
*circuit
)
604 rend_service_t
*service
;
607 char buf
[RELAY_PAYLOAD_SIZE
];
608 char auth
[DIGEST_LEN
+ 9];
609 char serviceid
[REND_SERVICE_ID_LEN
+1];
611 tor_assert(circuit
->purpose
== CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
);
612 tor_assert(CIRCUIT_IS_ORIGIN(circuit
));
613 tor_assert(circuit
->cpath
);
615 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
616 circuit
->rend_pk_digest
,10);
618 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
620 log_fn(LOG_WARN
, "Unrecognized service ID %s on introduction circuit %d",
621 serviceid
, circuit
->n_circ_id
);
626 "Established circuit %d as introduction point for service %s",
627 circuit
->n_circ_id
, serviceid
);
629 /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
630 len
= crypto_pk_asn1_encode(service
->private_key
, buf
+2,
631 RELAY_PAYLOAD_SIZE
-2);
632 set_uint16(buf
, htons((uint16_t)len
));
634 memcpy(auth
, circuit
->cpath
->prev
->handshake_digest
, DIGEST_LEN
);
635 memcpy(auth
+DIGEST_LEN
, "INTRODUCE", 9);
636 if (crypto_digest(buf
+len
, auth
, DIGEST_LEN
+9))
639 r
= crypto_pk_private_sign_digest(service
->private_key
, buf
+len
, buf
, len
);
641 log_fn(LOG_WARN
, "Couldn't sign introduction request");
646 if (connection_edge_send_command(NULL
, circuit
,RELAY_COMMAND_ESTABLISH_INTRO
,
647 buf
, len
, circuit
->cpath
->prev
)<0) {
649 "Couldn't send introduction request for service %s on circuit %d",
650 serviceid
, circuit
->n_circ_id
);
656 circuit_mark_for_close(circuit
);
659 /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
660 * live introduction point, and note that the service descriptor is
663 rend_service_intro_established(circuit_t
*circuit
, const char *request
, size_t request_len
)
665 rend_service_t
*service
;
667 if (circuit
->purpose
!= CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
) {
668 log_fn(LOG_WARN
, "received INTRO_ESTABLISHED cell on non-intro circuit");
671 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
673 log_fn(LOG_WARN
, "Unknown service on introduction circuit %d",
677 service
->desc_is_dirty
= time(NULL
);
678 circuit
->purpose
= CIRCUIT_PURPOSE_S_INTRO
;
682 circuit_mark_for_close(circuit
);
686 /** Called once a circuit to a rendezvous point is established: sends a
687 * RELAY_COMMAND_RENDEZVOUS1 cell.
690 rend_service_rendezvous_has_opened(circuit_t
*circuit
)
692 rend_service_t
*service
;
693 char buf
[RELAY_PAYLOAD_SIZE
];
695 char serviceid
[REND_SERVICE_ID_LEN
+1];
698 tor_assert(circuit
->purpose
== CIRCUIT_PURPOSE_S_CONNECT_REND
);
699 tor_assert(circuit
->cpath
);
700 tor_assert(circuit
->build_state
);
701 hop
= circuit
->build_state
->pending_final_cpath
;
704 base16_encode(hexcookie
,9,circuit
->rend_cookie
,4);
705 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
706 circuit
->rend_pk_digest
,10);
709 "Done building circuit %d to rendezvous with cookie %s for service %s",
710 circuit
->n_circ_id
, hexcookie
, serviceid
);
712 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
714 log_fn(LOG_WARN
, "Internal error: unrecognized service ID on introduction circuit");
718 /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
719 memcpy(buf
, circuit
->rend_cookie
, REND_COOKIE_LEN
);
720 if (crypto_dh_get_public(hop
->handshake_state
,
721 buf
+REND_COOKIE_LEN
, DH_KEY_LEN
)<0) {
722 log_fn(LOG_WARN
,"Couldn't get DH public key");
725 memcpy(buf
+REND_COOKIE_LEN
+DH_KEY_LEN
, hop
->handshake_digest
,
729 if (connection_edge_send_command(NULL
, circuit
, RELAY_COMMAND_RENDEZVOUS1
,
730 buf
, REND_COOKIE_LEN
+DH_KEY_LEN
+DIGEST_LEN
,
731 circuit
->cpath
->prev
)<0) {
732 log_fn(LOG_WARN
, "Couldn't send RENDEZVOUS1 cell");
736 crypto_dh_free(hop
->handshake_state
);
737 hop
->handshake_state
= NULL
;
739 /* Append the cpath entry. */
740 hop
->state
= CPATH_STATE_OPEN
;
741 /* set the windows to default. these are the windows
742 * that bob thinks alice has.
744 hop
->package_window
= CIRCWINDOW_START
;
745 hop
->deliver_window
= CIRCWINDOW_START
;
747 onion_append_to_cpath(&circuit
->cpath
, hop
);
748 circuit
->build_state
->pending_final_cpath
= NULL
; /* prevent double-free */
750 /* Change the circuit purpose. */
751 circuit
->purpose
= CIRCUIT_PURPOSE_S_REND_JOINED
;
755 circuit_mark_for_close(circuit
);
759 * Manage introduction points
762 /** Return the (possibly non-open) introduction circuit ending at
763 * <b>router</b> for the service whose public key is <b>pk_digest</b>. Return
764 * NULL if no such service is found.
767 find_intro_circuit(routerinfo_t
*router
, const char *pk_digest
)
769 circuit_t
*circ
= NULL
;
772 while ((circ
= circuit_get_next_by_pk_and_purpose(circ
,pk_digest
,
773 CIRCUIT_PURPOSE_S_INTRO
))) {
774 tor_assert(circ
->cpath
);
775 if (circ
->build_state
->chosen_exit_name
&&
776 !strcasecmp(circ
->build_state
->chosen_exit_name
, router
->nickname
)) {
782 while ((circ
= circuit_get_next_by_pk_and_purpose(circ
,pk_digest
,
783 CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
))) {
784 tor_assert(circ
->cpath
);
785 if (circ
->build_state
->chosen_exit_name
&&
786 !strcasecmp(circ
->build_state
->chosen_exit_name
, router
->nickname
)) {
793 /** Encode and sign an up-to-date service descriptor for <b>service</b>,
794 * and upload it to all the dirservers.
797 upload_service_descriptor(rend_service_t
*service
)
802 /* Update the descriptor. */
803 rend_service_update_descriptor(service
);
804 if (rend_encode_service_descriptor(service
->desc
,
805 service
->private_key
,
806 &desc
, &desc_len
)<0) {
807 log_fn(LOG_WARN
, "Couldn't encode service descriptor; not uploading");
811 /* Post it to the dirservers */
812 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC
, desc
, desc_len
);
815 service
->desc_is_dirty
= 0;
818 /* XXXX Make this longer once directories remember service descriptors across
820 #define MAX_SERVICE_PUBLICATION_INTERVAL (15*60)
822 /** For every service, check how many intro points it currently has, and:
823 * - Pick new intro points as necessary.
824 * - Launch circuits to any new intro points.
826 void rend_services_introduce(void) {
828 routerinfo_t
*router
;
829 rend_service_t
*service
;
831 int changed
, prev_intro_nodes
;
832 smartlist_t
*intro_routers
, *exclude_routers
;
835 intro_routers
= smartlist_create();
836 exclude_routers
= smartlist_create();
839 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
840 smartlist_clear(intro_routers
);
841 service
= smartlist_get(rend_service_list
, i
);
845 if (now
> service
->intro_period_started
+INTRO_CIRC_RETRY_PERIOD
) {
846 /* One period has elapsed; we can try building circuits again. */
847 service
->intro_period_started
= now
;
848 service
->n_intro_circuits_launched
= 0;
849 } else if (service
->n_intro_circuits_launched
>=
850 MAX_INTRO_CIRCS_PER_PERIOD
) {
851 /* We have failed too many times in this period; wait for the next
852 * one before we try again. */
856 /* Find out which introduction points we have in progress for this service. */
857 for (j
=0; j
< smartlist_len(service
->intro_nodes
); ++j
) {
858 intro
= smartlist_get(service
->intro_nodes
, j
);
859 router
= router_get_by_nickname(intro
);
860 if (!router
|| !find_intro_circuit(router
,service
->pk_digest
)) {
861 log_fn(LOG_INFO
,"Giving up on %s as intro point for %s.",
862 intro
, service
->service_id
);
864 smartlist_del(service
->intro_nodes
,j
--);
866 service
->desc_is_dirty
= now
;
868 smartlist_add(intro_routers
, router
);
871 /* We have enough intro points, and the intro points we thought we had were
874 if (!changed
&& smartlist_len(service
->intro_nodes
) >= NUM_INTRO_POINTS
) {
875 /* We have all our intro points! Start a fresh period and reset the
877 service
->intro_period_started
= now
;
878 service
->n_intro_circuits_launched
= 0;
882 /* Remember how many introduction circuits we started with. */
883 prev_intro_nodes
= smartlist_len(service
->intro_nodes
);
885 smartlist_add_all(exclude_routers
, intro_routers
);
886 /* The directory is now here. Pick three ORs as intro points. */
887 for (j
=prev_intro_nodes
; j
< NUM_INTRO_POINTS
; ++j
) {
888 router
= router_choose_random_node(service
->intro_prefer_nodes
,
889 service
->intro_exclude_nodes
, exclude_routers
, 1, 0,
890 get_options()->_AllowUnverified
& ALLOW_UNVERIFIED_INTRODUCTION
, 0);
892 log_fn(LOG_WARN
, "Could only establish %d introduction points for %s",
893 smartlist_len(service
->intro_nodes
), service
->service_id
);
897 smartlist_add(intro_routers
, router
);
898 smartlist_add(exclude_routers
, router
);
899 /*XXX009 should strdup the hexdigest, not nickname */
900 smartlist_add(service
->intro_nodes
, tor_strdup(router
->nickname
));
901 log_fn(LOG_INFO
,"Picked router %s as an intro point for %s.", router
->nickname
,
902 service
->service_id
);
905 /* Reset exclude_routers, for the next time around the loop. */
906 smartlist_clear(exclude_routers
);
908 /* If there's no need to launch new circuits, stop here. */
912 /* Establish new introduction points. */
913 for (j
=prev_intro_nodes
; j
< smartlist_len(service
->intro_nodes
); ++j
) {
914 intro
= smartlist_get(service
->intro_nodes
, j
);
915 r
= rend_service_launch_establish_intro(service
, intro
);
917 log_fn(LOG_WARN
, "Error launching circuit to node %s for service %s",
918 intro
, service
->service_id
);
922 smartlist_free(intro_routers
);
923 smartlist_free(exclude_routers
);
926 /** Regenerate and upload rendezvous service descriptors for all
927 * services, if necessary. If the descriptor has been dirty enough
928 * for long enough, definitely upload; else only upload when the
929 * periodic timeout has expired.
931 * For the first upload, pick a random time between now and two periods
932 * from now, and pick it independently for each service.
935 rend_consider_services_upload(time_t now
) {
937 rend_service_t
*service
;
938 int rendpostperiod
= get_options()->RendPostPeriod
;
940 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
941 service
= smartlist_get(rend_service_list
, i
);
942 if (!service
->next_upload_time
) { /* never been uploaded yet */
943 service
->next_upload_time
=
944 now
+ crypto_pseudo_rand_int(2*rendpostperiod
);
946 if (service
->next_upload_time
< now
||
947 (service
->desc_is_dirty
&&
948 service
->desc_is_dirty
< now
-5)) {
949 /* if it's time, or if the directory servers have a wrong service
950 * descriptor and ours has been stable for 5 seconds, upload a
952 upload_service_descriptor(service
);
953 service
->next_upload_time
= now
+ rendpostperiod
;
958 /** Log the status of introduction points for all rendezvous services
959 * at log severity <b>severity</b>.
962 rend_service_dump_stats(int severity
)
965 routerinfo_t
*router
;
966 rend_service_t
*service
;
970 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
971 service
= smartlist_get(rend_service_list
, i
);
972 log(severity
, "Service configured in %s:", service
->directory
);
973 for (j
=0; j
< smartlist_len(service
->intro_nodes
); ++j
) {
974 nickname
= smartlist_get(service
->intro_nodes
, j
);
975 router
= router_get_by_nickname(smartlist_get(service
->intro_nodes
,j
));
977 log(severity
, " Intro point at %s: unrecognized router",nickname
);
980 circ
= find_intro_circuit(router
, service
->pk_digest
);
982 log(severity
, " Intro point at %s: no circuit",nickname
);
985 log(severity
, " Intro point at %s: circuit is %s",nickname
,
986 circuit_state_to_string
[circ
->state
]);
991 /** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
992 * 'circ', and look up the port and address based on conn-\>port.
993 * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
997 rend_service_set_connection_addr_port(connection_t
*conn
, circuit_t
*circ
)
999 rend_service_t
*service
;
1001 rend_service_port_config_t
*p
;
1002 char serviceid
[REND_SERVICE_ID_LEN
+1];
1004 tor_assert(circ
->purpose
== CIRCUIT_PURPOSE_S_REND_JOINED
);
1005 log_fn(LOG_DEBUG
,"beginning to hunt for addr/port");
1006 base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
1007 circ
->rend_pk_digest
,10);
1008 service
= rend_service_get_by_pk_digest(circ
->rend_pk_digest
);
1010 log_fn(LOG_WARN
, "Couldn't find any service associated with pk %s on rendezvous circuit %d; closing",
1011 serviceid
, circ
->n_circ_id
);
1014 for (i
= 0; i
< smartlist_len(service
->ports
); ++i
) {
1015 p
= smartlist_get(service
->ports
, i
);
1016 if (conn
->port
== p
->virtual_port
) {
1017 conn
->addr
= p
->real_address
;
1018 conn
->port
= p
->real_port
;
1022 log_fn(LOG_INFO
, "No virtual port mapping exists for port %d on service %s",
1023 conn
->port
,serviceid
);