Back to index

tor  0.2.3.18-rc
rendservice.c
Go to the documentation of this file.
00001 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00002  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00003 /* See LICENSE for licensing information */
00004 
00010 #include "or.h"
00011 #include "circuitbuild.h"
00012 #include "circuitlist.h"
00013 #include "circuituse.h"
00014 #include "config.h"
00015 #include "directory.h"
00016 #include "networkstatus.h"
00017 #include "nodelist.h"
00018 #include "rendclient.h"
00019 #include "rendcommon.h"
00020 #include "rendservice.h"
00021 #include "router.h"
00022 #include "relay.h"
00023 #include "rephist.h"
00024 #include "routerlist.h"
00025 #include "routerparse.h"
00026 
00027 static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro,
00028                                             const char *pk_digest);
00029 static rend_intro_point_t *find_intro_point(origin_circuit_t *circ);
00030 
00031 static int intro_point_accepted_intro_count(rend_intro_point_t *intro);
00032 static int intro_point_should_expire_now(rend_intro_point_t *intro,
00033                                          time_t now);
00034 
00038 typedef struct rend_service_port_config_t {
00039   uint16_t virtual_port;
00040   uint16_t real_port;
00041   tor_addr_t real_addr;
00042 } rend_service_port_config_t;
00043 
00045 #define NUM_INTRO_POINTS_DEFAULT 3
00046 
00047 #define NUM_INTRO_POINTS_MAX 10
00048 
00050 #define INTRO_CIRC_RETRY_PERIOD (60*5)
00051 
00053 #define MAX_INTRO_CIRCS_PER_PERIOD 10
00054 
00056 #define MAX_REND_FAILURES 30
00057 
00059 #define MAX_REND_TIMEOUT 30
00060 
00063 #define INTRO_POINT_EXPIRATION_GRACE_PERIOD 5*60
00064 
00066 typedef struct rend_service_t {
00067   /* Fields specified in config file */
00068   char *directory; 
00069   smartlist_t *ports; 
00070   rend_auth_type_t auth_type; 
00072   smartlist_t *clients; 
00075   /* Other fields */
00076   crypto_pk_t *private_key; 
00077   char service_id[REND_SERVICE_ID_LEN_BASE32+1]; 
00079   char pk_digest[DIGEST_LEN]; 
00080   smartlist_t *intro_nodes; 
00082   time_t intro_period_started; 
00084   int n_intro_circuits_launched; 
00086   unsigned int n_intro_points_wanted; 
00088   rend_service_descriptor_t *desc; 
00089   time_t desc_is_dirty; 
00092   time_t next_upload_time; 
00100   digestmap_t *accepted_intro_dh_parts;
00103   time_t last_cleaned_accepted_intro_dh_parts;
00104 } rend_service_t;
00105 
00108 static smartlist_t *rend_service_list = NULL;
00109 
00111 int
00112 num_rend_services(void)
00113 {
00114   if (!rend_service_list)
00115     return 0;
00116   return smartlist_len(rend_service_list);
00117 }
00118 
00122 static const char *
00123 rend_service_describe_for_log(rend_service_t *service)
00124 {
00125   /* XXX024 Use this function throughout rendservice.c. */
00126   /* XXX024 Return a more useful description? */
00127   return safe_str_client(service->service_id);
00128 }
00129 
00131 static void
00132 rend_authorized_client_free(rend_authorized_client_t *client)
00133 {
00134   if (!client)
00135     return;
00136   if (client->client_key)
00137     crypto_pk_free(client->client_key);
00138   tor_free(client->client_name);
00139   tor_free(client);
00140 }
00141 
00143 static void
00144 rend_authorized_client_strmap_item_free(void *authorized_client)
00145 {
00146   rend_authorized_client_free(authorized_client);
00147 }
00148 
00151 static void
00152 rend_service_free(rend_service_t *service)
00153 {
00154   if (!service)
00155     return;
00156 
00157   tor_free(service->directory);
00158   SMARTLIST_FOREACH(service->ports, void*, p, tor_free(p));
00159   smartlist_free(service->ports);
00160   if (service->private_key)
00161     crypto_pk_free(service->private_key);
00162   if (service->intro_nodes) {
00163     SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro,
00164       rend_intro_point_free(intro););
00165     smartlist_free(service->intro_nodes);
00166   }
00167 
00168   rend_service_descriptor_free(service->desc);
00169   if (service->clients) {
00170     SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, c,
00171       rend_authorized_client_free(c););
00172     smartlist_free(service->clients);
00173   }
00174   digestmap_free(service->accepted_intro_dh_parts, _tor_free);
00175   tor_free(service);
00176 }
00177 
00180 void
00181 rend_service_free_all(void)
00182 {
00183   if (!rend_service_list)
00184     return;
00185 
00186   SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
00187                     rend_service_free(ptr));
00188   smartlist_free(rend_service_list);
00189   rend_service_list = NULL;
00190 }
00191 
00194 static void
00195 rend_add_service(rend_service_t *service)
00196 {
00197   int i;
00198   rend_service_port_config_t *p;
00199 
00200   service->intro_nodes = smartlist_new();
00201 
00202   if (service->auth_type != REND_NO_AUTH &&
00203       smartlist_len(service->clients) == 0) {
00204     log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no "
00205                         "clients; ignoring.",
00206              escaped(service->directory));
00207     rend_service_free(service);
00208     return;
00209   }
00210 
00211   if (!smartlist_len(service->ports)) {
00212     log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured; "
00213              "ignoring.",
00214              escaped(service->directory));
00215     rend_service_free(service);
00216   } else {
00217     int dupe = 0;
00218     /* XXX This duplicate check has two problems:
00219      *
00220      * a) It's O(n^2), but the same comment from the bottom of
00221      *    rend_config_services() should apply.
00222      *
00223      * b) We only compare directory paths as strings, so we can't
00224      *    detect two distinct paths that specify the same directory
00225      *    (which can arise from symlinks, case-insensitivity, bind
00226      *    mounts, etc.).
00227      *
00228      * It also can't detect that two separate Tor instances are trying
00229      * to use the same HiddenServiceDir; for that, we would need a
00230      * lock file.  But this is enough to detect a simple mistake that
00231      * at least one person has actually made.
00232      */
00233     SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
00234                       dupe = dupe ||
00235                              !strcmp(ptr->directory, service->directory));
00236     if (dupe) {
00237       log_warn(LD_REND, "Another hidden service is already configured for "
00238                "directory %s, ignoring.", service->directory);
00239       rend_service_free(service);
00240       return;
00241     }
00242     smartlist_add(rend_service_list, service);
00243     log_debug(LD_REND,"Configuring service with directory \"%s\"",
00244               service->directory);
00245     for (i = 0; i < smartlist_len(service->ports); ++i) {
00246       p = smartlist_get(service->ports, i);
00247       log_debug(LD_REND,"Service maps port %d to %s:%d",
00248                 p->virtual_port, fmt_addr(&p->real_addr), p->real_port);
00249     }
00250   }
00251 }
00252 
00260 static rend_service_port_config_t *
00261 parse_port_config(const char *string)
00262 {
00263   smartlist_t *sl;
00264   int virtport;
00265   int realport;
00266   uint16_t p;
00267   tor_addr_t addr;
00268   const char *addrport;
00269   rend_service_port_config_t *result = NULL;
00270 
00271   sl = smartlist_new();
00272   smartlist_split_string(sl, string, " ",
00273                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
00274   if (smartlist_len(sl) < 1 || smartlist_len(sl) > 2) {
00275     log_warn(LD_CONFIG, "Bad syntax in hidden service port configuration.");
00276     goto err;
00277   }
00278 
00279   virtport = (int)tor_parse_long(smartlist_get(sl,0), 10, 1, 65535, NULL,NULL);
00280   if (!virtport) {
00281     log_warn(LD_CONFIG, "Missing or invalid port %s in hidden service port "
00282              "configuration", escaped(smartlist_get(sl,0)));
00283     goto err;
00284   }
00285 
00286   if (smartlist_len(sl) == 1) {
00287     /* No addr:port part; use default. */
00288     realport = virtport;
00289     tor_addr_from_ipv4h(&addr, 0x7F000001u); /* 127.0.0.1 */
00290   } else {
00291     addrport = smartlist_get(sl,1);
00292     if (strchr(addrport, ':') || strchr(addrport, '.')) {
00293       if (tor_addr_port_lookup(addrport, &addr, &p)<0) {
00294         log_warn(LD_CONFIG,"Unparseable address in hidden service port "
00295                  "configuration.");
00296         goto err;
00297       }
00298       realport = p?p:virtport;
00299     } else {
00300       /* No addr:port, no addr -- must be port. */
00301       realport = (int)tor_parse_long(addrport, 10, 1, 65535, NULL, NULL);
00302       if (!realport) {
00303         log_warn(LD_CONFIG,"Unparseable or out-of-range port %s in hidden "
00304                  "service port configuration.", escaped(addrport));
00305         goto err;
00306       }
00307       tor_addr_from_ipv4h(&addr, 0x7F000001u); /* Default to 127.0.0.1 */
00308     }
00309   }
00310 
00311   result = tor_malloc(sizeof(rend_service_port_config_t));
00312   result->virtual_port = virtport;
00313   result->real_port = realport;
00314   tor_addr_copy(&result->real_addr, &addr);
00315  err:
00316   SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
00317   smartlist_free(sl);
00318   return result;
00319 }
00320 
00326 int
00327 rend_config_services(const or_options_t *options, int validate_only)
00328 {
00329   config_line_t *line;
00330   rend_service_t *service = NULL;
00331   rend_service_port_config_t *portcfg;
00332   smartlist_t *old_service_list = NULL;
00333 
00334   if (!validate_only) {
00335     old_service_list = rend_service_list;
00336     rend_service_list = smartlist_new();
00337   }
00338 
00339   for (line = options->RendConfigLines; line; line = line->next) {
00340     if (!strcasecmp(line->key, "HiddenServiceDir")) {
00341       if (service) { /* register the one we just finished parsing */
00342         if (validate_only)
00343           rend_service_free(service);
00344         else
00345           rend_add_service(service);
00346       }
00347       service = tor_malloc_zero(sizeof(rend_service_t));
00348       service->directory = tor_strdup(line->value);
00349       service->ports = smartlist_new();
00350       service->intro_period_started = time(NULL);
00351       service->n_intro_points_wanted = NUM_INTRO_POINTS_DEFAULT;
00352       continue;
00353     }
00354     if (!service) {
00355       log_warn(LD_CONFIG, "%s with no preceding HiddenServiceDir directive",
00356                line->key);
00357       rend_service_free(service);
00358       return -1;
00359     }
00360     if (!strcasecmp(line->key, "HiddenServicePort")) {
00361       portcfg = parse_port_config(line->value);
00362       if (!portcfg) {
00363         rend_service_free(service);
00364         return -1;
00365       }
00366       smartlist_add(service->ports, portcfg);
00367     } else if (!strcasecmp(line->key, "HiddenServiceAuthorizeClient")) {
00368       /* Parse auth type and comma-separated list of client names and add a
00369        * rend_authorized_client_t for each client to the service's list
00370        * of authorized clients. */
00371       smartlist_t *type_names_split, *clients;
00372       const char *authname;
00373       int num_clients;
00374       if (service->auth_type != REND_NO_AUTH) {
00375         log_warn(LD_CONFIG, "Got multiple HiddenServiceAuthorizeClient "
00376                  "lines for a single service.");
00377         rend_service_free(service);
00378         return -1;
00379       }
00380       type_names_split = smartlist_new();
00381       smartlist_split_string(type_names_split, line->value, " ", 0, 2);
00382       if (smartlist_len(type_names_split) < 1) {
00383         log_warn(LD_BUG, "HiddenServiceAuthorizeClient has no value. This "
00384                          "should have been prevented when parsing the "
00385                          "configuration.");
00386         smartlist_free(type_names_split);
00387         rend_service_free(service);
00388         return -1;
00389       }
00390       authname = smartlist_get(type_names_split, 0);
00391       if (!strcasecmp(authname, "basic")) {
00392         service->auth_type = REND_BASIC_AUTH;
00393       } else if (!strcasecmp(authname, "stealth")) {
00394         service->auth_type = REND_STEALTH_AUTH;
00395       } else {
00396         log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
00397                  "unrecognized auth-type '%s'. Only 'basic' or 'stealth' "
00398                  "are recognized.",
00399                  (char *) smartlist_get(type_names_split, 0));
00400         SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
00401         smartlist_free(type_names_split);
00402         rend_service_free(service);
00403         return -1;
00404       }
00405       service->clients = smartlist_new();
00406       if (smartlist_len(type_names_split) < 2) {
00407         log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains "
00408                             "auth-type '%s', but no client names.",
00409                  service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth");
00410         SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
00411         smartlist_free(type_names_split);
00412         continue;
00413       }
00414       clients = smartlist_new();
00415       smartlist_split_string(clients, smartlist_get(type_names_split, 1),
00416                              ",", SPLIT_SKIP_SPACE, 0);
00417       SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp));
00418       smartlist_free(type_names_split);
00419       /* Remove duplicate client names. */
00420       num_clients = smartlist_len(clients);
00421       smartlist_sort_strings(clients);
00422       smartlist_uniq_strings(clients);
00423       if (smartlist_len(clients) < num_clients) {
00424         log_info(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
00425                             "duplicate client name(s); removing.",
00426                  num_clients - smartlist_len(clients));
00427         num_clients = smartlist_len(clients);
00428       }
00429       SMARTLIST_FOREACH_BEGIN(clients, const char *, client_name)
00430       {
00431         rend_authorized_client_t *client;
00432         size_t len = strlen(client_name);
00433         if (len < 1 || len > REND_CLIENTNAME_MAX_LEN) {
00434           log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
00435                               "illegal client name: '%s'. Length must be "
00436                               "between 1 and %d characters.",
00437                    client_name, REND_CLIENTNAME_MAX_LEN);
00438           SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
00439           smartlist_free(clients);
00440           rend_service_free(service);
00441           return -1;
00442         }
00443         if (strspn(client_name, REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
00444           log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
00445                               "illegal client name: '%s'. Valid "
00446                               "characters are [A-Za-z0-9+_-].",
00447                    client_name);
00448           SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
00449           smartlist_free(clients);
00450           rend_service_free(service);
00451           return -1;
00452         }
00453         client = tor_malloc_zero(sizeof(rend_authorized_client_t));
00454         client->client_name = tor_strdup(client_name);
00455         smartlist_add(service->clients, client);
00456         log_debug(LD_REND, "Adding client name '%s'", client_name);
00457       }
00458       SMARTLIST_FOREACH_END(client_name);
00459       SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
00460       smartlist_free(clients);
00461       /* Ensure maximum number of clients. */
00462       if ((service->auth_type == REND_BASIC_AUTH &&
00463             smartlist_len(service->clients) > 512) ||
00464           (service->auth_type == REND_STEALTH_AUTH &&
00465             smartlist_len(service->clients) > 16)) {
00466         log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains %d "
00467                             "client authorization entries, but only a "
00468                             "maximum of %d entries is allowed for "
00469                             "authorization type '%s'.",
00470                  smartlist_len(service->clients),
00471                  service->auth_type == REND_BASIC_AUTH ? 512 : 16,
00472                  service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth");
00473         rend_service_free(service);
00474         return -1;
00475       }
00476     } else {
00477       tor_assert(!strcasecmp(line->key, "HiddenServiceVersion"));
00478       if (strcmp(line->value, "2")) {
00479         log_warn(LD_CONFIG,
00480                  "The only supported HiddenServiceVersion is 2.");
00481         rend_service_free(service);
00482         return -1;
00483       }
00484     }
00485   }
00486   if (service) {
00487     if (validate_only)
00488       rend_service_free(service);
00489     else
00490       rend_add_service(service);
00491   }
00492 
00493   /* If this is a reload and there were hidden services configured before,
00494    * keep the introduction points that are still needed and close the
00495    * other ones. */
00496   if (old_service_list && !validate_only) {
00497     smartlist_t *surviving_services = smartlist_new();
00498     circuit_t *circ;
00499 
00500     /* Copy introduction points to new services. */
00501     /* XXXX This is O(n^2), but it's only called on reconfigure, so it's
00502      * probably ok? */
00503     SMARTLIST_FOREACH(rend_service_list, rend_service_t *, new, {
00504       SMARTLIST_FOREACH(old_service_list, rend_service_t *, old, {
00505         if (!strcmp(old->directory, new->directory)) {
00506           smartlist_add_all(new->intro_nodes, old->intro_nodes);
00507           smartlist_clear(old->intro_nodes);
00508           smartlist_add(surviving_services, old);
00509           break;
00510         }
00511       });
00512     });
00513 
00514     /* Close introduction circuits of services we don't serve anymore. */
00515     /* XXXX it would be nicer if we had a nicer abstraction to use here,
00516      * so we could just iterate over the list of services to close, but
00517      * once again, this isn't critical-path code. */
00518     for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
00519       if (!circ->marked_for_close &&
00520           circ->state == CIRCUIT_STATE_OPEN &&
00521           (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
00522            circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
00523         origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
00524         int keep_it = 0;
00525         tor_assert(oc->rend_data);
00526         SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
00527           if (tor_memeq(ptr->pk_digest, oc->rend_data->rend_pk_digest,
00528                       DIGEST_LEN)) {
00529             keep_it = 1;
00530             break;
00531           }
00532         });
00533         if (keep_it)
00534           continue;
00535         log_info(LD_REND, "Closing intro point %s for service %s.",
00536                  safe_str_client(extend_info_describe(
00537                                             oc->build_state->chosen_exit)),
00538                  oc->rend_data->onion_address);
00539         circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
00540         /* XXXX Is there another reason we should use here? */
00541       }
00542     }
00543     smartlist_free(surviving_services);
00544     SMARTLIST_FOREACH(old_service_list, rend_service_t *, ptr,
00545                       rend_service_free(ptr));
00546     smartlist_free(old_service_list);
00547   }
00548 
00549   return 0;
00550 }
00551 
00555 static void
00556 rend_service_update_descriptor(rend_service_t *service)
00557 {
00558   rend_service_descriptor_t *d;
00559   origin_circuit_t *circ;
00560   int i;
00561 
00562   rend_service_descriptor_free(service->desc);
00563   service->desc = NULL;
00564 
00565   d = service->desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
00566   d->pk = crypto_pk_dup_key(service->private_key);
00567   d->timestamp = time(NULL);
00568   d->intro_nodes = smartlist_new();
00569   /* Support intro protocols 2 and 3. */
00570   d->protocols = (1 << 2) + (1 << 3);
00571 
00572   for (i = 0; i < smartlist_len(service->intro_nodes); ++i) {
00573     rend_intro_point_t *intro_svc = smartlist_get(service->intro_nodes, i);
00574     rend_intro_point_t *intro_desc;
00575 
00576     /* This intro point won't be listed in the descriptor... */
00577     intro_svc->listed_in_last_desc = 0;
00578 
00579     if (intro_svc->time_expiring != -1) {
00580       /* This intro point is expiring.  Don't list it. */
00581       continue;
00582     }
00583 
00584     circ = find_intro_circuit(intro_svc, service->pk_digest);
00585     if (!circ || circ->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) {
00586       /* This intro point's circuit isn't finished yet.  Don't list it. */
00587       continue;
00588     }
00589 
00590     /* ...unless this intro point is listed in the descriptor. */
00591     intro_svc->listed_in_last_desc = 1;
00592 
00593     /* We have an entirely established intro circuit.  Publish it in
00594      * our descriptor. */
00595     intro_desc = tor_malloc_zero(sizeof(rend_intro_point_t));
00596     intro_desc->extend_info = extend_info_dup(intro_svc->extend_info);
00597     if (intro_svc->intro_key)
00598       intro_desc->intro_key = crypto_pk_dup_key(intro_svc->intro_key);
00599     smartlist_add(d->intro_nodes, intro_desc);
00600 
00601     if (intro_svc->time_published == -1) {
00602       /* We are publishing this intro point in a descriptor for the
00603        * first time -- note the current time in the service's copy of
00604        * the intro point. */
00605       intro_svc->time_published = time(NULL);
00606     }
00607   }
00608 }
00609 
00614 int
00615 rend_service_load_keys(void)
00616 {
00617   int r = 0;
00618   char fname[512];
00619   char buf[1500];
00620 
00621   SMARTLIST_FOREACH_BEGIN(rend_service_list, rend_service_t *, s) {
00622     if (s->private_key)
00623       continue;
00624     log_info(LD_REND, "Loading hidden-service keys from \"%s\"",
00625              s->directory);
00626 
00627     /* Check/create directory */
00628     if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0)
00629       return -1;
00630 
00631     /* Load key */
00632     if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
00633         strlcat(fname,PATH_SEPARATOR"private_key",sizeof(fname))
00634                                                   >= sizeof(fname)) {
00635       log_warn(LD_CONFIG, "Directory name too long to store key file: \"%s\".",
00636                s->directory);
00637       return -1;
00638     }
00639     s->private_key = init_key_from_file(fname, 1, LOG_ERR);
00640     if (!s->private_key)
00641       return -1;
00642 
00643     /* Create service file */
00644     if (rend_get_service_id(s->private_key, s->service_id)<0) {
00645       log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
00646       return -1;
00647     }
00648     if (crypto_pk_get_digest(s->private_key, s->pk_digest)<0) {
00649       log_warn(LD_BUG, "Couldn't compute hash of public key.");
00650       return -1;
00651     }
00652     if (strlcpy(fname,s->directory,sizeof(fname)) >= sizeof(fname) ||
00653         strlcat(fname,PATH_SEPARATOR"hostname",sizeof(fname))
00654                                                   >= sizeof(fname)) {
00655       log_warn(LD_CONFIG, "Directory name too long to store hostname file:"
00656                " \"%s\".", s->directory);
00657       return -1;
00658     }
00659     tor_snprintf(buf, sizeof(buf),"%s.onion\n", s->service_id);
00660     if (write_str_to_file(fname,buf,0)<0) {
00661       log_warn(LD_CONFIG, "Could not write onion address to hostname file.");
00662       return -1;
00663     }
00664 
00665     /* If client authorization is configured, load or generate keys. */
00666     if (s->auth_type != REND_NO_AUTH) {
00667       char *client_keys_str = NULL;
00668       strmap_t *parsed_clients = strmap_new();
00669       char cfname[512];
00670       FILE *cfile, *hfile;
00671       open_file_t *open_cfile = NULL, *open_hfile = NULL;
00672 
00673       /* Load client keys and descriptor cookies, if available. */
00674       if (tor_snprintf(cfname, sizeof(cfname), "%s"PATH_SEPARATOR"client_keys",
00675                        s->directory)<0) {
00676         log_warn(LD_CONFIG, "Directory name too long to store client keys "
00677                  "file: \"%s\".", s->directory);
00678         goto err;
00679       }
00680       client_keys_str = read_file_to_str(cfname, RFTS_IGNORE_MISSING, NULL);
00681       if (client_keys_str) {
00682         if (rend_parse_client_keys(parsed_clients, client_keys_str) < 0) {
00683           log_warn(LD_CONFIG, "Previously stored client_keys file could not "
00684                               "be parsed.");
00685           goto err;
00686         } else {
00687           log_info(LD_CONFIG, "Parsed %d previously stored client entries.",
00688                    strmap_size(parsed_clients));
00689           tor_free(client_keys_str);
00690         }
00691       }
00692 
00693       /* Prepare client_keys and hostname files. */
00694       if (!(cfile = start_writing_to_stdio_file(cfname,
00695                                                 OPEN_FLAGS_REPLACE | O_TEXT,
00696                                                 0600, &open_cfile))) {
00697         log_warn(LD_CONFIG, "Could not open client_keys file %s",
00698                  escaped(cfname));
00699         goto err;
00700       }
00701       if (!(hfile = start_writing_to_stdio_file(fname,
00702                                                 OPEN_FLAGS_REPLACE | O_TEXT,
00703                                                 0600, &open_hfile))) {
00704         log_warn(LD_CONFIG, "Could not open hostname file %s", escaped(fname));
00705         goto err;
00706       }
00707 
00708       /* Either use loaded keys for configured clients or generate new
00709        * ones if a client is new. */
00710       SMARTLIST_FOREACH_BEGIN(s->clients, rend_authorized_client_t *, client)
00711       {
00712         char desc_cook_out[3*REND_DESC_COOKIE_LEN_BASE64+1];
00713         char service_id[16+1];
00714         rend_authorized_client_t *parsed =
00715             strmap_get(parsed_clients, client->client_name);
00716         int written;
00717         size_t len;
00718         /* Copy descriptor cookie from parsed entry or create new one. */
00719         if (parsed) {
00720           memcpy(client->descriptor_cookie, parsed->descriptor_cookie,
00721                  REND_DESC_COOKIE_LEN);
00722         } else {
00723           crypto_rand(client->descriptor_cookie, REND_DESC_COOKIE_LEN);
00724         }
00725         if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
00726                           client->descriptor_cookie,
00727                           REND_DESC_COOKIE_LEN) < 0) {
00728           log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
00729           strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
00730           return -1;
00731         }
00732         /* Copy client key from parsed entry or create new one if required. */
00733         if (parsed && parsed->client_key) {
00734           client->client_key = crypto_pk_dup_key(parsed->client_key);
00735         } else if (s->auth_type == REND_STEALTH_AUTH) {
00736           /* Create private key for client. */
00737           crypto_pk_t *prkey = NULL;
00738           if (!(prkey = crypto_pk_new())) {
00739             log_warn(LD_BUG,"Error constructing client key");
00740             goto err;
00741           }
00742           if (crypto_pk_generate_key(prkey)) {
00743             log_warn(LD_BUG,"Error generating client key");
00744             crypto_pk_free(prkey);
00745             goto err;
00746           }
00747           if (crypto_pk_check_key(prkey) <= 0) {
00748             log_warn(LD_BUG,"Generated client key seems invalid");
00749             crypto_pk_free(prkey);
00750             goto err;
00751           }
00752           client->client_key = prkey;
00753         }
00754         /* Add entry to client_keys file. */
00755         desc_cook_out[strlen(desc_cook_out)-1] = '\0'; /* Remove newline. */
00756         written = tor_snprintf(buf, sizeof(buf),
00757                                "client-name %s\ndescriptor-cookie %s\n",
00758                                client->client_name, desc_cook_out);
00759         if (written < 0) {
00760           log_warn(LD_BUG, "Could not write client entry.");
00761           goto err;
00762         }
00763         if (client->client_key) {
00764           char *client_key_out = NULL;
00765           crypto_pk_write_private_key_to_string(client->client_key,
00766                                                 &client_key_out, &len);
00767           if (rend_get_service_id(client->client_key, service_id)<0) {
00768             log_warn(LD_BUG, "Internal error: couldn't encode service ID.");
00769             tor_free(client_key_out);
00770             goto err;
00771           }
00772           written = tor_snprintf(buf + written, sizeof(buf) - written,
00773                                  "client-key\n%s", client_key_out);
00774           tor_free(client_key_out);
00775           if (written < 0) {
00776             log_warn(LD_BUG, "Could not write client entry.");
00777             goto err;
00778           }
00779         }
00780 
00781         if (fputs(buf, cfile) < 0) {
00782           log_warn(LD_FS, "Could not append client entry to file: %s",
00783                    strerror(errno));
00784           goto err;
00785         }
00786 
00787         /* Add line to hostname file. */
00788         if (s->auth_type == REND_BASIC_AUTH) {
00789           /* Remove == signs (newline has been removed above). */
00790           desc_cook_out[strlen(desc_cook_out)-2] = '\0';
00791           tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
00792                        s->service_id, desc_cook_out, client->client_name);
00793         } else {
00794           char extended_desc_cookie[REND_DESC_COOKIE_LEN+1];
00795           memcpy(extended_desc_cookie, client->descriptor_cookie,
00796                  REND_DESC_COOKIE_LEN);
00797           extended_desc_cookie[REND_DESC_COOKIE_LEN] =
00798               ((int)s->auth_type - 1) << 4;
00799           if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
00800                             extended_desc_cookie,
00801                             REND_DESC_COOKIE_LEN+1) < 0) {
00802             log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
00803             goto err;
00804           }
00805           desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove A= and
00806                                                             newline. */
00807           tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
00808                        service_id, desc_cook_out, client->client_name);
00809         }
00810 
00811         if (fputs(buf, hfile)<0) {
00812           log_warn(LD_FS, "Could not append host entry to file: %s",
00813                    strerror(errno));
00814           goto err;
00815         }
00816       }
00817       SMARTLIST_FOREACH_END(client);
00818 
00819       goto done;
00820     err:
00821       r = -1;
00822     done:
00823       tor_free(client_keys_str);
00824       strmap_free(parsed_clients, rend_authorized_client_strmap_item_free);
00825       if (r<0) {
00826         if (open_cfile)
00827           abort_writing_to_file(open_cfile);
00828         if (open_hfile)
00829           abort_writing_to_file(open_hfile);
00830         return r;
00831       } else {
00832         finish_writing_to_file(open_cfile);
00833         finish_writing_to_file(open_hfile);
00834       }
00835     }
00836   } SMARTLIST_FOREACH_END(s);
00837   return r;
00838 }
00839 
00843 static rend_service_t *
00844 rend_service_get_by_pk_digest(const char* digest)
00845 {
00846   SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
00847                     if (tor_memeq(s->pk_digest,digest,DIGEST_LEN))
00848                         return s);
00849   return NULL;
00850 }
00851 
00855 static int
00856 rend_service_requires_uptime(rend_service_t *service)
00857 {
00858   int i;
00859   rend_service_port_config_t *p;
00860 
00861   for (i=0; i < smartlist_len(service->ports); ++i) {
00862     p = smartlist_get(service->ports, i);
00863     if (smartlist_string_num_isin(get_options()->LongLivedPorts,
00864                                   p->virtual_port))
00865       return 1;
00866   }
00867   return 0;
00868 }
00869 
00872 static int
00873 rend_check_authorization(rend_service_t *service,
00874                          const char *descriptor_cookie)
00875 {
00876   rend_authorized_client_t *auth_client = NULL;
00877   tor_assert(service);
00878   tor_assert(descriptor_cookie);
00879   if (!service->clients) {
00880     log_warn(LD_BUG, "Can't check authorization for a service that has no "
00881                      "authorized clients configured.");
00882     return 0;
00883   }
00884 
00885   /* Look up client authorization by descriptor cookie. */
00886   SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, client, {
00887     if (tor_memeq(client->descriptor_cookie, descriptor_cookie,
00888                 REND_DESC_COOKIE_LEN)) {
00889       auth_client = client;
00890       break;
00891     }
00892   });
00893   if (!auth_client) {
00894     char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64];
00895     base64_encode(descriptor_cookie_base64, sizeof(descriptor_cookie_base64),
00896                   descriptor_cookie, REND_DESC_COOKIE_LEN);
00897     log_info(LD_REND, "No authorization found for descriptor cookie '%s'! "
00898                       "Dropping cell!",
00899              descriptor_cookie_base64);
00900     return 0;
00901   }
00902 
00903   /* Allow the request. */
00904   log_debug(LD_REND, "Client %s authorized for service %s.",
00905             auth_client->client_name, service->service_id);
00906   return 1;
00907 }
00908 
00911 static void
00912 clean_accepted_intro_dh_parts(rend_service_t *service, time_t now)
00913 {
00914   const time_t cutoff = now - REND_REPLAY_TIME_INTERVAL;
00915 
00916   service->last_cleaned_accepted_intro_dh_parts = now;
00917   if (!service->accepted_intro_dh_parts)
00918     return;
00919 
00920   DIGESTMAP_FOREACH_MODIFY(service->accepted_intro_dh_parts, digest,
00921                            time_t *, t) {
00922     if (*t < cutoff) {
00923       tor_free(t);
00924       MAP_DEL_CURRENT(digest);
00925     }
00926   } DIGESTMAP_FOREACH_END;
00927 }
00928 
00931 static void
00932 rend_service_note_removing_intro_point(rend_service_t *service,
00933                                        rend_intro_point_t *intro)
00934 {
00935   time_t now = time(NULL);
00936 
00937   /* Don't process an intro point twice here. */
00938   if (intro->rend_service_note_removing_intro_point_called) {
00939     return;
00940   } else {
00941     intro->rend_service_note_removing_intro_point_called = 1;
00942   }
00943 
00944   /* Update service->n_intro_points_wanted based on how long intro
00945    * lasted and how many introductions it handled. */
00946   if (intro->time_published == -1) {
00947     /* This intro point was never used.  Don't change
00948      * n_intro_points_wanted. */
00949   } else {
00950     /* We want to increase the number of introduction points service
00951      * operates if intro was heavily used, or decrease the number of
00952      * intro points if intro was lightly used.
00953      *
00954      * We consider an intro point's target 'usage' to be
00955      * INTRO_POINT_LIFETIME_INTRODUCTIONS introductions in
00956      * INTRO_POINT_LIFETIME_MIN_SECONDS seconds.  To calculate intro's
00957      * fraction of target usage, we divide the fraction of
00958      * _LIFETIME_INTRODUCTIONS introductions that it has handled by
00959      * the fraction of _LIFETIME_MIN_SECONDS for which it existed.
00960      *
00961      * Then we multiply that fraction of desired usage by a fudge
00962      * factor of 1.5, to decide how many new introduction points
00963      * should ideally replace intro (which is now closed or soon to be
00964      * closed).  In theory, assuming that introduction load is
00965      * distributed equally across all intro points and ignoring the
00966      * fact that different intro points are established and closed at
00967      * different times, that number of intro points should bring all
00968      * of our intro points exactly to our target usage.
00969      *
00970      * Then we clamp that number to a number of intro points we might
00971      * be willing to replace this intro point with and turn it into an
00972      * integer. then we clamp it again to the number of new intro
00973      * points we could establish now, then we adjust
00974      * service->n_intro_points_wanted and let rend_services_introduce
00975      * create the new intro points we want (if any).
00976      */
00977     const double intro_point_usage =
00978       intro_point_accepted_intro_count(intro) /
00979       (double)(now - intro->time_published);
00980     const double intro_point_target_usage =
00981       INTRO_POINT_LIFETIME_INTRODUCTIONS /
00982       (double)INTRO_POINT_LIFETIME_MIN_SECONDS;
00983     const double fractional_n_intro_points_wanted_to_replace_this_one =
00984       (1.5 * (intro_point_usage / intro_point_target_usage));
00985     unsigned int n_intro_points_wanted_to_replace_this_one;
00986     unsigned int n_intro_points_wanted_now;
00987     unsigned int n_intro_points_really_wanted_now;
00988     int n_intro_points_really_replacing_this_one;
00989 
00990     if (fractional_n_intro_points_wanted_to_replace_this_one >
00991         NUM_INTRO_POINTS_MAX) {
00992       n_intro_points_wanted_to_replace_this_one = NUM_INTRO_POINTS_MAX;
00993     } else if (fractional_n_intro_points_wanted_to_replace_this_one < 0) {
00994       n_intro_points_wanted_to_replace_this_one = 0;
00995     } else {
00996       n_intro_points_wanted_to_replace_this_one = (unsigned)
00997         fractional_n_intro_points_wanted_to_replace_this_one;
00998     }
00999 
01000     n_intro_points_wanted_now =
01001       service->n_intro_points_wanted +
01002       n_intro_points_wanted_to_replace_this_one - 1;
01003 
01004     if (n_intro_points_wanted_now < NUM_INTRO_POINTS_DEFAULT) {
01005       /* XXXX This should be NUM_INTRO_POINTS_MIN instead.  Perhaps
01006        * another use of NUM_INTRO_POINTS_DEFAULT should be, too. */
01007       n_intro_points_really_wanted_now = NUM_INTRO_POINTS_DEFAULT;
01008     } else if (n_intro_points_wanted_now > NUM_INTRO_POINTS_MAX) {
01009       n_intro_points_really_wanted_now = NUM_INTRO_POINTS_MAX;
01010     } else {
01011       n_intro_points_really_wanted_now = n_intro_points_wanted_now;
01012     }
01013 
01014     n_intro_points_really_replacing_this_one =
01015       n_intro_points_really_wanted_now - service->n_intro_points_wanted + 1;
01016 
01017     log_info(LD_REND, "Replacing closing intro point for service %s "
01018              "with %d new intro points (wanted %g replacements); "
01019              "service will now try to have %u intro points",
01020              rend_service_describe_for_log(service),
01021              n_intro_points_really_replacing_this_one,
01022              fractional_n_intro_points_wanted_to_replace_this_one,
01023              n_intro_points_really_wanted_now);
01024 
01025     service->n_intro_points_wanted = n_intro_points_really_wanted_now;
01026   }
01027 }
01028 
01029 /******
01030  * Handle cells
01031  ******/
01032 
01036  /* XXXX024 this function sure could use some organizing. -RD */
01037 int
01038 rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
01039                        size_t request_len)
01040 {
01041   char *ptr, *r_cookie;
01042   extend_info_t *extend_info = NULL;
01043   char buf[RELAY_PAYLOAD_SIZE];
01044   char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN]; /* Holds KH, Df, Db, Kf, Kb */
01045   rend_service_t *service;
01046   rend_intro_point_t *intro_point;
01047   int r, i, v3_shift = 0;
01048   size_t len, keylen;
01049   crypto_dh_t *dh = NULL;
01050   origin_circuit_t *launched = NULL;
01051   crypt_path_t *cpath = NULL;
01052   char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
01053   char hexcookie[9];
01054   int circ_needs_uptime;
01055   int reason = END_CIRC_REASON_TORPROTOCOL;
01056   crypto_pk_t *intro_key;
01057   char intro_key_digest[DIGEST_LEN];
01058   int auth_type;
01059   size_t auth_len = 0;
01060   char auth_data[REND_DESC_COOKIE_LEN];
01061   crypto_digest_t *digest = NULL;
01062   time_t now = time(NULL);
01063   char diffie_hellman_hash[DIGEST_LEN];
01064   time_t *access_time;
01065   const or_options_t *options = get_options();
01066 
01067   if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) {
01068     log_warn(LD_PROTOCOL,
01069              "Got an INTRODUCE2 over a non-introduction circuit %d.",
01070              circuit->_base.n_circ_id);
01071     return -1;
01072   }
01073 
01074 #ifndef NON_ANONYMOUS_MODE_ENABLED
01075   tor_assert(!(circuit->build_state->onehop_tunnel));
01076 #endif
01077   tor_assert(circuit->rend_data);
01078 
01079   base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
01080                 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
01081   log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %d.",
01082            escaped(serviceid), circuit->_base.n_circ_id);
01083 
01084   /* min key length plus digest length plus nickname length */
01085   if (request_len < DIGEST_LEN+REND_COOKIE_LEN+(MAX_NICKNAME_LEN+1)+
01086       DH_KEY_LEN+42) {
01087     log_warn(LD_PROTOCOL, "Got a truncated INTRODUCE2 cell on circ %d.",
01088              circuit->_base.n_circ_id);
01089     return -1;
01090   }
01091 
01092   /* look up service depending on circuit. */
01093   service = rend_service_get_by_pk_digest(
01094                 circuit->rend_data->rend_pk_digest);
01095   if (!service) {
01096     log_warn(LD_BUG, "Internal error: Got an INTRODUCE2 cell on an intro "
01097              "circ for an unrecognized service %s.",
01098              escaped(serviceid));
01099     return -1;
01100   }
01101 
01102   /* use intro key instead of service key. */
01103   intro_key = circuit->intro_key;
01104 
01105   /* first DIGEST_LEN bytes of request is intro or service pk digest */
01106   crypto_pk_get_digest(intro_key, intro_key_digest);
01107   if (tor_memneq(intro_key_digest, request, DIGEST_LEN)) {
01108     base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
01109                   (char*)request, REND_SERVICE_ID_LEN);
01110     log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).",
01111              escaped(serviceid));
01112     return -1;
01113   }
01114 
01115   keylen = crypto_pk_keysize(intro_key);
01116   if (request_len < keylen+DIGEST_LEN) {
01117     log_warn(LD_PROTOCOL,
01118              "PK-encrypted portion of INTRODUCE2 cell was truncated.");
01119     return -1;
01120   }
01121 
01122   intro_point = find_intro_point(circuit);
01123   if (intro_point == NULL) {
01124     log_warn(LD_BUG, "Internal error: Got an INTRODUCE2 cell on an intro circ "
01125              "(for service %s) with no corresponding rend_intro_point_t.",
01126              escaped(serviceid));
01127     return -1;
01128   }
01129 
01130   if (!service->accepted_intro_dh_parts)
01131     service->accepted_intro_dh_parts = digestmap_new();
01132 
01133   if (!intro_point->accepted_intro_rsa_parts)
01134     intro_point->accepted_intro_rsa_parts = digestmap_new();
01135 
01136   {
01137     char pkpart_digest[DIGEST_LEN];
01138     /* Check for replay of PK-encrypted portion. */
01139     crypto_digest(pkpart_digest, (char*)request+DIGEST_LEN, keylen);
01140     access_time = digestmap_get(intro_point->accepted_intro_rsa_parts,
01141                                 pkpart_digest);
01142     if (access_time != NULL) {
01143       log_warn(LD_REND, "Possible replay detected! We received an "
01144                "INTRODUCE2 cell with same PK-encrypted part %d seconds ago. "
01145                "Dropping cell.", (int)(now-*access_time));
01146       return -1;
01147     }
01148     access_time = tor_malloc(sizeof(time_t));
01149     *access_time = now;
01150     digestmap_set(intro_point->accepted_intro_rsa_parts,
01151                   pkpart_digest, access_time);
01152   }
01153 
01154   /* Next N bytes is encrypted with service key */
01155   note_crypto_pk_op(REND_SERVER);
01156   r = crypto_pk_private_hybrid_decrypt(
01157        intro_key,buf,sizeof(buf),
01158        (char*)(request+DIGEST_LEN),request_len-DIGEST_LEN,
01159        PK_PKCS1_OAEP_PADDING,1);
01160   if (r<0) {
01161     log_warn(LD_PROTOCOL, "Couldn't decrypt INTRODUCE2 cell.");
01162     return -1;
01163   }
01164   len = r;
01165   if (*buf == 3) {
01166     /* Version 3 INTRODUCE2 cell. */
01167     v3_shift = 1;
01168     auth_type = buf[1];
01169     switch (auth_type) {
01170       case REND_BASIC_AUTH:
01171         /* fall through */
01172       case REND_STEALTH_AUTH:
01173         auth_len = ntohs(get_uint16(buf+2));
01174         if (auth_len != REND_DESC_COOKIE_LEN) {
01175           log_info(LD_REND, "Wrong auth data size %d, should be %d.",
01176                    (int)auth_len, REND_DESC_COOKIE_LEN);
01177           return -1;
01178         }
01179         memcpy(auth_data, buf+4, sizeof(auth_data));
01180         v3_shift += 2+REND_DESC_COOKIE_LEN;
01181         break;
01182       case REND_NO_AUTH:
01183         break;
01184       default:
01185         log_info(LD_REND, "Unknown authorization type '%d'", auth_type);
01186     }
01187 
01188     /* Skip the timestamp field.  We no longer use it. */
01189     v3_shift += 4;
01190   }
01191   if (*buf == 2 || *buf == 3) {
01192     /* Version 2 INTRODUCE2 cell. */
01193     int klen;
01194     extend_info = tor_malloc_zero(sizeof(extend_info_t));
01195     tor_addr_from_ipv4n(&extend_info->addr, get_uint32(buf+v3_shift+1));
01196     extend_info->port = ntohs(get_uint16(buf+v3_shift+5));
01197     memcpy(extend_info->identity_digest, buf+v3_shift+7,
01198            DIGEST_LEN);
01199     extend_info->nickname[0] = '$';
01200     base16_encode(extend_info->nickname+1, sizeof(extend_info->nickname)-1,
01201                   extend_info->identity_digest, DIGEST_LEN);
01202 
01203     klen = ntohs(get_uint16(buf+v3_shift+7+DIGEST_LEN));
01204     if ((int)len != v3_shift+7+DIGEST_LEN+2+klen+20+128) {
01205       log_warn(LD_PROTOCOL, "Bad length %u for version %d INTRODUCE2 cell.",
01206                (int)len, *buf);
01207       reason = END_CIRC_REASON_TORPROTOCOL;
01208       goto err;
01209     }
01210     extend_info->onion_key =
01211         crypto_pk_asn1_decode(buf+v3_shift+7+DIGEST_LEN+2, klen);
01212     if (!extend_info->onion_key) {
01213       log_warn(LD_PROTOCOL, "Error decoding onion key in version %d "
01214                             "INTRODUCE2 cell.", *buf);
01215       reason = END_CIRC_REASON_TORPROTOCOL;
01216       goto err;
01217     }
01218     ptr = buf+v3_shift+7+DIGEST_LEN+2+klen;
01219     len -= v3_shift+7+DIGEST_LEN+2+klen;
01220   } else {
01221     char *rp_nickname;
01222     size_t nickname_field_len;
01223     const node_t *node;
01224     int version;
01225     if (*buf == 1) {
01226       rp_nickname = buf+1;
01227       nickname_field_len = MAX_HEX_NICKNAME_LEN+1;
01228       version = 1;
01229     } else {
01230       nickname_field_len = MAX_NICKNAME_LEN+1;
01231       rp_nickname = buf;
01232       version = 0;
01233     }
01234     ptr=memchr(rp_nickname,0,nickname_field_len);
01235     if (!ptr || ptr == rp_nickname) {
01236       log_warn(LD_PROTOCOL,
01237                "Couldn't find a nul-padded nickname in INTRODUCE2 cell.");
01238       return -1;
01239     }
01240     if ((version == 0 && !is_legal_nickname(rp_nickname)) ||
01241         (version == 1 && !is_legal_nickname_or_hexdigest(rp_nickname))) {
01242       log_warn(LD_PROTOCOL, "Bad nickname in INTRODUCE2 cell.");
01243       return -1;
01244     }
01245     /* Okay, now we know that a nickname is at the start of the buffer. */
01246     ptr = rp_nickname+nickname_field_len;
01247     len -= nickname_field_len;
01248     len -= rp_nickname - buf; /* also remove header space used by version, if
01249                                * any */
01250     node = node_get_by_nickname(rp_nickname, 0);
01251     if (!node) {
01252       log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
01253                escaped_safe_str_client(rp_nickname));
01254       /* XXXX Add a no-such-router reason? */
01255       reason = END_CIRC_REASON_TORPROTOCOL;
01256       goto err;
01257     }
01258 
01259     extend_info = extend_info_from_node(node, 0);
01260   }
01261 
01262   if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
01263     log_warn(LD_PROTOCOL, "Bad length %u for INTRODUCE2 cell.", (int)len);
01264     reason = END_CIRC_REASON_TORPROTOCOL;
01265     goto err;
01266   }
01267 
01268   /* Check if we'd refuse to talk to this router */
01269   if (options->StrictNodes &&
01270       routerset_contains_extendinfo(options->ExcludeNodes, extend_info)) {
01271     log_warn(LD_REND, "Client asked to rendezvous at a relay that we "
01272              "exclude, and StrictNodes is set. Refusing service.");
01273     reason = END_CIRC_REASON_INTERNAL; /* XXX might leak why we refused */
01274     goto err;
01275   }
01276 
01277   r_cookie = ptr;
01278   base16_encode(hexcookie,9,r_cookie,4);
01279 
01280   /* Determine hash of Diffie-Hellman, part 1 to detect replays. */
01281   digest = crypto_digest_new();
01282   crypto_digest_add_bytes(digest, ptr+REND_COOKIE_LEN, DH_KEY_LEN);
01283   crypto_digest_get_digest(digest, diffie_hellman_hash, DIGEST_LEN);
01284   crypto_digest_free(digest);
01285 
01286   /* Check whether there is a past request with the same Diffie-Hellman,
01287    * part 1. */
01288   access_time = digestmap_get(service->accepted_intro_dh_parts,
01289                               diffie_hellman_hash);
01290   if (access_time != NULL) {
01291     /* A Tor client will send a new INTRODUCE1 cell with the same rend
01292      * cookie and DH public key as its previous one if its intro circ
01293      * times out while in state CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT .
01294      * If we received the first INTRODUCE1 cell (the intro-point relay
01295      * converts it into an INTRODUCE2 cell), we are already trying to
01296      * connect to that rend point (and may have already succeeded);
01297      * drop this cell. */
01298     log_info(LD_REND, "We received an "
01299              "INTRODUCE2 cell with same first part of "
01300              "Diffie-Hellman handshake %d seconds ago. Dropping "
01301              "cell.",
01302              (int) (now - *access_time));
01303     goto err;
01304   }
01305 
01306   /* Add request to access history, including time and hash of Diffie-Hellman,
01307    * part 1, and possibly remove requests from the history that are older than
01308    * one hour. */
01309   access_time = tor_malloc(sizeof(time_t));
01310   *access_time = now;
01311   digestmap_set(service->accepted_intro_dh_parts,
01312                 diffie_hellman_hash, access_time);
01313   if (service->last_cleaned_accepted_intro_dh_parts + REND_REPLAY_TIME_INTERVAL
01314       < now)
01315     clean_accepted_intro_dh_parts(service, now);
01316 
01317   /* If the service performs client authorization, check included auth data. */
01318   if (service->clients) {
01319     if (auth_len > 0) {
01320       if (rend_check_authorization(service, auth_data)) {
01321         log_info(LD_REND, "Authorization data in INTRODUCE2 cell are valid.");
01322       } else {
01323         log_info(LD_REND, "The authorization data that are contained in "
01324                  "the INTRODUCE2 cell are invalid. Dropping cell.");
01325         reason = END_CIRC_REASON_CONNECTFAILED;
01326         goto err;
01327       }
01328     } else {
01329       log_info(LD_REND, "INTRODUCE2 cell does not contain authentication "
01330                "data, but we require client authorization. Dropping cell.");
01331       reason = END_CIRC_REASON_CONNECTFAILED;
01332       goto err;
01333     }
01334   }
01335 
01336   /* Try DH handshake... */
01337   dh = crypto_dh_new(DH_TYPE_REND);
01338   if (!dh || crypto_dh_generate_public(dh)<0) {
01339     log_warn(LD_BUG,"Internal error: couldn't build DH state "
01340              "or generate public key.");
01341     reason = END_CIRC_REASON_INTERNAL;
01342     goto err;
01343   }
01344   if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, ptr+REND_COOKIE_LEN,
01345                                DH_KEY_LEN, keys,
01346                                DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
01347     log_warn(LD_BUG, "Internal error: couldn't complete DH handshake");
01348     reason = END_CIRC_REASON_INTERNAL;
01349     goto err;
01350   }
01351 
01352   circ_needs_uptime = rend_service_requires_uptime(service);
01353 
01354   /* help predict this next time */
01355   rep_hist_note_used_internal(now, circ_needs_uptime, 1);
01356 
01357   /* Launch a circuit to alice's chosen rendezvous point.
01358    */
01359   for (i=0;i<MAX_REND_FAILURES;i++) {
01360     int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL;
01361     if (circ_needs_uptime) flags |= CIRCLAUNCH_NEED_UPTIME;
01362     launched = circuit_launch_by_extend_info(
01363                         CIRCUIT_PURPOSE_S_CONNECT_REND, extend_info, flags);
01364 
01365     if (launched)
01366       break;
01367   }
01368   if (!launched) { /* give up */
01369     log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous "
01370              "point %s for service %s.",
01371              safe_str_client(extend_info_describe(extend_info)),
01372              serviceid);
01373     reason = END_CIRC_REASON_CONNECTFAILED;
01374     goto err;
01375   }
01376   log_info(LD_REND,
01377            "Accepted intro; launching circuit to %s "
01378            "(cookie %s) for service %s.",
01379            safe_str_client(extend_info_describe(extend_info)),
01380            hexcookie, serviceid);
01381   tor_assert(launched->build_state);
01382   /* Fill in the circuit's state. */
01383   launched->rend_data = tor_malloc_zero(sizeof(rend_data_t));
01384   memcpy(launched->rend_data->rend_pk_digest,
01385          circuit->rend_data->rend_pk_digest,
01386          DIGEST_LEN);
01387   memcpy(launched->rend_data->rend_cookie, r_cookie, REND_COOKIE_LEN);
01388   strlcpy(launched->rend_data->onion_address, service->service_id,
01389           sizeof(launched->rend_data->onion_address));
01390 
01391   launched->build_state->service_pending_final_cpath_ref =
01392     tor_malloc_zero(sizeof(crypt_path_reference_t));
01393   launched->build_state->service_pending_final_cpath_ref->refcount = 1;
01394 
01395   launched->build_state->service_pending_final_cpath_ref->cpath = cpath =
01396     tor_malloc_zero(sizeof(crypt_path_t));
01397   cpath->magic = CRYPT_PATH_MAGIC;
01398   launched->build_state->expiry_time = now + MAX_REND_TIMEOUT;
01399 
01400   cpath->dh_handshake_state = dh;
01401   dh = NULL;
01402   if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0)
01403     goto err;
01404   memcpy(cpath->handshake_digest, keys, DIGEST_LEN);
01405   if (extend_info) extend_info_free(extend_info);
01406 
01407   memset(keys, 0, sizeof(keys));
01408   return 0;
01409  err:
01410   memset(keys, 0, sizeof(keys));
01411   if (dh) crypto_dh_free(dh);
01412   if (launched)
01413     circuit_mark_for_close(TO_CIRCUIT(launched), reason);
01414   if (extend_info) extend_info_free(extend_info);
01415   return -1;
01416 }
01417 
01421 void
01422 rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
01423 {
01424   origin_circuit_t *newcirc;
01425   cpath_build_state_t *newstate, *oldstate;
01426 
01427   tor_assert(oldcirc->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
01428 
01429   /* Don't relaunch the same rend circ twice. */
01430   if (oldcirc->hs_service_side_rend_circ_has_been_relaunched) {
01431     log_info(LD_REND, "Rendezvous circuit to %s has already been relaunched; "
01432              "not relaunching it again.",
01433              oldcirc->build_state ?
01434              safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
01435              : "*unknown*");
01436     return;
01437   }
01438   oldcirc->hs_service_side_rend_circ_has_been_relaunched = 1;
01439 
01440   if (!oldcirc->build_state ||
01441       oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
01442       oldcirc->build_state->expiry_time < time(NULL)) {
01443     log_info(LD_REND,
01444              "Attempt to build circuit to %s for rendezvous has failed "
01445              "too many times or expired; giving up.",
01446              oldcirc->build_state ?
01447              safe_str(extend_info_describe(oldcirc->build_state->chosen_exit))
01448              : "*unknown*");
01449     return;
01450   }
01451 
01452   oldstate = oldcirc->build_state;
01453   tor_assert(oldstate);
01454 
01455   if (oldstate->service_pending_final_cpath_ref == NULL) {
01456     log_info(LD_REND,"Skipping relaunch of circ that failed on its first hop. "
01457              "Initiator will retry.");
01458     return;
01459   }
01460 
01461   log_info(LD_REND,"Reattempting rendezvous circuit to '%s'",
01462            safe_str(extend_info_describe(oldstate->chosen_exit)));
01463 
01464   newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND,
01465                             oldstate->chosen_exit,
01466                             CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
01467 
01468   if (!newcirc) {
01469     log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.",
01470              safe_str(extend_info_describe(oldstate->chosen_exit)));
01471     return;
01472   }
01473   newstate = newcirc->build_state;
01474   tor_assert(newstate);
01475   newstate->failure_count = oldstate->failure_count+1;
01476   newstate->expiry_time = oldstate->expiry_time;
01477   newstate->service_pending_final_cpath_ref =
01478     oldstate->service_pending_final_cpath_ref;
01479   ++(newstate->service_pending_final_cpath_ref->refcount);
01480 
01481   newcirc->rend_data = rend_data_dup(oldcirc->rend_data);
01482 }
01483 
01487 static int
01488 rend_service_launch_establish_intro(rend_service_t *service,
01489                                     rend_intro_point_t *intro)
01490 {
01491   origin_circuit_t *launched;
01492 
01493   log_info(LD_REND,
01494            "Launching circuit to introduction point %s for service %s",
01495            safe_str_client(extend_info_describe(intro->extend_info)),
01496            service->service_id);
01497 
01498   rep_hist_note_used_internal(time(NULL), 1, 0);
01499 
01500   ++service->n_intro_circuits_launched;
01501   launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
01502                              intro->extend_info,
01503                              CIRCLAUNCH_NEED_UPTIME|CIRCLAUNCH_IS_INTERNAL);
01504 
01505   if (!launched) {
01506     log_info(LD_REND,
01507              "Can't launch circuit to establish introduction at %s.",
01508              safe_str_client(extend_info_describe(intro->extend_info)));
01509     return -1;
01510   }
01511 
01512   if (tor_memneq(intro->extend_info->identity_digest,
01513       launched->build_state->chosen_exit->identity_digest, DIGEST_LEN)) {
01514     char cann[HEX_DIGEST_LEN+1], orig[HEX_DIGEST_LEN+1];
01515     base16_encode(cann, sizeof(cann),
01516                   launched->build_state->chosen_exit->identity_digest,
01517                   DIGEST_LEN);
01518     base16_encode(orig, sizeof(orig),
01519                   intro->extend_info->identity_digest, DIGEST_LEN);
01520     log_info(LD_REND, "The intro circuit we just cannibalized ends at $%s, "
01521                       "but we requested an intro circuit to $%s. Updating "
01522                       "our service.", cann, orig);
01523     extend_info_free(intro->extend_info);
01524     intro->extend_info = extend_info_dup(launched->build_state->chosen_exit);
01525   }
01526 
01527   launched->rend_data = tor_malloc_zero(sizeof(rend_data_t));
01528   strlcpy(launched->rend_data->onion_address, service->service_id,
01529           sizeof(launched->rend_data->onion_address));
01530   memcpy(launched->rend_data->rend_pk_digest, service->pk_digest, DIGEST_LEN);
01531   launched->intro_key = crypto_pk_dup_key(intro->intro_key);
01532   if (launched->_base.state == CIRCUIT_STATE_OPEN)
01533     rend_service_intro_has_opened(launched);
01534   return 0;
01535 }
01536 
01539 static int
01540 count_established_intro_points(const char *query)
01541 {
01542   int num_ipos = 0;
01543   circuit_t *circ;
01544   for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
01545     if (!circ->marked_for_close &&
01546         circ->state == CIRCUIT_STATE_OPEN &&
01547         (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
01548          circ->purpose == CIRCUIT_PURPOSE_S_INTRO)) {
01549       origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ);
01550       if (oc->rend_data &&
01551           !rend_cmp_service_ids(query, oc->rend_data->onion_address))
01552         num_ipos++;
01553     }
01554   }
01555   return num_ipos;
01556 }
01557 
01561 void
01562 rend_service_intro_has_opened(origin_circuit_t *circuit)
01563 {
01564   rend_service_t *service;
01565   size_t len;
01566   int r;
01567   char buf[RELAY_PAYLOAD_SIZE];
01568   char auth[DIGEST_LEN + 9];
01569   char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
01570   int reason = END_CIRC_REASON_TORPROTOCOL;
01571   crypto_pk_t *intro_key;
01572 
01573   tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
01574 #ifndef NON_ANONYMOUS_MODE_ENABLED
01575   tor_assert(!(circuit->build_state->onehop_tunnel));
01576 #endif
01577   tor_assert(circuit->cpath);
01578   tor_assert(circuit->rend_data);
01579 
01580   base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
01581                 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
01582 
01583   service = rend_service_get_by_pk_digest(
01584                 circuit->rend_data->rend_pk_digest);
01585   if (!service) {
01586     log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.",
01587              serviceid, circuit->_base.n_circ_id);
01588     reason = END_CIRC_REASON_NOSUCHSERVICE;
01589     goto err;
01590   }
01591 
01592   /* If we already have enough introduction circuits for this service,
01593    * redefine this one as a general circuit or close it, depending. */
01594   if (count_established_intro_points(serviceid) >
01595       (int)service->n_intro_points_wanted) { /* XXX023 remove cast */
01596     const or_options_t *options = get_options();
01597     if (options->ExcludeNodes) {
01598       /* XXXX in some future version, we can test whether the transition is
01599          allowed or not given the actual nodes in the circuit.  But for now,
01600          this case, we might as well close the thing. */
01601       log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
01602                "circuit, but we already have enough.  Closing it.");
01603       circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_NONE);
01604       return;
01605     } else {
01606       tor_assert(circuit->build_state->is_internal);
01607       log_info(LD_CIRC|LD_REND, "We have just finished an introduction "
01608                "circuit, but we already have enough. Redefining purpose to "
01609                "general; leaving as internal.");
01610 
01611       circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_C_GENERAL);
01612 
01613       {
01614         rend_data_t *rend_data = circuit->rend_data;
01615         circuit->rend_data = NULL;
01616         rend_data_free(rend_data);
01617       }
01618       {
01619         crypto_pk_t *intro_key = circuit->intro_key;
01620         circuit->intro_key = NULL;
01621         crypto_pk_free(intro_key);
01622       }
01623 
01624       circuit_has_opened(circuit);
01625       return;
01626     }
01627   }
01628 
01629   log_info(LD_REND,
01630            "Established circuit %d as introduction point for service %s",
01631            circuit->_base.n_circ_id, serviceid);
01632 
01633   /* Use the intro key instead of the service key in ESTABLISH_INTRO. */
01634   intro_key = circuit->intro_key;
01635   /* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
01636   r = crypto_pk_asn1_encode(intro_key, buf+2,
01637                             RELAY_PAYLOAD_SIZE-2);
01638   if (r < 0) {
01639     log_warn(LD_BUG, "Internal error; failed to establish intro point.");
01640     reason = END_CIRC_REASON_INTERNAL;
01641     goto err;
01642   }
01643   len = r;
01644   set_uint16(buf, htons((uint16_t)len));
01645   len += 2;
01646   memcpy(auth, circuit->cpath->prev->handshake_digest, DIGEST_LEN);
01647   memcpy(auth+DIGEST_LEN, "INTRODUCE", 9);
01648   if (crypto_digest(buf+len, auth, DIGEST_LEN+9))
01649     goto err;
01650   len += 20;
01651   note_crypto_pk_op(REND_SERVER);
01652   r = crypto_pk_private_sign_digest(intro_key, buf+len, sizeof(buf)-len,
01653                                     buf, len);
01654   if (r<0) {
01655     log_warn(LD_BUG, "Internal error: couldn't sign introduction request.");
01656     reason = END_CIRC_REASON_INTERNAL;
01657     goto err;
01658   }
01659   len += r;
01660 
01661   if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
01662                                    RELAY_COMMAND_ESTABLISH_INTRO,
01663                                    buf, len, circuit->cpath->prev)<0) {
01664     log_info(LD_GENERAL,
01665              "Couldn't send introduction request for service %s on circuit %d",
01666              serviceid, circuit->_base.n_circ_id);
01667     reason = END_CIRC_REASON_INTERNAL;
01668     goto err;
01669   }
01670 
01671   return;
01672  err:
01673   circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
01674 }
01675 
01679 int
01680 rend_service_intro_established(origin_circuit_t *circuit,
01681                                const uint8_t *request,
01682                                size_t request_len)
01683 {
01684   rend_service_t *service;
01685   char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
01686   (void) request;
01687   (void) request_len;
01688 
01689   if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
01690     log_warn(LD_PROTOCOL,
01691              "received INTRO_ESTABLISHED cell on non-intro circuit.");
01692     goto err;
01693   }
01694   tor_assert(circuit->rend_data);
01695   service = rend_service_get_by_pk_digest(
01696                 circuit->rend_data->rend_pk_digest);
01697   if (!service) {
01698     log_warn(LD_REND, "Unknown service on introduction circuit %d.",
01699              circuit->_base.n_circ_id);
01700     goto err;
01701   }
01702   service->desc_is_dirty = time(NULL);
01703   circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_INTRO);
01704 
01705   base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32 + 1,
01706                 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
01707   log_info(LD_REND,
01708            "Received INTRO_ESTABLISHED cell on circuit %d for service %s",
01709            circuit->_base.n_circ_id, serviceid);
01710 
01711   return 0;
01712  err:
01713   circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
01714   return -1;
01715 }
01716 
01720 void
01721 rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
01722 {
01723   rend_service_t *service;
01724   char buf[RELAY_PAYLOAD_SIZE];
01725   crypt_path_t *hop;
01726   char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
01727   char hexcookie[9];
01728   int reason;
01729 
01730   tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
01731   tor_assert(circuit->cpath);
01732   tor_assert(circuit->build_state);
01733 #ifndef NON_ANONYMOUS_MODE_ENABLED
01734   tor_assert(!(circuit->build_state->onehop_tunnel));
01735 #endif
01736   tor_assert(circuit->rend_data);
01737   hop = circuit->build_state->service_pending_final_cpath_ref->cpath;
01738 
01739   base16_encode(hexcookie,9,circuit->rend_data->rend_cookie,4);
01740   base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
01741                 circuit->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
01742 
01743   log_info(LD_REND,
01744            "Done building circuit %d to rendezvous with "
01745            "cookie %s for service %s",
01746            circuit->_base.n_circ_id, hexcookie, serviceid);
01747 
01748   /* Clear the 'in-progress HS circ has timed out' flag for
01749    * consistency with what happens on the client side; this line has
01750    * no effect on Tor's behaviour. */
01751   circuit->hs_circ_has_timed_out = 0;
01752 
01753   /* If hop is NULL, another rend circ has already connected to this
01754    * rend point.  Close this circ. */
01755   if (hop == NULL) {
01756     log_info(LD_REND, "Another rend circ has already reached this rend point; "
01757              "closing this rend circ.");
01758     reason = END_CIRC_REASON_NONE;
01759     goto err;
01760   }
01761 
01762   /* Remove our final cpath element from the reference, so that no
01763    * other circuit will try to use it.  Store it in
01764    * pending_final_cpath for now to ensure that it will be freed if
01765    * our rendezvous attempt fails. */
01766   circuit->build_state->pending_final_cpath = hop;
01767   circuit->build_state->service_pending_final_cpath_ref->cpath = NULL;
01768 
01769   service = rend_service_get_by_pk_digest(
01770                 circuit->rend_data->rend_pk_digest);
01771   if (!service) {
01772     log_warn(LD_GENERAL, "Internal error: unrecognized service ID on "
01773              "rendezvous circuit.");
01774     reason = END_CIRC_REASON_INTERNAL;
01775     goto err;
01776   }
01777 
01778   /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
01779   memcpy(buf, circuit->rend_data->rend_cookie, REND_COOKIE_LEN);
01780   if (crypto_dh_get_public(hop->dh_handshake_state,
01781                            buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
01782     log_warn(LD_GENERAL,"Couldn't get DH public key.");
01783     reason = END_CIRC_REASON_INTERNAL;
01784     goto err;
01785   }
01786   memcpy(buf+REND_COOKIE_LEN+DH_KEY_LEN, hop->handshake_digest,
01787          DIGEST_LEN);
01788 
01789   /* Send the cell */
01790   if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
01791                                    RELAY_COMMAND_RENDEZVOUS1,
01792                                    buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
01793                                    circuit->cpath->prev)<0) {
01794     log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
01795     reason = END_CIRC_REASON_INTERNAL;
01796     goto err;
01797   }
01798 
01799   crypto_dh_free(hop->dh_handshake_state);
01800   hop->dh_handshake_state = NULL;
01801 
01802   /* Append the cpath entry. */
01803   hop->state = CPATH_STATE_OPEN;
01804   /* set the windows to default. these are the windows
01805    * that bob thinks alice has.
01806    */
01807   hop->package_window = circuit_initial_package_window();
01808   hop->deliver_window = CIRCWINDOW_START;
01809 
01810   onion_append_to_cpath(&circuit->cpath, hop);
01811   circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
01812 
01813   /* Change the circuit purpose. */
01814   circuit_change_purpose(TO_CIRCUIT(circuit), CIRCUIT_PURPOSE_S_REND_JOINED);
01815 
01816   return;
01817  err:
01818   circuit_mark_for_close(TO_CIRCUIT(circuit), reason);
01819 }
01820 
01821 /*
01822  * Manage introduction points
01823  */
01824 
01830 static origin_circuit_t *
01831 find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest)
01832 {
01833   origin_circuit_t *circ = NULL;
01834 
01835   tor_assert(intro);
01836   while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
01837                                                   CIRCUIT_PURPOSE_S_INTRO))) {
01838     if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
01839                 intro->extend_info->identity_digest, DIGEST_LEN) &&
01840         circ->rend_data) {
01841       return circ;
01842     }
01843   }
01844 
01845   circ = NULL;
01846   while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
01847                                         CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
01848     if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
01849                 intro->extend_info->identity_digest, DIGEST_LEN) &&
01850         circ->rend_data) {
01851       return circ;
01852     }
01853   }
01854   return NULL;
01855 }
01856 
01859 static rend_intro_point_t *
01860 find_intro_point(origin_circuit_t *circ)
01861 {
01862   const char *serviceid;
01863   rend_service_t *service = NULL;
01864 
01865   tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
01866              TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO);
01867   tor_assert(circ->rend_data);
01868   serviceid = circ->rend_data->onion_address;
01869 
01870   SMARTLIST_FOREACH(rend_service_list, rend_service_t *, s,
01871     if (tor_memeq(s->service_id, serviceid, REND_SERVICE_ID_LEN_BASE32)) {
01872       service = s;
01873       break;
01874     });
01875 
01876   if (service == NULL) return NULL;
01877 
01878   SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro_point,
01879     if (crypto_pk_cmp_keys(intro_point->intro_key, circ->intro_key) == 0) {
01880       return intro_point;
01881     });
01882 
01883   return NULL;
01884 }
01885 
01890 static void
01891 directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
01892                          smartlist_t *descs, const char *service_id,
01893                          int seconds_valid)
01894 {
01895   int i, j, failed_upload = 0;
01896   smartlist_t *responsible_dirs = smartlist_new();
01897   smartlist_t *successful_uploads = smartlist_new();
01898   routerstatus_t *hs_dir;
01899   for (i = 0; i < smartlist_len(descs); i++) {
01900     rend_encoded_v2_service_descriptor_t *desc = smartlist_get(descs, i);
01901     /* Determine responsible dirs. */
01902     if (hid_serv_get_responsible_directories(responsible_dirs,
01903                                              desc->desc_id) < 0) {
01904       log_warn(LD_REND, "Could not determine the responsible hidden service "
01905                         "directories to post descriptors to.");
01906       smartlist_free(responsible_dirs);
01907       smartlist_free(successful_uploads);
01908       return;
01909     }
01910     for (j = 0; j < smartlist_len(responsible_dirs); j++) {
01911       char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
01912       char *hs_dir_ip;
01913       const node_t *node;
01914       hs_dir = smartlist_get(responsible_dirs, j);
01915       if (smartlist_digest_isin(renddesc->successful_uploads,
01916                                 hs_dir->identity_digest))
01917         /* Don't upload descriptor if we succeeded in doing so last time. */
01918         continue;
01919       node = node_get_by_id(hs_dir->identity_digest);
01920       if (!node || !node_has_descriptor(node)) {
01921         log_info(LD_REND, "Not launching upload for for v2 descriptor to "
01922                           "hidden service directory %s; we don't have its "
01923                           "router descriptor. Queuing for later upload.",
01924                  safe_str_client(routerstatus_describe(hs_dir)));
01925         failed_upload = -1;
01926         continue;
01927       }
01928       /* Send publish request. */
01929       directory_initiate_command_routerstatus(hs_dir,
01930                                               DIR_PURPOSE_UPLOAD_RENDDESC_V2,
01931                                               ROUTER_PURPOSE_GENERAL,
01932                                               1, NULL, desc->desc_str,
01933                                               strlen(desc->desc_str), 0);
01934       base32_encode(desc_id_base32, sizeof(desc_id_base32),
01935                     desc->desc_id, DIGEST_LEN);
01936       hs_dir_ip = tor_dup_ip(hs_dir->addr);
01937       log_info(LD_REND, "Launching upload for v2 descriptor for "
01938                         "service '%s' with descriptor ID '%s' with validity "
01939                         "of %d seconds to hidden service directory '%s' on "
01940                         "%s:%d.",
01941                safe_str_client(service_id),
01942                safe_str_client(desc_id_base32),
01943                seconds_valid,
01944                hs_dir->nickname,
01945                hs_dir_ip,
01946                hs_dir->or_port);
01947       tor_free(hs_dir_ip);
01948       /* Remember successful upload to this router for next time. */
01949       if (!smartlist_digest_isin(successful_uploads, hs_dir->identity_digest))
01950         smartlist_add(successful_uploads, hs_dir->identity_digest);
01951     }
01952     smartlist_clear(responsible_dirs);
01953   }
01954   if (!failed_upload) {
01955     if (renddesc->successful_uploads) {
01956       SMARTLIST_FOREACH(renddesc->successful_uploads, char *, c, tor_free(c););
01957       smartlist_free(renddesc->successful_uploads);
01958       renddesc->successful_uploads = NULL;
01959     }
01960     renddesc->all_uploads_performed = 1;
01961   } else {
01962     /* Remember which routers worked this time, so that we don't upload the
01963      * descriptor to them again. */
01964     if (!renddesc->successful_uploads)
01965       renddesc->successful_uploads = smartlist_new();
01966     SMARTLIST_FOREACH(successful_uploads, const char *, c, {
01967       if (!smartlist_digest_isin(renddesc->successful_uploads, c)) {
01968         char *hsdir_id = tor_memdup(c, DIGEST_LEN);
01969         smartlist_add(renddesc->successful_uploads, hsdir_id);
01970       }
01971     });
01972   }
01973   smartlist_free(responsible_dirs);
01974   smartlist_free(successful_uploads);
01975 }
01976 
01980 static void
01981 upload_service_descriptor(rend_service_t *service)
01982 {
01983   time_t now = time(NULL);
01984   int rendpostperiod;
01985   char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
01986   int uploaded = 0;
01987 
01988   rendpostperiod = get_options()->RendPostPeriod;
01989 
01990   /* Upload descriptor? */
01991   if (get_options()->PublishHidServDescriptors) {
01992     networkstatus_t *c = networkstatus_get_latest_consensus();
01993     if (c && smartlist_len(c->routerstatus_list) > 0) {
01994       int seconds_valid, i, j, num_descs;
01995       smartlist_t *descs = smartlist_new();
01996       smartlist_t *client_cookies = smartlist_new();
01997       /* Either upload a single descriptor (including replicas) or one
01998        * descriptor for each authorized client in case of authorization
01999        * type 'stealth'. */
02000       num_descs = service->auth_type == REND_STEALTH_AUTH ?
02001                       smartlist_len(service->clients) : 1;
02002       for (j = 0; j < num_descs; j++) {
02003         crypto_pk_t *client_key = NULL;
02004         rend_authorized_client_t *client = NULL;
02005         smartlist_clear(client_cookies);
02006         switch (service->auth_type) {
02007           case REND_NO_AUTH:
02008             /* Do nothing here. */
02009             break;
02010           case REND_BASIC_AUTH:
02011             SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *,
02012                 cl, smartlist_add(client_cookies, cl->descriptor_cookie));
02013             break;
02014           case REND_STEALTH_AUTH:
02015             client = smartlist_get(service->clients, j);
02016             client_key = client->client_key;
02017             smartlist_add(client_cookies, client->descriptor_cookie);
02018             break;
02019         }
02020         /* Encode the current descriptor. */
02021         seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
02022                                                    now, 0,
02023                                                    service->auth_type,
02024                                                    client_key,
02025                                                    client_cookies);
02026         if (seconds_valid < 0) {
02027           log_warn(LD_BUG, "Internal error: couldn't encode service "
02028                    "descriptor; not uploading.");
02029           smartlist_free(descs);
02030           smartlist_free(client_cookies);
02031           return;
02032         }
02033         /* Post the current descriptors to the hidden service directories. */
02034         rend_get_service_id(service->desc->pk, serviceid);
02035         log_info(LD_REND, "Launching upload for hidden service %s",
02036                      serviceid);
02037         directory_post_to_hs_dir(service->desc, descs, serviceid,
02038                                  seconds_valid);
02039         /* Free memory for descriptors. */
02040         for (i = 0; i < smartlist_len(descs); i++)
02041           rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
02042         smartlist_clear(descs);
02043         /* Update next upload time. */
02044         if (seconds_valid - REND_TIME_PERIOD_OVERLAPPING_V2_DESCS
02045             > rendpostperiod)
02046           service->next_upload_time = now + rendpostperiod;
02047         else if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS)
02048           service->next_upload_time = now + seconds_valid + 1;
02049         else
02050           service->next_upload_time = now + seconds_valid -
02051               REND_TIME_PERIOD_OVERLAPPING_V2_DESCS + 1;
02052         /* Post also the next descriptors, if necessary. */
02053         if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS) {
02054           seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
02055                                                      now, 1,
02056                                                      service->auth_type,
02057                                                      client_key,
02058                                                      client_cookies);
02059           if (seconds_valid < 0) {
02060             log_warn(LD_BUG, "Internal error: couldn't encode service "
02061                      "descriptor; not uploading.");
02062             smartlist_free(descs);
02063             smartlist_free(client_cookies);
02064             return;
02065           }
02066           directory_post_to_hs_dir(service->desc, descs, serviceid,
02067                                    seconds_valid);
02068           /* Free memory for descriptors. */
02069           for (i = 0; i < smartlist_len(descs); i++)
02070             rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
02071           smartlist_clear(descs);
02072         }
02073       }
02074       smartlist_free(descs);
02075       smartlist_free(client_cookies);
02076       uploaded = 1;
02077       log_info(LD_REND, "Successfully uploaded v2 rend descriptors!");
02078     }
02079   }
02080 
02081   /* If not uploaded, try again in one minute. */
02082   if (!uploaded)
02083     service->next_upload_time = now + 60;
02084 
02085   /* Unmark dirty flag of this service. */
02086   service->desc_is_dirty = 0;
02087 }
02088 
02091 static int
02092 intro_point_accepted_intro_count(rend_intro_point_t *intro)
02093 {
02094   if (intro->accepted_intro_rsa_parts == NULL) {
02095     return 0;
02096   } else {
02097     return digestmap_size(intro->accepted_intro_rsa_parts);
02098   }
02099 }
02100 
02104 static int
02105 intro_point_should_expire_now(rend_intro_point_t *intro,
02106                               time_t now)
02107 {
02108   tor_assert(intro != NULL);
02109 
02110   if (intro->time_published == -1) {
02111     /* Don't expire an intro point if we haven't even published it yet. */
02112     return 0;
02113   }
02114 
02115   if (intro->time_expiring != -1) {
02116     /* We've already started expiring this intro point.  *Don't* let
02117      * this function's result 'flap'. */
02118     return 1;
02119   }
02120 
02121   if (intro_point_accepted_intro_count(intro) >=
02122       INTRO_POINT_LIFETIME_INTRODUCTIONS) {
02123     /* This intro point has been used too many times.  Expire it now. */
02124     return 1;
02125   }
02126 
02127   if (intro->time_to_expire == -1) {
02128     /* This intro point has been published, but we haven't picked an
02129      * expiration time for it.  Pick one now. */
02130     int intro_point_lifetime_seconds =
02131       INTRO_POINT_LIFETIME_MIN_SECONDS +
02132       crypto_rand_int(INTRO_POINT_LIFETIME_MAX_SECONDS -
02133                       INTRO_POINT_LIFETIME_MIN_SECONDS);
02134 
02135     /* Start the expiration timer now, rather than when the intro
02136      * point was first published.  There shouldn't be much of a time
02137      * difference. */
02138     intro->time_to_expire = now + intro_point_lifetime_seconds;
02139 
02140     return 0;
02141   }
02142 
02143   /* This intro point has a time to expire set already.  Use it. */
02144   return (now >= intro->time_to_expire);
02145 }
02146 
02151 void
02152 rend_services_introduce(void)
02153 {
02154   int i,j,r;
02155   const node_t *node;
02156   rend_service_t *service;
02157   rend_intro_point_t *intro;
02158   int intro_point_set_changed, prev_intro_nodes;
02159   unsigned int n_intro_points_unexpired;
02160   unsigned int n_intro_points_to_open;
02161   smartlist_t *intro_nodes;
02162   time_t now;
02163   const or_options_t *options = get_options();
02164 
02165   intro_nodes = smartlist_new();
02166   now = time(NULL);
02167 
02168   for (i=0; i < smartlist_len(rend_service_list); ++i) {
02169     smartlist_clear(intro_nodes);
02170     service = smartlist_get(rend_service_list, i);
02171 
02172     tor_assert(service);
02173 
02174     /* intro_point_set_changed becomes non-zero iff the set of intro
02175      * points to be published in service's descriptor has changed. */
02176     intro_point_set_changed = 0;
02177 
02178     /* n_intro_points_unexpired collects the number of non-expiring
02179      * intro points we have, so that we know how many new intro
02180      * circuits we need to launch for this service. */
02181     n_intro_points_unexpired = 0;
02182 
02183     if (now > service->intro_period_started+INTRO_CIRC_RETRY_PERIOD) {
02184       /* One period has elapsed; we can try building circuits again. */
02185       service->intro_period_started = now;
02186       service->n_intro_circuits_launched = 0;
02187     } else if (service->n_intro_circuits_launched >=
02188                MAX_INTRO_CIRCS_PER_PERIOD) {
02189       /* We have failed too many times in this period; wait for the next
02190        * one before we try again. */
02191       continue;
02192     }
02193 
02194     /* Find out which introduction points we have in progress for this
02195        service. */
02196     SMARTLIST_FOREACH_BEGIN(service->intro_nodes, rend_intro_point_t *,
02197                             intro) {
02198       origin_circuit_t *intro_circ =
02199         find_intro_circuit(intro, service->pk_digest);
02200 
02201       if (intro->time_expiring + INTRO_POINT_EXPIRATION_GRACE_PERIOD > now) {
02202         /* This intro point has completely expired.  Remove it, and
02203          * mark the circuit for close if it's still alive. */
02204         if (intro_circ != NULL) {
02205           circuit_mark_for_close(TO_CIRCUIT(intro_circ),
02206                                  END_CIRC_REASON_FINISHED);
02207         }
02208         rend_intro_point_free(intro);
02209         intro = NULL; /* SMARTLIST_DEL_CURRENT takes a name, not a value. */
02210         SMARTLIST_DEL_CURRENT(service->intro_nodes, intro);
02211         /* We don't need to set intro_point_set_changed here, because
02212          * this intro point wouldn't have been published in a current
02213          * descriptor anyway. */
02214         continue;
02215       }
02216 
02217       node = node_get_by_id(intro->extend_info->identity_digest);
02218       if (!node || !intro_circ) {
02219         int removing_this_intro_point_changes_the_intro_point_set = 1;
02220         log_info(LD_REND, "Giving up on %s as intro point for %s"
02221                  " (circuit disappeared).",
02222                  safe_str_client(extend_info_describe(intro->extend_info)),
02223                  safe_str_client(service->service_id));
02224         rend_service_note_removing_intro_point(service, intro);
02225         if (intro->time_expiring != -1) {
02226           log_info(LD_REND, "We were already expiring the intro point; "
02227                    "no need to mark the HS descriptor as dirty over this.");
02228           removing_this_intro_point_changes_the_intro_point_set = 0;
02229         } else if (intro->listed_in_last_desc) {
02230           log_info(LD_REND, "The intro point we are giving up on was "
02231                    "included in the last published descriptor. "
02232                    "Marking current descriptor as dirty.");
02233           service->desc_is_dirty = now;
02234         }
02235         rend_intro_point_free(intro);
02236         intro = NULL; /* SMARTLIST_DEL_CURRENT takes a name, not a value. */
02237         SMARTLIST_DEL_CURRENT(service->intro_nodes, intro);
02238         if (removing_this_intro_point_changes_the_intro_point_set)
02239           intro_point_set_changed = 1;
02240       }
02241 
02242       if (intro != NULL && intro_point_should_expire_now(intro, now)) {
02243         log_info(LD_REND, "Expiring %s as intro point for %s.",
02244                  safe_str_client(extend_info_describe(intro->extend_info)),
02245                  safe_str_client(service->service_id));
02246 
02247         rend_service_note_removing_intro_point(service, intro);
02248 
02249         /* The polite (and generally Right) way to expire an intro
02250          * point is to establish a new one to replace it, publish a
02251          * new descriptor that doesn't list any expiring intro points,
02252          * and *then*, once our upload attempts for the new descriptor
02253          * have ended (whether in success or failure), close the
02254          * expiring intro points.
02255          *
02256          * Unfortunately, we can't find out when the new descriptor
02257          * has actually been uploaded, so we'll have to settle for a
02258          * five-minute timer.  Start it.  XXXX024 This sucks. */
02259         intro->time_expiring = now;
02260 
02261         intro_point_set_changed = 1;
02262       }
02263 
02264       if (intro != NULL && intro->time_expiring == -1)
02265         ++n_intro_points_unexpired;
02266 
02267       if (node)
02268         smartlist_add(intro_nodes, (void*)node);
02269     } SMARTLIST_FOREACH_END(intro);
02270 
02271     if (!intro_point_set_changed &&
02272         (n_intro_points_unexpired >= service->n_intro_points_wanted)) {
02273       continue;
02274     }
02275 
02276     /* Remember how many introduction circuits we started with.
02277      *
02278      * prev_intro_nodes serves a different purpose than
02279      * n_intro_points_unexpired -- this variable tells us where our
02280      * previously-created intro points end and our new ones begin in
02281      * the intro-point list, so we don't have to launch the circuits
02282      * at the same time as we create the intro points they correspond
02283      * to.  XXXX This is daft. */
02284     prev_intro_nodes = smartlist_len(service->intro_nodes);
02285 
02286     /* We have enough directory information to start establishing our
02287      * intro points. We want to end up with n_intro_points_wanted
02288      * intro points, but if we're just starting, we launch two extra
02289      * circuits and use the first n_intro_points_wanted that complete.
02290      *
02291      * The ones after the first three will be converted to 'general'
02292      * internal circuits in rend_service_intro_has_opened(), and then
02293      * we'll drop them from the list of intro points next time we
02294      * go through the above "find out which introduction points we have
02295      * in progress" loop. */
02296     n_intro_points_to_open = (service->n_intro_points_wanted +
02297                               (prev_intro_nodes == 0 ? 2 : 0));
02298     for (j = (int)n_intro_points_unexpired;
02299          j < (int)n_intro_points_to_open;
02300          ++j) { /* XXXX remove casts */
02301       router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
02302       if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
02303         flags |= CRN_ALLOW_INVALID;
02304       node = router_choose_random_node(intro_nodes,
02305                                        options->ExcludeNodes, flags);
02306       if (!node) {
02307         log_warn(LD_REND,
02308                  "Could only establish %d introduction points for %s; "
02309                  "wanted %u.",
02310                  smartlist_len(service->intro_nodes), service->service_id,
02311                  n_intro_points_to_open);
02312         break;
02313       }
02314       intro_point_set_changed = 1;
02315       smartlist_add(intro_nodes, (void*)node);
02316       intro = tor_malloc_zero(sizeof(rend_intro_point_t));
02317       intro->extend_info = extend_info_from_node(node, 0);
02318       intro->intro_key = crypto_pk_new();
02319       tor_assert(!crypto_pk_generate_key(intro->intro_key));
02320       intro->time_published = -1;
02321       intro->time_to_expire = -1;
02322       intro->time_expiring = -1;
02323       smartlist_add(service->intro_nodes, intro);
02324       log_info(LD_REND, "Picked router %s as an intro point for %s.",
02325                safe_str_client(node_describe(node)),
02326                safe_str_client(service->service_id));
02327     }
02328 
02329     /* If there's no need to launch new circuits, stop here. */
02330     if (!intro_point_set_changed)
02331       continue;
02332 
02333     /* Establish new introduction points. */
02334     for (j=prev_intro_nodes; j < smartlist_len(service->intro_nodes); ++j) {
02335       intro = smartlist_get(service->intro_nodes, j);
02336       r = rend_service_launch_establish_intro(service, intro);
02337       if (r<0) {
02338         log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
02339                  safe_str_client(extend_info_describe(intro->extend_info)),
02340                  safe_str_client(service->service_id));
02341       }
02342     }
02343   }
02344   smartlist_free(intro_nodes);
02345 }
02346 
02355 void
02356 rend_consider_services_upload(time_t now)
02357 {
02358   int i;
02359   rend_service_t *service;
02360   int rendpostperiod = get_options()->RendPostPeriod;
02361 
02362   if (!get_options()->PublishHidServDescriptors)
02363     return;
02364 
02365   for (i=0; i < smartlist_len(rend_service_list); ++i) {
02366     service = smartlist_get(rend_service_list, i);
02367     if (!service->next_upload_time) { /* never been uploaded yet */
02368       /* The fixed lower bound of 30 seconds ensures that the descriptor
02369        * is stable before being published. See comment below. */
02370       service->next_upload_time =
02371         now + 30 + crypto_rand_int(2*rendpostperiod);
02372     }
02373     if (service->next_upload_time < now ||
02374         (service->desc_is_dirty &&
02375          service->desc_is_dirty < now-30)) {
02376       /* if it's time, or if the directory servers have a wrong service
02377        * descriptor and ours has been stable for 30 seconds, upload a
02378        * new one of each format. */
02379       rend_service_update_descriptor(service);
02380       upload_service_descriptor(service);
02381     }
02382   }
02383 }
02384 
02388 static int consider_republishing_rend_descriptors = 1;
02389 
02393 void
02394 rend_hsdir_routers_changed(void)
02395 {
02396   consider_republishing_rend_descriptors = 1;
02397 }
02398 
02402 void
02403 rend_consider_descriptor_republication(void)
02404 {
02405   int i;
02406   rend_service_t *service;
02407 
02408   if (!consider_republishing_rend_descriptors)
02409     return;
02410   consider_republishing_rend_descriptors = 0;
02411 
02412   if (!get_options()->PublishHidServDescriptors)
02413     return;
02414 
02415   for (i=0; i < smartlist_len(rend_service_list); ++i) {
02416     service = smartlist_get(rend_service_list, i);
02417     if (service->desc && !service->desc->all_uploads_performed) {
02418       /* If we failed in uploading a descriptor last time, try again *without*
02419        * updating the descriptor's contents. */
02420       upload_service_descriptor(service);
02421     }
02422   }
02423 }
02424 
02428 void
02429 rend_service_dump_stats(int severity)
02430 {
02431   int i,j;
02432   rend_service_t *service;
02433   rend_intro_point_t *intro;
02434   const char *safe_name;
02435   origin_circuit_t *circ;
02436 
02437   for (i=0; i < smartlist_len(rend_service_list); ++i) {
02438     service = smartlist_get(rend_service_list, i);
02439     log(severity, LD_GENERAL, "Service configured in \"%s\":",
02440         service->directory);
02441     for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
02442       intro = smartlist_get(service->intro_nodes, j);
02443       safe_name = safe_str_client(intro->extend_info->nickname);
02444 
02445       circ = find_intro_circuit(intro, service->pk_digest);
02446       if (!circ) {
02447         log(severity, LD_GENERAL, "  Intro point %d at %s: no circuit",
02448             j, safe_name);
02449         continue;
02450       }
02451       log(severity, LD_GENERAL, "  Intro point %d at %s: circuit is %s",
02452           j, safe_name, circuit_state_to_string(circ->_base.state));
02453     }
02454   }
02455 }
02456 
02462 int
02463 rend_service_set_connection_addr_port(edge_connection_t *conn,
02464                                       origin_circuit_t *circ)
02465 {
02466   rend_service_t *service;
02467   char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
02468   smartlist_t *matching_ports;
02469   rend_service_port_config_t *chosen_port;
02470 
02471   tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
02472   tor_assert(circ->rend_data);
02473   log_debug(LD_REND,"beginning to hunt for addr/port");
02474   base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
02475                 circ->rend_data->rend_pk_digest, REND_SERVICE_ID_LEN);
02476   service = rend_service_get_by_pk_digest(
02477                 circ->rend_data->rend_pk_digest);
02478   if (!service) {
02479     log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
02480              "rendezvous circuit %d; closing.",
02481              serviceid, circ->_base.n_circ_id);
02482     return -1;
02483   }
02484   matching_ports = smartlist_new();
02485   SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
02486   {
02487     if (conn->_base.port == p->virtual_port) {
02488       smartlist_add(matching_ports, p);
02489     }
02490   });
02491   chosen_port = smartlist_choose(matching_ports);
02492   smartlist_free(matching_ports);
02493   if (chosen_port) {
02494     tor_addr_copy(&conn->_base.addr, &chosen_port->real_addr);
02495     conn->_base.port = chosen_port->real_port;
02496     return 0;
02497   }
02498   log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
02499            conn->_base.port,serviceid);
02500   return -1;
02501 }
02502