1 /* Copyright 2004 Roger Dingledine */
2 /* See LICENSE for licensing information */
7 * \brief The hidden-service side of rendezvous functionality.
12 static circuit_t
*find_intro_circuit(routerinfo_t
*router
, const char *pk_digest
);
14 /** Represents the mapping from a virtual port of a rendezvous service to
15 * a real port on some IP.
17 typedef struct rend_service_port_config_t
{
18 uint16_t virtual_port
;
20 uint32_t real_address
;
21 } rend_service_port_config_t
;
23 /** Try to maintain this many intro points per service if possible. */
24 #define NUM_INTRO_POINTS 3
26 /** If we can't build our intro circuits, don't retry for this long. */
27 #define INTRO_CIRC_RETRY_PERIOD 60*10
28 /** Don't try to build more than this many circuits before giving up
30 #define MAX_INTRO_CIRCS_PER_PERIOD 10
32 /** Represents a single hidden service running at this OP. */
33 typedef struct rend_service_t
{
34 /** Fields specified in config file */
35 char *directory
; /**< where in the filesystem it stores it */
36 smartlist_t
*ports
; /**< List of rend_service_port_config_t */
37 char *intro_prefer_nodes
; /**< comma-separated list of nicknames */
38 char *intro_exclude_nodes
; /**< comma-separated list of nicknames */
40 crypto_pk_env_t
*private_key
;
41 char service_id
[REND_SERVICE_ID_LEN
+1];
42 char pk_digest
[DIGEST_LEN
];
43 smartlist_t
*intro_nodes
; /**< list of nicknames for intro points we have,
44 * or are trying to establish. */
45 time_t intro_period_started
;
46 int n_intro_circuits_launched
; /**< count of intro circuits we have
47 * established in this period. */
48 rend_service_descriptor_t
*desc
;
52 /** A list of rend_service_t's for services run on this OP.
54 static smartlist_t
*rend_service_list
= NULL
;
56 /** Release the storage held by <b>service</b>.
58 static void rend_service_free(rend_service_t
*service
)
61 tor_free(service
->directory
);
62 SMARTLIST_FOREACH(service
->ports
, void*, p
, tor_free(p
));
63 smartlist_free(service
->ports
);
64 if (service
->private_key
)
65 crypto_free_pk_env(service
->private_key
);
66 tor_free(service
->intro_prefer_nodes
);
67 tor_free(service
->intro_exclude_nodes
);
68 SMARTLIST_FOREACH(service
->intro_nodes
, void*, p
, tor_free(p
));
69 smartlist_free(service
->intro_nodes
);
71 rend_service_descriptor_free(service
->desc
);
75 /** Release all the storage held in rend_service_list, and allocate a new,
76 * empty rend_service_list.
78 static void rend_service_free_all(void)
80 if (!rend_service_list
) {
81 rend_service_list
= smartlist_create();
84 SMARTLIST_FOREACH(rend_service_list
, rend_service_t
*, ptr
,
85 rend_service_free(ptr
));
86 smartlist_free(rend_service_list
);
87 rend_service_list
= smartlist_create();
90 /** Validate <b>service</b> and add it to rend_service_list if possible.
92 static void add_service(rend_service_t
*service
)
95 rend_service_port_config_t
*p
;
98 if (!service
->intro_prefer_nodes
)
99 service
->intro_prefer_nodes
= tor_strdup("");
100 if (!service
->intro_exclude_nodes
)
101 service
->intro_exclude_nodes
= tor_strdup("");
103 if (!smartlist_len(service
->ports
)) {
104 log_fn(LOG_WARN
, "Hidden service with no ports configured; ignoring.");
105 rend_service_free(service
);
107 smartlist_set_capacity(service
->ports
, -1);
108 smartlist_add(rend_service_list
, service
);
109 log_fn(LOG_DEBUG
,"Configuring service with directory %s",service
->directory
);
110 for (i
= 0; i
< smartlist_len(service
->ports
); ++i
) {
111 p
= smartlist_get(service
->ports
, i
);
112 addr
.s_addr
= htonl(p
->real_address
);
113 log_fn(LOG_DEBUG
,"Service maps port %d to %s:%d",
114 p
->virtual_port
, inet_ntoa(addr
), p
->real_port
);
119 /** Parses a real-port to virtual-port mapping and returns a new
120 * rend_service_port_config_t.
122 * The format is: VirtualPort (IP|RealPort|IP:RealPort)?
124 * IP defaults to 127.0.0.1; RealPort defaults to VirtualPort.
126 static rend_service_port_config_t
*parse_port_config(const char *string
)
128 int virtport
, realport
, r
;
130 char *endptr
, *colon
, *addrstring
;
131 rend_service_port_config_t
*result
;
133 virtport
= (int) strtol(string
, &endptr
, 10);
134 if (endptr
== string
) {
135 log_fn(LOG_WARN
, "Missing port in hidden service port configuration");
138 if (virtport
< 1 || virtport
> 65535) {
139 log_fn(LOG_WARN
, "Port out of range in hidden service port configuration");
142 string
= endptr
+ strspn(endptr
, " \t");
144 /* No addr:port part; use default. */
146 addr
.s_addr
= htonl(0x7F000001u
); /* 127.0.0.1 */
148 colon
= strchr(string
, ':');
150 /* Try to parse addr:port. */
151 addrstring
= tor_strndup(string
, colon
-string
);
152 r
= tor_inet_aton(addrstring
, &addr
);
153 tor_free(addrstring
);
155 log_fn(LOG_WARN
,"Unparseable address in hidden service port configuration");
158 realport
= strtol(colon
+1, &endptr
, 10);
160 log_fn(LOG_WARN
,"Unparseable or missing port in hidden service port configuration.");
163 } else if (strchr(string
, '.') && tor_inet_aton(string
, &addr
)) {
164 /* We have addr; use deafult port. */
167 /* No addr:port, no addr -- must be port. */
168 realport
= strtol(string
, &endptr
, 10);
170 log_fn(LOG_WARN
, "Unparseable of missing port in hidden service port configuration.");
173 addr
.s_addr
= htonl(0x7F000001u
); /* Default to 127.0.0.1 */
176 if (realport
< 1 || realport
> 65535) {
177 log_fn(LOG_WARN
, "Port out of range in hidden service port configuration.");
181 result
= tor_malloc(sizeof(rend_service_port_config_t
));
182 result
->virtual_port
= virtport
;
183 result
->real_port
= realport
;
184 result
->real_address
= (uint32_t) ntohl(addr
.s_addr
);
188 /** Set up rend_service_list, based on the values of HiddenServiceDir and
189 * HiddenServicePort in <b>options</b>. Return 0 on success and -1 on
192 int rend_config_services(or_options_t
*options
)
194 struct config_line_t
*line
;
195 rend_service_t
*service
= NULL
;
196 rend_service_port_config_t
*portcfg
;
197 rend_service_free_all();
199 for (line
= options
->RendConfigLines
; line
; line
= line
->next
) {
200 if (!strcasecmp(line
->key
, "HiddenServiceDir")) {
202 add_service(service
);
203 service
= tor_malloc_zero(sizeof(rend_service_t
));
204 service
->directory
= tor_strdup(line
->value
);
205 service
->ports
= smartlist_create();
206 service
->intro_nodes
= smartlist_create();
207 service
->intro_period_started
= time(NULL
);
211 log_fn(LOG_WARN
, "HiddenServicePort with no preceeding HiddenServiceDir directive");
212 rend_service_free(service
);
215 if (!strcasecmp(line
->key
, "HiddenServicePort")) {
216 portcfg
= parse_port_config(line
->value
);
218 rend_service_free(service
);
221 smartlist_add(service
->ports
, portcfg
);
222 } else if (!strcasecmp(line
->key
, "HiddenServiceNodes")) {
223 if (service
->intro_prefer_nodes
) {
224 log_fn(LOG_WARN
, "Got multiple HiddenServiceNodes lines for a single service");
227 service
->intro_prefer_nodes
= tor_strdup(line
->value
);
229 tor_assert(!strcasecmp(line
->key
, "HiddenServiceExcludeNodes"));
230 if (service
->intro_exclude_nodes
) {
231 log_fn(LOG_WARN
, "Got multiple HiddenServiceExcludedNodes lines for a single service");
234 service
->intro_exclude_nodes
= tor_strdup(line
->value
);
238 add_service(service
);
243 /** Replace the old value of <b>service</b>-\>desc with one that reflects
244 * the other fields in service.
246 static void rend_service_update_descriptor(rend_service_t
*service
)
248 rend_service_descriptor_t
*d
;
251 routerinfo_t
*router
;
254 rend_service_descriptor_free(service
->desc
);
255 service
->desc
= NULL
;
257 d
= service
->desc
= tor_malloc(sizeof(rend_service_descriptor_t
));
258 d
->pk
= crypto_pk_dup_key(service
->private_key
);
259 d
->timestamp
= time(NULL
);
260 n
= smartlist_len(service
->intro_nodes
);
261 d
->n_intro_points
= 0;
262 d
->intro_points
= tor_malloc(sizeof(char*)*n
);
263 for (i
=0; i
< n
; ++i
) {
264 router
= router_get_by_nickname(smartlist_get(service
->intro_nodes
, i
));
265 circ
= find_intro_circuit(router
, service
->pk_digest
);
266 if (circ
&& circ
->purpose
== CIRCUIT_PURPOSE_S_INTRO
) {
267 /* We have an entirely established intro circuit. */
268 d
->intro_points
[d
->n_intro_points
++] = tor_strdup(router
->nickname
);
273 /** Load and/or generate private keys for all hidden services. Return 0 on
274 * success, -1 on failure.
276 int rend_service_load_keys(void)
283 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
284 s
= smartlist_get(rend_service_list
,i
);
287 log_fn(LOG_INFO
, "Loading hidden-service keys from '%s'", s
->directory
);
289 /* Check/create directory */
290 if (check_private_dir(s
->directory
, 1) < 0)
294 if (strlcpy(fname
,s
->directory
,sizeof(fname
)) >= sizeof(fname
) ||
295 strlcat(fname
,"/private_key",sizeof(fname
)) >= sizeof(fname
)) {
296 log_fn(LOG_WARN
, "Directory name too long: '%s'", s
->directory
);
299 s
->private_key
= init_key_from_file(fname
);
303 /* Create service file */
304 if (rend_get_service_id(s
->private_key
, s
->service_id
)<0) {
305 log_fn(LOG_WARN
, "Couldn't encode service ID");
308 if (crypto_pk_get_digest(s
->private_key
, s
->pk_digest
)<0) {
309 log_fn(LOG_WARN
, "Couldn't compute hash of public key");
312 if (strlcpy(fname
,s
->directory
,sizeof(fname
)) >= sizeof(fname
) ||
313 strlcat(fname
,"/hostname",sizeof(fname
)) >= sizeof(fname
)) {
314 log_fn(LOG_WARN
, "Directory name too long: '%s'", s
->directory
);
317 sprintf(buf
, "%s.onion\n", s
->service_id
);
318 if (write_str_to_file(fname
,buf
)<0)
324 /** Return the service whose public key has a digest of <b>digest</b>. Return
325 * NULL if no such service exists.
327 static rend_service_t
*
328 rend_service_get_by_pk_digest(const char* digest
)
330 SMARTLIST_FOREACH(rend_service_list
, rend_service_t
*, s
,
331 if (!memcmp(s
->pk_digest
,digest
,DIGEST_LEN
)) return s
);
339 /** Respond to an INTRODUCE2 cell by launching a circuit to the chosen
343 rend_service_introduce(circuit_t
*circuit
, const char *request
, int request_len
)
345 char *ptr
, *rp_nickname
, *r_cookie
;
346 char buf
[RELAY_PAYLOAD_SIZE
];
347 char keys
[DIGEST_LEN
+CPATH_KEY_MATERIAL_LEN
]; /* Holds KH, Df, Db, Kf, Kb */
348 rend_service_t
*service
;
350 crypto_dh_env_t
*dh
= NULL
;
351 circuit_t
*launched
= NULL
;
352 crypt_path_t
*cpath
= NULL
;
353 char serviceid
[REND_SERVICE_ID_LEN
+1];
356 if (base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
357 circuit
->rend_pk_digest
,10)) {
360 log_fn(LOG_INFO
, "Received INTRODUCE2 cell for service %s on circ %d",
361 serviceid
, circuit
->n_circ_id
);
363 if (circuit
->purpose
!= CIRCUIT_PURPOSE_S_INTRO
) {
364 log_fn(LOG_WARN
, "Got an INTRODUCE2 over a non-introduction circuit %d",
369 /* min key length plus digest length plus nickname length */
370 if (request_len
< DIGEST_LEN
+REND_COOKIE_LEN
+(MAX_NICKNAME_LEN
+1)+
372 log_fn(LOG_WARN
, "Got a truncated INTRODUCE2 cell on circ %d",
377 /* first DIGEST_LEN bytes of request is service pk digest */
378 service
= rend_service_get_by_pk_digest(request
);
380 log_fn(LOG_WARN
, "Got an INTRODUCE2 cell for an unrecognized service %s",
384 if (memcmp(circuit
->rend_pk_digest
, request
, DIGEST_LEN
)) {
385 if (base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1, request
, 10)) {
388 log_fn(LOG_WARN
, "Got an INTRODUCE2 cell for the wrong service (%s)",
393 keylen
= crypto_pk_keysize(service
->private_key
);
394 if (request_len
< keylen
+DIGEST_LEN
) {
395 log_fn(LOG_WARN
, "PK-encrypted portion of INTRODUCE2 cell was truncated");
398 /* Next N bytes is encrypted with service key */
399 len
= crypto_pk_private_hybrid_decrypt(
400 service
->private_key
,request
+DIGEST_LEN
,request_len
-DIGEST_LEN
,buf
,
401 PK_PKCS1_OAEP_PADDING
,1);
403 log_fn(LOG_WARN
, "Couldn't decrypt INTRODUCE2 cell");
406 ptr
=memchr(buf
,0,MAX_NICKNAME_LEN
+1);
407 if (!ptr
|| ptr
== buf
) {
408 log_fn(LOG_WARN
, "Couldn't find a null-padded nickname in INTRODUCE2 cell");
411 if ((int)strspn(buf
,LEGAL_NICKNAME_CHARACTERS
) != ptr
-buf
) {
412 log_fn(LOG_WARN
, "Nickname in INTRODUCE2 cell contains illegal character.");
415 /* Okay, now we know that the nickname is at the start of the buffer. */
417 ptr
= buf
+(MAX_NICKNAME_LEN
+1);
418 len
-= (MAX_NICKNAME_LEN
+1);
419 if (len
!= REND_COOKIE_LEN
+DH_KEY_LEN
) {
420 log_fn(LOG_WARN
, "Bad length for INTRODUCE2 cell.");
424 hex_encode(r_cookie
,4,hexcookie
);
426 /* Try DH handshake... */
427 dh
= crypto_dh_new();
428 if (!dh
|| crypto_dh_generate_public(dh
)<0) {
429 log_fn(LOG_WARN
, "Couldn't build DH state or generate public key");
432 if (crypto_dh_compute_secret(dh
, ptr
+REND_COOKIE_LEN
, DH_KEY_LEN
, keys
,
433 DIGEST_LEN
+CPATH_KEY_MATERIAL_LEN
)<0) {
434 log_fn(LOG_WARN
, "Couldn't complete DH handshake");
438 /* Launch a circuit to alice's chosen rendezvous point.
440 launched
= circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND
, rp_nickname
);
442 "Accepted intro; launching circuit to '%s' (cookie %s) for service %s",
443 rp_nickname
, hexcookie
, serviceid
);
446 "Can't launch circuit to rendezvous point '%s' for service %s",
447 rp_nickname
, serviceid
);
450 tor_assert(launched
->build_state
);
451 /* Fill in the circuit's state. */
452 memcpy(launched
->rend_pk_digest
, circuit
->rend_pk_digest
,
454 memcpy(launched
->rend_cookie
, r_cookie
, REND_COOKIE_LEN
);
455 strcpy(launched
->rend_query
, service
->service_id
);
456 launched
->build_state
->pending_final_cpath
= cpath
=
457 tor_malloc_zero(sizeof(crypt_path_t
));
459 cpath
->handshake_state
= dh
;
461 if (circuit_init_cpath_crypto(cpath
,keys
+DIGEST_LEN
,1)<0)
463 memcpy(cpath
->handshake_digest
, keys
, DIGEST_LEN
);
467 if (dh
) crypto_dh_free(dh
);
468 if (launched
) circuit_mark_for_close(launched
);
472 /** How many times will a hidden service operator attempt to connect to
473 * a requested rendezvous point before giving up? */
474 #define MAX_REND_FAILURES 3
476 /** Called when we fail building a rendezvous circuit at some point other
477 * than the last hop: launches a new circuit to the same rendezvous point.
480 rend_service_relaunch_rendezvous(circuit_t
*oldcirc
)
483 cpath_build_state_t
*newstate
, *oldstate
;
485 tor_assert(oldcirc
->purpose
== CIRCUIT_PURPOSE_S_CONNECT_REND
);
487 if (!oldcirc
->build_state
||
488 oldcirc
->build_state
->failure_count
> MAX_REND_FAILURES
) {
489 log_fn(LOG_INFO
,"Attempt to build circuit to %s for rendezvous has failed too many times; giving up.",
490 oldcirc
->build_state
->chosen_exit
);
494 log_fn(LOG_INFO
,"Reattempting rendezvous circuit to %s",
495 oldcirc
->build_state
->chosen_exit
);
497 newcirc
= circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND
,
498 oldcirc
->build_state
->chosen_exit
);
500 log_fn(LOG_WARN
,"Couldn't relaunch rendezvous circuit to %s",
501 oldcirc
->build_state
->chosen_exit
);
504 oldstate
= oldcirc
->build_state
;
505 newstate
= newcirc
->build_state
;
506 tor_assert(newstate
&& oldstate
);
507 newstate
->failure_count
= oldstate
->failure_count
+1;
508 newstate
->pending_final_cpath
= oldstate
->pending_final_cpath
;
509 oldstate
->pending_final_cpath
= NULL
;
511 memcpy(newcirc
->rend_query
, oldcirc
->rend_query
, REND_SERVICE_ID_LEN
+1);
512 memcpy(newcirc
->rend_pk_digest
, oldcirc
->rend_pk_digest
, DIGEST_LEN
);
513 memcpy(newcirc
->rend_cookie
, oldcirc
->rend_cookie
, REND_COOKIE_LEN
);
516 /** Launch a circuit to serve as an introduction point for the service
517 * <b>service</b> at the introduction point <b>nickname</b>
520 rend_service_launch_establish_intro(rend_service_t
*service
, const char *nickname
)
524 log_fn(LOG_INFO
, "Launching circuit to introduction point %s for service %s",
525 nickname
, service
->service_id
);
527 ++service
->n_intro_circuits_launched
;
528 launched
= circuit_launch_new(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
, nickname
);
530 log_fn(LOG_WARN
, "Can't launch circuit to establish introduction at '%s'",
534 strcpy(launched
->rend_query
, service
->service_id
);
535 memcpy(launched
->rend_pk_digest
, service
->pk_digest
, DIGEST_LEN
);
540 /** Called when we're done building a circuit to an introduction point:
541 * sends a RELAY_ESTABLISH_INTRO cell.
544 rend_service_intro_has_opened(circuit_t
*circuit
)
546 rend_service_t
*service
;
548 char buf
[RELAY_PAYLOAD_SIZE
];
549 char auth
[DIGEST_LEN
+ 9];
550 char serviceid
[REND_SERVICE_ID_LEN
+1];
552 tor_assert(circuit
->purpose
== CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
);
553 tor_assert(CIRCUIT_IS_ORIGIN(circuit
) && circuit
->cpath
);
555 if (base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
556 circuit
->rend_pk_digest
,10)) {
560 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
562 log_fn(LOG_WARN
, "Unrecognized service ID %s on introduction circuit %d",
563 serviceid
, circuit
->n_circ_id
);
568 "Established circuit %d as introduction point for service %s",
569 circuit
->n_circ_id
, serviceid
);
571 /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
572 len
= crypto_pk_asn1_encode(service
->private_key
, buf
+2,
573 RELAY_PAYLOAD_SIZE
-2);
574 set_uint16(buf
, htons((uint16_t)len
));
576 memcpy(auth
, circuit
->cpath
->prev
->handshake_digest
, DIGEST_LEN
);
577 memcpy(auth
+DIGEST_LEN
, "INTRODUCE", 9);
578 if (crypto_digest(auth
, DIGEST_LEN
+9, buf
+len
))
581 r
= crypto_pk_private_sign_digest(service
->private_key
, buf
, len
, buf
+len
);
583 log_fn(LOG_WARN
, "Couldn't sign introduction request");
588 if (connection_edge_send_command(NULL
, circuit
,RELAY_COMMAND_ESTABLISH_INTRO
,
589 buf
, len
, circuit
->cpath
->prev
)<0) {
591 "Couldn't send introduction request for service %s on circuit %d",
592 serviceid
, circuit
->n_circ_id
);
598 circuit_mark_for_close(circuit
);
601 /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
602 * live introduction point, and note that the service descriptor is
605 rend_service_intro_established(circuit_t
*circuit
, const char *request
, int request_len
)
607 rend_service_t
*service
;
609 if (circuit
->purpose
!= CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
) {
610 log_fn(LOG_WARN
, "received INTRO_ESTABLISHED cell on non-intro circuit");
613 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
615 log_fn(LOG_WARN
, "Unknown service on introduction circuit %d",
619 service
->desc_is_dirty
= 1;
620 circuit
->purpose
= CIRCUIT_PURPOSE_S_INTRO
;
624 circuit_mark_for_close(circuit
);
628 /** Called once a circuit to a rendezvous point is established: sends a
629 * RELAY_COMMAND_RENDEZVOUS1 cell.
632 rend_service_rendezvous_has_opened(circuit_t
*circuit
)
634 rend_service_t
*service
;
635 char buf
[RELAY_PAYLOAD_SIZE
];
637 char serviceid
[REND_SERVICE_ID_LEN
+1];
640 tor_assert(circuit
->purpose
== CIRCUIT_PURPOSE_S_CONNECT_REND
);
641 tor_assert(circuit
->cpath
);
642 tor_assert(circuit
->build_state
);
643 hop
= circuit
->build_state
->pending_final_cpath
;
646 hex_encode(circuit
->rend_cookie
, 4, hexcookie
);
647 if (base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
648 circuit
->rend_pk_digest
,10)) {
653 "Done building circuit %d to rendezvous with cookie %s for service %s",
654 circuit
->n_circ_id
, hexcookie
, serviceid
);
656 service
= rend_service_get_by_pk_digest(circuit
->rend_pk_digest
);
658 log_fn(LOG_WARN
, "Internal error: unrecognized service ID on introduction circuit");
662 /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
663 memcpy(buf
, circuit
->rend_cookie
, REND_COOKIE_LEN
);
664 if (crypto_dh_get_public(hop
->handshake_state
,
665 buf
+REND_COOKIE_LEN
, DH_KEY_LEN
)<0) {
666 log_fn(LOG_WARN
,"Couldn't get DH public key");
669 memcpy(buf
+REND_COOKIE_LEN
+DH_KEY_LEN
, hop
->handshake_digest
,
673 if (connection_edge_send_command(NULL
, circuit
, RELAY_COMMAND_RENDEZVOUS1
,
674 buf
, REND_COOKIE_LEN
+DH_KEY_LEN
+DIGEST_LEN
,
675 circuit
->cpath
->prev
)<0) {
676 log_fn(LOG_WARN
, "Couldn't send RENDEZVOUS1 cell");
680 crypto_dh_free(hop
->handshake_state
);
681 hop
->handshake_state
= NULL
;
683 /* Append the cpath entry. */
684 hop
->state
= CPATH_STATE_OPEN
;
685 /* set the windows to default. these are the windows
686 * that bob thinks alice has.
688 hop
->package_window
= CIRCWINDOW_START
;
689 hop
->deliver_window
= CIRCWINDOW_START
;
691 onion_append_to_cpath(&circuit
->cpath
, hop
);
692 circuit
->build_state
->pending_final_cpath
= NULL
; /* prevent double-free */
694 /* Change the circuit purpose. */
695 circuit
->purpose
= CIRCUIT_PURPOSE_S_REND_JOINED
;
699 circuit_mark_for_close(circuit
);
703 * Manage introduction points
706 /** Return the (possibly non-open) introduction circuit ending at
707 * <b>router</b> for the service whose public key is <b>pk_digest</b>. Return
708 * NULL if no such service is found.
711 find_intro_circuit(routerinfo_t
*router
, const char *pk_digest
)
713 circuit_t
*circ
= NULL
;
715 while ((circ
= circuit_get_next_by_pk_and_purpose(circ
,pk_digest
,
716 CIRCUIT_PURPOSE_S_INTRO
))) {
717 tor_assert(circ
->cpath
);
718 if (circ
->build_state
->chosen_exit
&&
719 !strcasecmp(circ
->build_state
->chosen_exit
, router
->nickname
)) {
725 while ((circ
= circuit_get_next_by_pk_and_purpose(circ
,pk_digest
,
726 CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
))) {
727 tor_assert(circ
->cpath
);
728 if (circ
->build_state
->chosen_exit
&&
729 !strcasecmp(circ
->build_state
->chosen_exit
, router
->nickname
)) {
736 /** If the directory servers don't have an up-to-date descriptor for
737 * <b>service</b>, encode and sign the service descriptor for <b>service</b>,
738 * and upload it to all the dirservers.
741 upload_service_descriptor(rend_service_t
*service
)
745 if (!service
->desc_is_dirty
)
748 /* Update the descriptor. */
749 rend_service_update_descriptor(service
);
750 if (rend_encode_service_descriptor(service
->desc
,
751 service
->private_key
,
752 &desc
, &desc_len
)<0) {
753 log_fn(LOG_WARN
, "Couldn't encode service descriptor; not uploading");
757 /* Post it to the dirservers */
758 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC
, desc
, desc_len
);
761 service
->desc_is_dirty
= 0;
764 /* XXXX Make this longer once directories remember service descriptors across
766 #define MAX_SERVICE_PUBLICATION_INTERVAL (15*60)
768 /** For every service, check how many intro points it currently has, and:
769 * - Pick new intro points as necessary.
770 * - Launch circuits to any new intro points.
772 void rend_services_introduce(void) {
774 routerinfo_t
*router
;
775 rend_service_t
*service
;
777 int changed
, prev_intro_nodes
;
778 smartlist_t
*intro_routers
, *exclude_routers
;
781 intro_routers
= smartlist_create();
782 exclude_routers
= smartlist_create();
785 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
786 smartlist_clear(intro_routers
);
787 service
= smartlist_get(rend_service_list
, i
);
791 if (now
> service
->intro_period_started
+INTRO_CIRC_RETRY_PERIOD
) {
792 /* One period has elapsed; we can try building circuits again. */
793 service
->intro_period_started
= now
;
794 service
->n_intro_circuits_launched
= 0;
795 } else if (service
->n_intro_circuits_launched
>=MAX_INTRO_CIRCS_PER_PERIOD
){
796 /* We have failed too many times in this period; wait for the next
797 * one before we try again. */
801 /* Find out which introduction points we have in progress for this service. */
802 for (j
=0;j
< smartlist_len(service
->intro_nodes
); ++j
) {
803 intro
= smartlist_get(service
->intro_nodes
, j
);
804 router
= router_get_by_nickname(intro
);
805 if (!router
|| !find_intro_circuit(router
,service
->pk_digest
)) {
806 log_fn(LOG_INFO
,"Giving up on %s as intro point for %s.",
807 intro
, service
->service_id
);
808 smartlist_del(service
->intro_nodes
,j
--);
809 changed
= service
->desc_is_dirty
= 1;
811 smartlist_add(intro_routers
, router
);
814 /* We have enough intro points, and the intro points we thought we had were
817 if (!changed
&& smartlist_len(service
->intro_nodes
) >= NUM_INTRO_POINTS
) {
818 /* We have all our intro points! Start a fresh period and reset the
820 service
->intro_period_started
= now
;
821 service
->n_intro_circuits_launched
= 0;
825 /* Remember how many introduction circuits we started with. */
826 prev_intro_nodes
= smartlist_len(service
->intro_nodes
);
828 smartlist_add_all(exclude_routers
, intro_routers
);
829 /* The directory is now here. Pick three ORs as intro points. */
830 for (j
=prev_intro_nodes
; j
< NUM_INTRO_POINTS
; ++j
) {
831 router
= router_choose_random_node(service
->intro_prefer_nodes
,
832 service
->intro_exclude_nodes
,
835 log_fn(LOG_WARN
, "Could only establish %d introduction points for %s",
836 smartlist_len(service
->intro_nodes
), service
->service_id
);
840 smartlist_add(intro_routers
, router
);
841 smartlist_add(exclude_routers
, router
);
842 smartlist_add(service
->intro_nodes
, tor_strdup(router
->nickname
));
843 log_fn(LOG_INFO
,"Picked router %s as an intro point for %s.", router
->nickname
,
844 service
->service_id
);
847 /* Reset exclude_routers, for the next time around the loop. */
848 smartlist_clear(exclude_routers
);
850 /* If there's no need to launch new circuits, stop here. */
854 /* Establish new introduction points. */
855 for (j
=prev_intro_nodes
; j
< smartlist_len(service
->intro_nodes
); ++j
) {
856 intro
= smartlist_get(service
->intro_nodes
, j
);
857 r
= rend_service_launch_establish_intro(service
, intro
);
859 log_fn(LOG_WARN
, "Error launching circuit to node %s for service %s",
860 intro
, service
->service_id
);
864 smartlist_free(intro_routers
);
865 smartlist_free(exclude_routers
);
868 /** Regenerate and upload rendezvous service descriptors for all
869 * services. If <b>force</b> is false, skip services where we've already
870 * uploaded an up-to-date copy; if <b>force</b> is true, regenerate and
874 rend_services_upload(int force
)
877 rend_service_t
*service
;
879 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
880 service
= smartlist_get(rend_service_list
, i
);
882 service
->desc_is_dirty
= 1;
883 if (service
->desc_is_dirty
)
884 upload_service_descriptor(service
);
888 /** Log the status of introduction points for all rendezvous services
889 * at log severity <b>serverity</b>.
892 rend_service_dump_stats(int severity
)
895 routerinfo_t
*router
;
896 rend_service_t
*service
;
900 for (i
=0; i
< smartlist_len(rend_service_list
); ++i
) {
901 service
= smartlist_get(rend_service_list
, i
);
902 log(severity
, "Service configured in %s:", service
->directory
);
903 for (j
=0; j
< smartlist_len(service
->intro_nodes
); ++j
) {
904 nickname
= smartlist_get(service
->intro_nodes
, j
);
905 router
= router_get_by_nickname(smartlist_get(service
->intro_nodes
,j
));
907 log(severity
, " Intro point at %s: unrecognized router",nickname
);
910 circ
= find_intro_circuit(router
, service
->pk_digest
);
912 log(severity
, " Intro point at %s: no circuit",nickname
);
915 log(severity
, " Intro point at %s: circuit is %s",nickname
,
916 circuit_state_to_string
[circ
->state
]);
921 /** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
922 * 'circ', and look up the port and address based on conn-\>port.
923 * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
927 rend_service_set_connection_addr_port(connection_t
*conn
, circuit_t
*circ
)
929 rend_service_t
*service
;
931 rend_service_port_config_t
*p
;
932 char serviceid
[REND_SERVICE_ID_LEN
+1];
934 tor_assert(circ
->purpose
== CIRCUIT_PURPOSE_S_REND_JOINED
);
935 log_fn(LOG_DEBUG
,"beginning to hunt for addr/port");
936 if (base32_encode(serviceid
, REND_SERVICE_ID_LEN
+1,
937 circ
->rend_pk_digest
,10)) {
938 log_fn(LOG_WARN
,"bug: base32 failed");
941 service
= rend_service_get_by_pk_digest(circ
->rend_pk_digest
);
943 log_fn(LOG_WARN
, "Couldn't find any service associated with pk %s on rendezvous circuit %d; closing",
944 serviceid
, circ
->n_circ_id
);
947 for (i
= 0; i
< smartlist_len(service
->ports
); ++i
) {
948 p
= smartlist_get(service
->ports
, i
);
949 if (conn
->port
== p
->virtual_port
) {
950 conn
->addr
= p
->real_address
;
951 conn
->port
= p
->real_port
;
955 log_fn(LOG_INFO
, "No virtual port mapping exists for port %d on service %s",
956 conn
->port
,serviceid
);