Back to index

tor  0.2.3.18-rc
dirserv.c
Go to the documentation of this file.
00001 /* Copyright (c) 2001-2004, Roger Dingledine.
00002  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00003  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00004 /* See LICENSE for licensing information */
00005 
00006 #define DIRSERV_PRIVATE
00007 #include "or.h"
00008 #include "buffers.h"
00009 #include "config.h"
00010 #include "connection.h"
00011 #include "connection_or.h"
00012 #include "control.h"
00013 #include "directory.h"
00014 #include "dirserv.h"
00015 #include "dirvote.h"
00016 #include "hibernate.h"
00017 #include "microdesc.h"
00018 #include "networkstatus.h"
00019 #include "nodelist.h"
00020 #include "policies.h"
00021 #include "rephist.h"
00022 #include "router.h"
00023 #include "routerlist.h"
00024 #include "routerparse.h"
00025 
00033 #define ROUTER_ALLOW_SKEW (60*60*12)
00034 
00035 #define DIR_REGEN_SLACK_TIME 30
00036 
00038 #define MAX_UNTRUSTED_NETWORKSTATUSES 16
00039 
00041 #define MAX_V1_DIRECTORY_AGE (30*24*60*60)
00042 
00043 #define MAX_V1_RR_AGE (7*24*60*60)
00044 
00045 extern time_t time_of_process_start; /* from main.c */
00046 
00047 extern long stats_n_seconds_working; /* from main.c */
00048 
00050 static time_t the_directory_is_dirty = 1;
00053 static time_t runningrouters_is_dirty = 1;
00056 static time_t the_v2_networkstatus_is_dirty = 1;
00057 
00060 static cached_dir_t *the_directory = NULL;
00061 
00063 static cached_dir_t the_runningrouters;
00064 
00065 static void directory_remove_invalid(void);
00066 static cached_dir_t *dirserv_regenerate_directory(void);
00067 static char *format_versions_list(config_line_t *ln);
00068 struct authdir_config_t;
00069 static int add_fingerprint_to_dir(const char *nickname, const char *fp,
00070                                   struct authdir_config_t *list);
00071 static uint32_t
00072 dirserv_get_status_impl(const char *fp, const char *nickname,
00073                         const char *address,
00074                         uint32_t addr, uint16_t or_port,
00075                         const char *platform, const char *contact,
00076                         const char **msg, int should_log);
00077 static void clear_cached_dir(cached_dir_t *d);
00078 static const signed_descriptor_t *get_signed_descriptor_by_fp(
00079                                                         const char *fp,
00080                                                         int extrainfo,
00081                                                         time_t publish_cutoff);
00082 static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
00083 
00084 /************** Measured Bandwidth parsing code ******/
00085 #define MAX_MEASUREMENT_AGE (3*24*60*60) /* 3 days */
00086 
00087 /************** Fingerprint handling code ************/
00088 
00089 #define FP_NAMED   1  
00090 #define FP_INVALID 2  
00091 #define FP_REJECT  4  
00092 #define FP_BADDIR  8  
00093 #define FP_BADEXIT 16 
00094 #define FP_UNNAMED 32 
00098 typedef struct router_status_t {
00099   char nickname[MAX_NICKNAME_LEN+1];
00100   uint32_t status;
00101 } router_status_t;
00102 
00105 typedef struct authdir_config_t {
00106   strmap_t *fp_by_name; 
00107   digestmap_t *status_by_digest; 
00108 } authdir_config_t;
00109 
00111 static authdir_config_t *fingerprint_list = NULL;
00112 
00114 static authdir_config_t *
00115 authdir_config_new(void)
00116 {
00117   authdir_config_t *list = tor_malloc_zero(sizeof(authdir_config_t));
00118   list->fp_by_name = strmap_new();
00119   list->status_by_digest = digestmap_new();
00120   return list;
00121 }
00122 
00127 /* static */ int
00128 add_fingerprint_to_dir(const char *nickname, const char *fp,
00129                        authdir_config_t *list)
00130 {
00131   char *fingerprint;
00132   char d[DIGEST_LEN];
00133   router_status_t *status;
00134   tor_assert(nickname);
00135   tor_assert(fp);
00136   tor_assert(list);
00137 
00138   fingerprint = tor_strdup(fp);
00139   tor_strstrip(fingerprint, " ");
00140   if (base16_decode(d, DIGEST_LEN, fingerprint, strlen(fingerprint))) {
00141     log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"",
00142              escaped(fp));
00143     tor_free(fingerprint);
00144     return 0;
00145   }
00146 
00147   if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME)) {
00148     log_warn(LD_DIRSERV, "Tried to add a mapping for reserved nickname %s",
00149              UNNAMED_ROUTER_NICKNAME);
00150     tor_free(fingerprint);
00151     return 0;
00152   }
00153 
00154   status = digestmap_get(list->status_by_digest, d);
00155   if (!status) {
00156     status = tor_malloc_zero(sizeof(router_status_t));
00157     digestmap_set(list->status_by_digest, d, status);
00158   }
00159 
00160   if (nickname[0] != '!') {
00161     char *old_fp = strmap_get_lc(list->fp_by_name, nickname);
00162     if (old_fp && !strcasecmp(fingerprint, old_fp)) {
00163       tor_free(fingerprint);
00164     } else {
00165       tor_free(old_fp);
00166       strmap_set_lc(list->fp_by_name, nickname, fingerprint);
00167     }
00168     status->status |= FP_NAMED;
00169     strlcpy(status->nickname, nickname, sizeof(status->nickname));
00170   } else {
00171     tor_free(fingerprint);
00172     if (!strcasecmp(nickname, "!reject")) {
00173       status->status |= FP_REJECT;
00174     } else if (!strcasecmp(nickname, "!invalid")) {
00175       status->status |= FP_INVALID;
00176     } else if (!strcasecmp(nickname, "!baddir")) {
00177       status->status |= FP_BADDIR;
00178     } else if (!strcasecmp(nickname, "!badexit")) {
00179       status->status |= FP_BADEXIT;
00180     }
00181   }
00182   return 0;
00183 }
00184 
00187 int
00188 dirserv_add_own_fingerprint(const char *nickname, crypto_pk_t *pk)
00189 {
00190   char fp[FINGERPRINT_LEN+1];
00191   if (crypto_pk_get_fingerprint(pk, fp, 0)<0) {
00192     log_err(LD_BUG, "Error computing fingerprint");
00193     return -1;
00194   }
00195   if (!fingerprint_list)
00196     fingerprint_list = authdir_config_new();
00197   add_fingerprint_to_dir(nickname, fp, fingerprint_list);
00198   return 0;
00199 }
00200 
00206 int
00207 dirserv_load_fingerprint_file(void)
00208 {
00209   char *fname;
00210   char *cf;
00211   char *nickname, *fingerprint;
00212   authdir_config_t *fingerprint_list_new;
00213   int result;
00214   config_line_t *front=NULL, *list;
00215   const or_options_t *options = get_options();
00216 
00217   fname = get_datadir_fname("approved-routers");
00218   log_info(LD_GENERAL,
00219            "Reloading approved fingerprints from \"%s\"...", fname);
00220 
00221   cf = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
00222   if (!cf) {
00223     if (options->NamingAuthoritativeDir) {
00224       log_warn(LD_FS, "Cannot open fingerprint file '%s'. Failing.", fname);
00225       tor_free(fname);
00226       return -1;
00227     } else {
00228       log_info(LD_FS, "Cannot open fingerprint file '%s'. That's ok.", fname);
00229       tor_free(fname);
00230       return 0;
00231     }
00232   }
00233   tor_free(fname);
00234 
00235   result = config_get_lines(cf, &front, 0);
00236   tor_free(cf);
00237   if (result < 0) {
00238     log_warn(LD_CONFIG, "Error reading from fingerprint file");
00239     return -1;
00240   }
00241 
00242   fingerprint_list_new = authdir_config_new();
00243 
00244   for (list=front; list; list=list->next) {
00245     char digest_tmp[DIGEST_LEN];
00246     nickname = list->key; fingerprint = list->value;
00247     if (strlen(nickname) > MAX_NICKNAME_LEN) {
00248       log_notice(LD_CONFIG,
00249                  "Nickname '%s' too long in fingerprint file. Skipping.",
00250                  nickname);
00251       continue;
00252     }
00253     if (!is_legal_nickname(nickname) &&
00254         strcasecmp(nickname, "!reject") &&
00255         strcasecmp(nickname, "!invalid") &&
00256         strcasecmp(nickname, "!badexit")) {
00257       log_notice(LD_CONFIG,
00258                  "Invalid nickname '%s' in fingerprint file. Skipping.",
00259                  nickname);
00260       continue;
00261     }
00262     tor_strstrip(fingerprint, " "); /* remove spaces */
00263     if (strlen(fingerprint) != HEX_DIGEST_LEN ||
00264         base16_decode(digest_tmp, sizeof(digest_tmp),
00265                       fingerprint, HEX_DIGEST_LEN) < 0) {
00266       log_notice(LD_CONFIG,
00267                  "Invalid fingerprint (nickname '%s', "
00268                  "fingerprint %s). Skipping.",
00269                  nickname, fingerprint);
00270       continue;
00271     }
00272     if (0==strcasecmp(nickname, DEFAULT_CLIENT_NICKNAME)) {
00273       /* If you approved an OR called "client", then clients who use
00274        * the default nickname could all be rejected.  That's no good. */
00275       log_notice(LD_CONFIG,
00276                  "Authorizing nickname '%s' would break "
00277                  "many clients; skipping.",
00278                  DEFAULT_CLIENT_NICKNAME);
00279       continue;
00280     }
00281     if (0==strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME)) {
00282       /* If you approved an OR called "unnamed", then clients will be
00283        * confused. */
00284       log_notice(LD_CONFIG,
00285                  "Authorizing nickname '%s' is not allowed; skipping.",
00286                  UNNAMED_ROUTER_NICKNAME);
00287       continue;
00288     }
00289     if (add_fingerprint_to_dir(nickname, fingerprint, fingerprint_list_new)
00290         != 0)
00291       log_notice(LD_CONFIG, "Duplicate nickname '%s'.", nickname);
00292   }
00293 
00294   config_free_lines(front);
00295   dirserv_free_fingerprint_list();
00296   fingerprint_list = fingerprint_list_new;
00297   /* Delete any routers whose fingerprints we no longer recognize */
00298   directory_remove_invalid();
00299   return 0;
00300 }
00301 
00308 uint32_t
00309 dirserv_router_get_status(const routerinfo_t *router, const char **msg)
00310 {
00311   char d[DIGEST_LEN];
00312 
00313   if (crypto_pk_get_digest(router->identity_pkey, d)) {
00314     log_warn(LD_BUG,"Error computing fingerprint");
00315     if (msg)
00316       *msg = "Bug: Error computing fingerprint";
00317     return FP_REJECT;
00318   }
00319 
00320   return dirserv_get_status_impl(d, router->nickname,
00321                                  router->address,
00322                                  router->addr, router->or_port,
00323                                  router->platform, router->contact_info,
00324                                  msg, 1);
00325 }
00326 
00329 int
00330 dirserv_would_reject_router(const routerstatus_t *rs)
00331 {
00332   uint32_t res;
00333 
00334   res = dirserv_get_status_impl(rs->identity_digest, rs->nickname,
00335                                 "", /* address is only used in logs */
00336                                 rs->addr, rs->or_port,
00337                                 NULL, NULL,
00338                                 NULL, 0);
00339 
00340   return (res & FP_REJECT) != 0;
00341 }
00342 
00346 static uint32_t
00347 dirserv_get_name_status(const char *id_digest, const char *nickname)
00348 {
00349   char fp[HEX_DIGEST_LEN+1];
00350   char *fp_by_name;
00351 
00352   base16_encode(fp, sizeof(fp), id_digest, DIGEST_LEN);
00353 
00354   if ((fp_by_name =
00355        strmap_get_lc(fingerprint_list->fp_by_name, nickname))) {
00356     if (!strcasecmp(fp, fp_by_name)) {
00357       return FP_NAMED;
00358     } else {
00359       return FP_UNNAMED; /* Wrong fingerprint. */
00360     }
00361   }
00362   return 0;
00363 }
00364 
00372 static uint32_t
00373 dirserv_get_status_impl(const char *id_digest, const char *nickname,
00374                         const char *address,
00375                         uint32_t addr, uint16_t or_port,
00376                         const char *platform, const char *contact,
00377                         const char **msg, int should_log)
00378 {
00379   int reject_unlisted = get_options()->AuthDirRejectUnlisted;
00380   uint32_t result;
00381   router_status_t *status_by_digest;
00382 
00383   if (!fingerprint_list)
00384     fingerprint_list = authdir_config_new();
00385 
00386   if (should_log)
00387     log_debug(LD_DIRSERV, "%d fingerprints, %d digests known.",
00388               strmap_size(fingerprint_list->fp_by_name),
00389               digestmap_size(fingerprint_list->status_by_digest));
00390 
00391   /* Versions before Tor 0.2.1.30 have known security issues that
00392    * make them unsuitable for the current network. */
00393   if (platform && !tor_version_as_new_as(platform,"0.2.1.30")) {
00394     if (msg)
00395       *msg = "Tor version is insecure. Please upgrade!";
00396     return FP_REJECT;
00397   } else if (platform && tor_version_as_new_as(platform,"0.2.2.1-alpha")) {
00398     /* Versions from 0.2.2.1-alpha...0.2.2.20-alpha have known security
00399      * issues that make them unusable for the current network */
00400     if (!tor_version_as_new_as(platform, "0.2.2.21-alpha")) {
00401       if (msg)
00402         *msg = "Tor version is insecure. Please upgrade!";
00403       return FP_REJECT;
00404     }
00405   }
00406 
00407   result = dirserv_get_name_status(id_digest, nickname);
00408   if (result & FP_NAMED) {
00409     if (should_log)
00410       log_debug(LD_DIRSERV,"Good fingerprint for '%s'",nickname);
00411   }
00412   if (result & FP_UNNAMED) {
00413     if (should_log) {
00414       char *esc_contact = esc_for_log(contact);
00415       log_info(LD_DIRSERV,
00416                "Mismatched fingerprint for '%s'. "
00417                "ContactInfo '%s', platform '%s'.)",
00418                nickname,
00419                esc_contact,
00420                platform ? escaped(platform) : "");
00421       tor_free(esc_contact);
00422     }
00423     if (msg)
00424       *msg = "Rejected: There is already a named server with this nickname "
00425         "and a different fingerprint.";
00426   }
00427 
00428   status_by_digest = digestmap_get(fingerprint_list->status_by_digest,
00429                                    id_digest);
00430   if (status_by_digest)
00431     result |= (status_by_digest->status & ~FP_NAMED);
00432 
00433   if (result & FP_REJECT) {
00434     if (msg)
00435       *msg = "Fingerprint is marked rejected";
00436     return FP_REJECT;
00437   } else if (result & FP_INVALID) {
00438     if (msg)
00439       *msg = "Fingerprint is marked invalid";
00440   }
00441 
00442   if (authdir_policy_baddir_address(addr, or_port)) {
00443     if (should_log)
00444       log_info(LD_DIRSERV,
00445                "Marking '%s' as bad directory because of address '%s'",
00446                nickname, address);
00447     result |= FP_BADDIR;
00448   }
00449 
00450   if (authdir_policy_badexit_address(addr, or_port)) {
00451     if (should_log)
00452       log_info(LD_DIRSERV, "Marking '%s' as bad exit because of address '%s'",
00453                nickname, address);
00454     result |= FP_BADEXIT;
00455   }
00456 
00457   if (!(result & FP_NAMED)) {
00458     if (!authdir_policy_permits_address(addr, or_port)) {
00459       if (should_log)
00460         log_info(LD_DIRSERV, "Rejecting '%s' because of address '%s'",
00461                  nickname, address);
00462       if (msg)
00463         *msg = "Authdir is rejecting routers in this range.";
00464       return FP_REJECT;
00465     }
00466     if (!authdir_policy_valid_address(addr, or_port)) {
00467       if (should_log)
00468         log_info(LD_DIRSERV, "Not marking '%s' valid because of address '%s'",
00469                  nickname, address);
00470       result |= FP_INVALID;
00471     }
00472     if (reject_unlisted) {
00473       if (msg)
00474         *msg = "Authdir rejects unknown routers.";
00475       return FP_REJECT;
00476     }
00477   }
00478 
00479   return result;
00480 }
00481 
00485 const char *
00486 dirserv_get_nickname_by_digest(const char *digest)
00487 {
00488   router_status_t *status;
00489   if (!fingerprint_list)
00490     return NULL;
00491   tor_assert(digest);
00492 
00493   status = digestmap_get(fingerprint_list->status_by_digest, digest);
00494   return status ? status->nickname : NULL;
00495 }
00496 
00498 void
00499 dirserv_free_fingerprint_list(void)
00500 {
00501   if (!fingerprint_list)
00502     return;
00503 
00504   strmap_free(fingerprint_list->fp_by_name, _tor_free);
00505   digestmap_free(fingerprint_list->status_by_digest, _tor_free);
00506   tor_free(fingerprint_list);
00507 }
00508 
00509 /*
00510  *    Descriptor list
00511  */
00512 
00515 static int
00516 dirserv_router_has_valid_address(routerinfo_t *ri)
00517 {
00518   struct in_addr iaddr;
00519   if (get_options()->DirAllowPrivateAddresses)
00520     return 0; /* whatever it is, we're fine with it */
00521   if (!tor_inet_aton(ri->address, &iaddr)) {
00522     log_info(LD_DIRSERV,"Router %s published non-IP address '%s'. Refusing.",
00523              router_describe(ri),
00524              ri->address);
00525     return -1;
00526   }
00527   if (is_internal_IP(ntohl(iaddr.s_addr), 0)) {
00528     log_info(LD_DIRSERV,
00529              "Router %s published internal IP address '%s'. Refusing.",
00530              router_describe(ri), ri->address);
00531     return -1; /* it's a private IP, we should reject it */
00532   }
00533   return 0;
00534 }
00535 
00544 int
00545 authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
00546                                int complain, int *valid_out)
00547 {
00548   /* Okay.  Now check whether the fingerprint is recognized. */
00549   uint32_t status = dirserv_router_get_status(ri, msg);
00550   time_t now;
00551   int severity = (complain && ri->contact_info) ? LOG_NOTICE : LOG_INFO;
00552   tor_assert(msg);
00553   if (status & FP_REJECT)
00554     return -1; /* msg is already set. */
00555 
00556   /* Is there too much clock skew? */
00557   now = time(NULL);
00558   if (ri->cache_info.published_on > now+ROUTER_ALLOW_SKEW) {
00559     log_fn(severity, LD_DIRSERV, "Publication time for %s is too "
00560            "far (%d minutes) in the future; possible clock skew. Not adding "
00561            "(%s)",
00562            router_describe(ri),
00563            (int)((ri->cache_info.published_on-now)/60),
00564            esc_router_info(ri));
00565     *msg = "Rejected: Your clock is set too far in the future, or your "
00566       "timezone is not correct.";
00567     return -1;
00568   }
00569   if (ri->cache_info.published_on < now-ROUTER_MAX_AGE_TO_PUBLISH) {
00570     log_fn(severity, LD_DIRSERV,
00571            "Publication time for %s is too far "
00572            "(%d minutes) in the past. Not adding (%s)",
00573            router_describe(ri),
00574            (int)((now-ri->cache_info.published_on)/60),
00575            esc_router_info(ri));
00576     *msg = "Rejected: Server is expired, or your clock is too far in the past,"
00577       " or your timezone is not correct.";
00578     return -1;
00579   }
00580   if (dirserv_router_has_valid_address(ri) < 0) {
00581     log_fn(severity, LD_DIRSERV,
00582            "Router %s has invalid address '%s'. "
00583            "Not adding (%s).",
00584            router_describe(ri),
00585            ri->address,
00586            esc_router_info(ri));
00587     *msg = "Rejected: Address is not an IP, or IP is a private address.";
00588     return -1;
00589   }
00590 
00591   *valid_out = ! (status & FP_INVALID);
00592 
00593   return 0;
00594 }
00595 
00599 void
00600 dirserv_set_node_flags_from_authoritative_status(node_t *node,
00601                                                  uint32_t authstatus)
00602 {
00603   node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
00604   node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0;
00605   node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
00606 }
00607 
00609 static int
00610 WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
00611 {
00612   return a < b;
00613 }
00614 
00617 was_router_added_t
00618 dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose,
00619                                  const char *source,
00620                                  const char **msg)
00621 {
00622   was_router_added_t r, r_tmp;
00623   const char *msg_out;
00624   smartlist_t *list;
00625   const char *s;
00626   int n_parsed = 0;
00627   time_t now = time(NULL);
00628   char annotation_buf[ROUTER_ANNOTATION_BUF_LEN];
00629   char time_buf[ISO_TIME_LEN+1];
00630   int general = purpose == ROUTER_PURPOSE_GENERAL;
00631   tor_assert(msg);
00632 
00633   r=ROUTER_ADDED_SUCCESSFULLY; /*Least severe return value. */
00634 
00635   format_iso_time(time_buf, now);
00636   if (tor_snprintf(annotation_buf, sizeof(annotation_buf),
00637                    "@uploaded-at %s\n"
00638                    "@source %s\n"
00639                    "%s%s%s", time_buf, escaped(source),
00640                    !general ? "@purpose " : "",
00641                    !general ? router_purpose_to_string(purpose) : "",
00642                    !general ? "\n" : "")<0) {
00643     *msg = "Couldn't format annotations";
00644     return -1;
00645   }
00646 
00647   s = desc;
00648   list = smartlist_new();
00649   if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0, 0,
00650                                      annotation_buf)) {
00651     SMARTLIST_FOREACH(list, routerinfo_t *, ri, {
00652         msg_out = NULL;
00653         tor_assert(ri->purpose == purpose);
00654         r_tmp = dirserv_add_descriptor(ri, &msg_out, source);
00655         if (WRA_MORE_SEVERE(r_tmp, r)) {
00656           r = r_tmp;
00657           *msg = msg_out;
00658         }
00659       });
00660   }
00661   n_parsed += smartlist_len(list);
00662   smartlist_clear(list);
00663 
00664   s = desc;
00665   if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1, 0,
00666                                      NULL)) {
00667     SMARTLIST_FOREACH(list, extrainfo_t *, ei, {
00668         msg_out = NULL;
00669 
00670         r_tmp = dirserv_add_extrainfo(ei, &msg_out);
00671         if (WRA_MORE_SEVERE(r_tmp, r)) {
00672           r = r_tmp;
00673           *msg = msg_out;
00674         }
00675       });
00676   }
00677   n_parsed += smartlist_len(list);
00678   smartlist_free(list);
00679 
00680   if (! *msg) {
00681     if (!n_parsed) {
00682       *msg = "No descriptors found in your POST.";
00683       if (WRA_WAS_ADDED(r))
00684         r = ROUTER_WAS_NOT_NEW;
00685     } else {
00686       *msg = "(no message)";
00687     }
00688   }
00689 
00690   return r;
00691 }
00692 
00703 was_router_added_t
00704 dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
00705 {
00706   was_router_added_t r;
00707   routerinfo_t *ri_old;
00708   char *desc, *nickname;
00709   size_t desclen = 0;
00710   *msg = NULL;
00711 
00712   /* If it's too big, refuse it now. Otherwise we'll cache it all over the
00713    * network and it'll clog everything up. */
00714   if (ri->cache_info.signed_descriptor_len > MAX_DESCRIPTOR_UPLOAD_SIZE) {
00715     log_notice(LD_DIR, "Somebody attempted to publish a router descriptor '%s'"
00716                " (source: %s) with size %d. Either this is an attack, or the "
00717                "MAX_DESCRIPTOR_UPLOAD_SIZE (%d) constant is too low.",
00718                ri->nickname, source, (int)ri->cache_info.signed_descriptor_len,
00719                MAX_DESCRIPTOR_UPLOAD_SIZE);
00720     *msg = "Router descriptor was too large";
00721     control_event_or_authdir_new_descriptor("REJECTED",
00722                ri->cache_info.signed_descriptor_body,
00723                ri->cache_info.signed_descriptor_len, *msg);
00724     routerinfo_free(ri);
00725     return ROUTER_AUTHDIR_REJECTS;
00726   }
00727 
00728   /* Check whether this descriptor is semantically identical to the last one
00729    * from this server.  (We do this here and not in router_add_to_routerlist
00730    * because we want to be able to accept the newest router descriptor that
00731    * another authority has, so we all converge on the same one.) */
00732   ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest);
00733   if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on
00734       && router_differences_are_cosmetic(ri_old, ri)
00735       && !router_is_me(ri)) {
00736     log_info(LD_DIRSERV,
00737              "Not replacing descriptor from %s (source: %s); "
00738              "differences are cosmetic.",
00739              router_describe(ri), source);
00740     *msg = "Not replacing router descriptor; no information has changed since "
00741       "the last one with this identity.";
00742     control_event_or_authdir_new_descriptor("DROPPED",
00743                          ri->cache_info.signed_descriptor_body,
00744                          ri->cache_info.signed_descriptor_len, *msg);
00745     routerinfo_free(ri);
00746     return ROUTER_WAS_NOT_NEW;
00747   }
00748 
00749   /* Make a copy of desc, since router_add_to_routerlist might free
00750    * ri and its associated signed_descriptor_t. */
00751   desclen = ri->cache_info.signed_descriptor_len;
00752   desc = tor_strndup(ri->cache_info.signed_descriptor_body, desclen);
00753   nickname = tor_strdup(ri->nickname);
00754 
00755   /* Tell if we're about to need to launch a test if we add this. */
00756   ri->needs_retest_if_added =
00757     dirserv_should_launch_reachability_test(ri, ri_old);
00758 
00759   r = router_add_to_routerlist(ri, msg, 0, 0);
00760   if (!WRA_WAS_ADDED(r)) {
00761     /* unless the routerinfo was fine, just out-of-date */
00762     if (WRA_WAS_REJECTED(r))
00763       control_event_or_authdir_new_descriptor("REJECTED", desc, desclen, *msg);
00764     log_info(LD_DIRSERV,
00765              "Did not add descriptor from '%s' (source: %s): %s.",
00766              nickname, source, *msg ? *msg : "(no message)");
00767   } else {
00768     smartlist_t *changed;
00769     control_event_or_authdir_new_descriptor("ACCEPTED", desc, desclen, *msg);
00770 
00771     changed = smartlist_new();
00772     smartlist_add(changed, ri);
00773     routerlist_descriptors_added(changed, 0);
00774     smartlist_free(changed);
00775     if (!*msg) {
00776       *msg =  "Descriptor accepted";
00777     }
00778     log_info(LD_DIRSERV,
00779              "Added descriptor from '%s' (source: %s): %s.",
00780              nickname, source, *msg);
00781   }
00782   tor_free(desc);
00783   tor_free(nickname);
00784   return r;
00785 }
00786 
00788 static was_router_added_t
00789 dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
00790 {
00791   const routerinfo_t *ri;
00792   int r;
00793   tor_assert(msg);
00794   *msg = NULL;
00795 
00796   ri = router_get_by_id_digest(ei->cache_info.identity_digest);
00797   if (!ri) {
00798     *msg = "No corresponding router descriptor for extra-info descriptor";
00799     extrainfo_free(ei);
00800     return ROUTER_BAD_EI;
00801   }
00802 
00803   /* If it's too big, refuse it now. Otherwise we'll cache it all over the
00804    * network and it'll clog everything up. */
00805   if (ei->cache_info.signed_descriptor_len > MAX_EXTRAINFO_UPLOAD_SIZE) {
00806     log_notice(LD_DIR, "Somebody attempted to publish an extrainfo "
00807                "with size %d. Either this is an attack, or the "
00808                "MAX_EXTRAINFO_UPLOAD_SIZE (%d) constant is too low.",
00809                (int)ei->cache_info.signed_descriptor_len,
00810                MAX_EXTRAINFO_UPLOAD_SIZE);
00811     *msg = "Extrainfo document was too large";
00812     extrainfo_free(ei);
00813     return ROUTER_BAD_EI;
00814   }
00815 
00816   if ((r = routerinfo_incompatible_with_extrainfo(ri, ei, NULL, msg))) {
00817     extrainfo_free(ei);
00818     return r < 0 ? ROUTER_WAS_NOT_NEW : ROUTER_BAD_EI;
00819   }
00820   router_add_extrainfo_to_routerlist(ei, msg, 0, 0);
00821   return ROUTER_ADDED_SUCCESSFULLY;
00822 }
00823 
00828 static void
00829 directory_remove_invalid(void)
00830 {
00831   int changed = 0;
00832   routerlist_t *rl = router_get_routerlist();
00833   smartlist_t *nodes = smartlist_new();
00834   smartlist_add_all(nodes, nodelist_get_list());
00835 
00836   SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
00837     const char *msg;
00838     routerinfo_t *ent = node->ri;
00839     char description[NODE_DESC_BUF_LEN];
00840     uint32_t r;
00841     if (!ent)
00842       continue;
00843     r = dirserv_router_get_status(ent, &msg);
00844     router_get_description(description, ent);
00845     if (r & FP_REJECT) {
00846       log_info(LD_DIRSERV, "Router %s is now rejected: %s",
00847                description, msg?msg:"");
00848       routerlist_remove(rl, ent, 0, time(NULL));
00849       changed = 1;
00850       continue;
00851     }
00852 #if 0
00853     if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
00854       log_info(LD_DIRSERV,
00855                "Router %s is now %snamed.", description,
00856                (r&FP_NAMED)?"":"un");
00857       ent->is_named = (r&FP_NAMED)?1:0;
00858       changed = 1;
00859     }
00860     if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
00861       log_info(LD_DIRSERV,
00862                "Router '%s' is now %snamed. (FP_UNNAMED)", description,
00863                (r&FP_NAMED)?"":"un");
00864       ent->is_named = (r&FP_NUNAMED)?0:1;
00865       changed = 1;
00866     }
00867 #endif
00868     if (bool_neq((r & FP_INVALID), !node->is_valid)) {
00869       log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
00870                (r&FP_INVALID) ? "in" : "");
00871       node->is_valid = (r&FP_INVALID)?0:1;
00872       changed = 1;
00873     }
00874     if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
00875       log_info(LD_DIRSERV, "Router '%s' is now a %s directory", description,
00876                (r & FP_BADDIR) ? "bad" : "good");
00877       node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
00878       changed = 1;
00879     }
00880     if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
00881       log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
00882                (r & FP_BADEXIT) ? "bad" : "good");
00883       node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
00884       changed = 1;
00885     }
00886   } SMARTLIST_FOREACH_END(node);
00887   if (changed)
00888     directory_set_dirty();
00889 
00890   routerlist_assert_ok(rl);
00891   smartlist_free(nodes);
00892 }
00893 
00898 void
00899 directory_set_dirty(void)
00900 {
00901   time_t now = time(NULL);
00902   int set_v1_dirty=0;
00903 
00904   /* Regenerate stubs only every 8 hours.
00905    * XXXX It would be nice to generate less often, but these are just
00906    * stubs: it doesn't matter. */
00907 #define STUB_REGENERATE_INTERVAL (8*60*60)
00908   if (!the_directory || !the_runningrouters.dir)
00909     set_v1_dirty = 1;
00910   else if (the_directory->published < now - STUB_REGENERATE_INTERVAL ||
00911            the_runningrouters.published < now - STUB_REGENERATE_INTERVAL)
00912     set_v1_dirty = 1;
00913 
00914   if (set_v1_dirty) {
00915     if (!the_directory_is_dirty)
00916       the_directory_is_dirty = now;
00917     if (!runningrouters_is_dirty)
00918       runningrouters_is_dirty = now;
00919   }
00920   if (!the_v2_networkstatus_is_dirty)
00921     the_v2_networkstatus_is_dirty = now;
00922 }
00923 
00929 static char *
00930 list_single_server_status(const routerinfo_t *desc, int is_live)
00931 {
00932   char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
00933   char *cp;
00934   const node_t *node;
00935 
00936   tor_assert(desc);
00937 
00938   cp = buf;
00939   if (!is_live) {
00940     *cp++ = '!';
00941   }
00942   node = node_get_by_id(desc->cache_info.identity_digest);
00943   if (node && node->is_valid) {
00944     strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
00945     cp += strlen(cp);
00946     *cp++ = '=';
00947   }
00948   *cp++ = '$';
00949   base16_encode(cp, HEX_DIGEST_LEN+1, desc->cache_info.identity_digest,
00950                 DIGEST_LEN);
00951   return tor_strdup(buf);
00952 }
00953 
00954 /* DOCDOC running_long_enough_to_decide_unreachable */
00955 static INLINE int
00956 running_long_enough_to_decide_unreachable(void)
00957 {
00958   return time_of_process_start
00959     + get_options()->TestingAuthDirTimeToLearnReachability < approx_time();
00960 }
00961 
00965 #define REACHABLE_TIMEOUT (45*60)
00966 
00970 #define HIBERNATION_PUBLICATION_SKEW (60*60)
00971 
00975 void
00976 dirserv_set_router_is_running(routerinfo_t *router, time_t now)
00977 {
00978   /*XXXX024 This function is a mess.  Separate out the part that calculates
00979     whether it's reachable and the part that tells rephist that the router was
00980     unreachable.
00981    */
00982   int answer;
00983   node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
00984   tor_assert(node);
00985 
00986   if (router_is_me(router)) {
00987     /* We always know if we are down ourselves. */
00988     answer = ! we_are_hibernating();
00989   } else if (router->is_hibernating &&
00990              (router->cache_info.published_on +
00991               HIBERNATION_PUBLICATION_SKEW) > router->last_reachable) {
00992     /* A hibernating router is down unless we (somehow) had contact with it
00993      * since it declared itself to be hibernating. */
00994     answer = 0;
00995   } else if (get_options()->AssumeReachable) {
00996     /* If AssumeReachable, everybody is up unless they say they are down! */
00997     answer = 1;
00998   } else {
00999     /* Otherwise, a router counts as up if we found it reachable in the last
01000        REACHABLE_TIMEOUT seconds. */
01001     answer = (now < router->last_reachable + REACHABLE_TIMEOUT);
01002   }
01003 
01004   if (!answer && running_long_enough_to_decide_unreachable()) {
01005     /* Not considered reachable. tell rephist about that.
01006 
01007        Because we launch a reachability test for each router every
01008        REACHABILITY_TEST_CYCLE_PERIOD seconds, then the router has probably
01009        been down since at least that time after we last successfully reached
01010        it.
01011      */
01012     time_t when = now;
01013     if (router->last_reachable &&
01014         router->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD < now)
01015       when = router->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD;
01016     rep_hist_note_router_unreachable(router->cache_info.identity_digest, when);
01017   }
01018 
01019   node->is_running = answer;
01020 }
01021 
01028 int
01029 list_server_status_v1(smartlist_t *routers, char **router_status_out,
01030                       int for_controller)
01031 {
01032   /* List of entries in a router-status style: An optional !, then an optional
01033    * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
01034   smartlist_t *rs_entries;
01035   time_t now = time(NULL);
01036   time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
01037   const or_options_t *options = get_options();
01038   /* We include v2 dir auths here too, because they need to answer
01039    * controllers. Eventually we'll deprecate this whole function;
01040    * see also networkstatus_getinfo_by_purpose(). */
01041   int authdir = authdir_mode_publishes_statuses(options);
01042   tor_assert(router_status_out);
01043 
01044   rs_entries = smartlist_new();
01045 
01046   SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
01047     const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
01048     tor_assert(node);
01049     if (authdir) {
01050       /* Update router status in routerinfo_t. */
01051       dirserv_set_router_is_running(ri, now);
01052     }
01053     if (for_controller) {
01054       char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
01055       char *cp = name_buf;
01056       if (!node->is_running)
01057         *cp++ = '!';
01058       router_get_verbose_nickname(cp, ri);
01059       smartlist_add(rs_entries, tor_strdup(name_buf));
01060     } else if (ri->cache_info.published_on >= cutoff) {
01061       smartlist_add(rs_entries, list_single_server_status(ri,
01062                                                           node->is_running));
01063     }
01064   } SMARTLIST_FOREACH_END(ri);
01065 
01066   *router_status_out = smartlist_join_strings(rs_entries, " ", 0, NULL);
01067 
01068   SMARTLIST_FOREACH(rs_entries, char *, cp, tor_free(cp));
01069   smartlist_free(rs_entries);
01070 
01071   return 0;
01072 }
01073 
01079 static char *
01080 format_versions_list(config_line_t *ln)
01081 {
01082   smartlist_t *versions;
01083   char *result;
01084   versions = smartlist_new();
01085   for ( ; ln; ln = ln->next) {
01086     smartlist_split_string(versions, ln->value, ",",
01087                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
01088   }
01089   sort_version_list(versions, 1);
01090   result = smartlist_join_strings(versions,",",0,NULL);
01091   SMARTLIST_FOREACH(versions,char *,s,tor_free(s));
01092   smartlist_free(versions);
01093   return result;
01094 }
01095 
01099 static int
01100 router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
01101 {
01102   time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
01103   if (ri->cache_info.published_on < cutoff)
01104     return 0;
01105   if (!node->is_running || !node->is_valid || ri->is_hibernating)
01106     return 0;
01107   return 1;
01108 }
01109 
01116 int
01117 dirserv_dump_directory_to_string(char **dir_out,
01118                                  crypto_pk_t *private_key)
01119 {
01120   char *cp;
01121   char *identity_pkey; /* Identity key, DER64-encoded. */
01122   char *recommended_versions;
01123   char digest[DIGEST_LEN];
01124   char published[ISO_TIME_LEN+1];
01125   char *buf = NULL;
01126   size_t buf_len;
01127   size_t identity_pkey_len;
01128   time_t now = time(NULL);
01129 
01130   tor_assert(dir_out);
01131   *dir_out = NULL;
01132 
01133   if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,
01134                                            &identity_pkey_len)<0) {
01135     log_warn(LD_BUG,"write identity_pkey to string failed!");
01136     return -1;
01137   }
01138 
01139   recommended_versions =
01140     format_versions_list(get_options()->RecommendedVersions);
01141 
01142   format_iso_time(published, now);
01143 
01144   buf_len = 2048+strlen(recommended_versions);
01145 
01146   buf = tor_malloc(buf_len);
01147   /* We'll be comparing against buf_len throughout the rest of the
01148      function, though strictly speaking we shouldn't be able to exceed
01149      it.  This is C, after all, so we may as well check for buffer
01150      overruns.*/
01151 
01152   tor_snprintf(buf, buf_len,
01153                "signed-directory\n"
01154                "published %s\n"
01155                "recommended-software %s\n"
01156                "router-status %s\n"
01157                "dir-signing-key\n%s\n",
01158                published, recommended_versions, "",
01159                identity_pkey);
01160 
01161   tor_free(recommended_versions);
01162   tor_free(identity_pkey);
01163 
01164   cp = buf + strlen(buf);
01165   *cp = '\0';
01166 
01167   /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
01168      signature. */
01169   if (strlcat(buf, "directory-signature ", buf_len) >= buf_len)
01170     goto truncated;
01171   if (strlcat(buf, get_options()->Nickname, buf_len) >= buf_len)
01172     goto truncated;
01173   if (strlcat(buf, "\n", buf_len) >= buf_len)
01174     goto truncated;
01175 
01176   if (router_get_dir_hash(buf,digest)) {
01177     log_warn(LD_BUG,"couldn't compute digest");
01178     tor_free(buf);
01179     return -1;
01180   }
01181   note_crypto_pk_op(SIGN_DIR);
01182   if (router_append_dirobj_signature(buf,buf_len,digest,DIGEST_LEN,
01183                                      private_key)<0) {
01184     tor_free(buf);
01185     return -1;
01186   }
01187 
01188   *dir_out = buf;
01189   return 0;
01190  truncated:
01191   log_warn(LD_BUG,"tried to exceed string length.");
01192   tor_free(buf);
01193   return -1;
01194 }
01195 
01196 /********************************************************************/
01197 
01198 /* A set of functions to answer questions about how we'd like to behave
01199  * as a directory mirror/client. */
01200 
01203 int
01204 directory_fetches_from_authorities(const or_options_t *options)
01205 {
01206   const routerinfo_t *me;
01207   uint32_t addr;
01208   int refuseunknown;
01209   if (options->FetchDirInfoEarly)
01210     return 1;
01211   if (options->BridgeRelay == 1)
01212     return 0;
01213   if (server_mode(options) && router_pick_published_address(options, &addr)<0)
01214     return 1; /* we don't know our IP address; ask an authority. */
01215   refuseunknown = ! router_my_exit_policy_is_reject_star() &&
01216     should_refuse_unknown_exits(options);
01217   if (options->DirPort == NULL && !refuseunknown)
01218     return 0;
01219   if (!server_mode(options) || !advertised_server_mode())
01220     return 0;
01221   me = router_get_my_routerinfo();
01222   if (!me || (!me->dir_port && !refuseunknown))
01223     return 0; /* if dirport not advertised, return 0 too */
01224   return 1;
01225 }
01226 
01230 int
01231 directory_fetches_dir_info_early(const or_options_t *options)
01232 {
01233   return directory_fetches_from_authorities(options);
01234 }
01235 
01242 int
01243 directory_fetches_dir_info_later(const or_options_t *options)
01244 {
01245   return options->UseBridges != 0;
01246 }
01247 
01250 int
01251 directory_caches_v2_dir_info(const or_options_t *options)
01252 {
01253   return options->DirPort != NULL;
01254 }
01255 
01259 int
01260 directory_caches_unknown_auth_certs(const or_options_t *options)
01261 {
01262   return options->DirPort || options->BridgeRelay;
01263 }
01264 
01268 int
01269 directory_caches_dir_info(const or_options_t *options)
01270 {
01271   if (options->BridgeRelay || options->DirPort)
01272     return 1;
01273   if (!server_mode(options) || !advertised_server_mode())
01274     return 0;
01275   /* We need an up-to-date view of network info if we're going to try to
01276    * block exit attempts from unknown relays. */
01277   return ! router_my_exit_policy_is_reject_star() &&
01278     should_refuse_unknown_exits(options);
01279 }
01280 
01284 int
01285 directory_permits_begindir_requests(const or_options_t *options)
01286 {
01287   return options->BridgeRelay != 0 || options->DirPort != NULL;
01288 }
01289 
01293 int
01294 directory_permits_controller_requests(const or_options_t *options)
01295 {
01296   return options->DirPort != NULL;
01297 }
01298 
01303 int
01304 directory_too_idle_to_fetch_descriptors(const or_options_t *options,
01305                                         time_t now)
01306 {
01307   return !directory_caches_dir_info(options) &&
01308          !options->FetchUselessDescriptors &&
01309          rep_hist_circbuilding_dormant(now);
01310 }
01311 
01312 /********************************************************************/
01313 
01314 /* Used only by non-v1-auth dirservers: The v1 directory and
01315  * runningrouters we'll serve when requested. */
01316 
01319 static cached_dir_t *cached_directory = NULL;
01322 static cached_dir_t cached_runningrouters;
01323 
01326 static digestmap_t *cached_v2_networkstatus = NULL;
01327 
01330 static strmap_t *cached_consensuses = NULL;
01331 
01338 static void
01339 set_cached_dir(cached_dir_t *d, char *directory, time_t when)
01340 {
01341   time_t now = time(NULL);
01342   if (when<=d->published) {
01343     log_info(LD_DIRSERV, "Ignoring old directory; not caching.");
01344     tor_free(directory);
01345   } else if (when>=now+ROUTER_MAX_AGE_TO_PUBLISH) {
01346     log_info(LD_DIRSERV, "Ignoring future directory; not caching.");
01347     tor_free(directory);
01348   } else {
01349     /* if (when>d->published && when<now+ROUTER_MAX_AGE) */
01350     log_debug(LD_DIRSERV, "Caching directory.");
01351     tor_free(d->dir);
01352     d->dir = directory;
01353     d->dir_len = strlen(directory);
01354     tor_free(d->dir_z);
01355     if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
01356                           ZLIB_METHOD)) {
01357       log_warn(LD_BUG,"Error compressing cached directory");
01358     }
01359     d->published = when;
01360   }
01361 }
01362 
01365 void
01366 cached_dir_decref(cached_dir_t *d)
01367 {
01368   if (!d || --d->refcnt > 0)
01369     return;
01370   clear_cached_dir(d);
01371   tor_free(d);
01372 }
01373 
01376 cached_dir_t *
01377 new_cached_dir(char *s, time_t published)
01378 {
01379   cached_dir_t *d = tor_malloc_zero(sizeof(cached_dir_t));
01380   d->refcnt = 1;
01381   d->dir = s;
01382   d->dir_len = strlen(s);
01383   d->published = published;
01384   if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
01385                         ZLIB_METHOD)) {
01386     log_warn(LD_BUG, "Error compressing directory");
01387   }
01388   return d;
01389 }
01390 
01392 static void
01393 clear_cached_dir(cached_dir_t *d)
01394 {
01395   tor_free(d->dir);
01396   tor_free(d->dir_z);
01397   memset(d, 0, sizeof(cached_dir_t));
01398 }
01399 
01401 static void
01402 _free_cached_dir(void *_d)
01403 {
01404   cached_dir_t *d;
01405   if (!_d)
01406     return;
01407 
01408   d = (cached_dir_t *)_d;
01409   cached_dir_decref(d);
01410 }
01411 
01420 void
01421 dirserv_set_cached_directory(const char *directory, time_t published,
01422                              int is_running_routers)
01423 {
01424   time_t now = time(NULL);
01425 
01426   if (is_running_routers) {
01427     if (published >= now - MAX_V1_RR_AGE)
01428       set_cached_dir(&cached_runningrouters, tor_strdup(directory), published);
01429   } else {
01430     if (published >= now - MAX_V1_DIRECTORY_AGE) {
01431       cached_dir_decref(cached_directory);
01432       cached_directory = new_cached_dir(tor_strdup(directory), published);
01433     }
01434   }
01435 }
01436 
01445 void
01446 dirserv_set_cached_networkstatus_v2(const char *networkstatus,
01447                                     const char *identity,
01448                                     time_t published)
01449 {
01450   cached_dir_t *d, *old_d;
01451   smartlist_t *trusted_dirs;
01452   if (!cached_v2_networkstatus)
01453     cached_v2_networkstatus = digestmap_new();
01454 
01455   old_d = digestmap_get(cached_v2_networkstatus, identity);
01456   if (!old_d && !networkstatus)
01457     return;
01458 
01459   if (networkstatus) {
01460     if (!old_d || published > old_d->published) {
01461       d = new_cached_dir(tor_strdup(networkstatus), published);
01462       digestmap_set(cached_v2_networkstatus, identity, d);
01463       if (old_d)
01464         cached_dir_decref(old_d);
01465     }
01466   } else {
01467     if (old_d) {
01468       digestmap_remove(cached_v2_networkstatus, identity);
01469       cached_dir_decref(old_d);
01470     }
01471   }
01472 
01473   /* Now purge old entries. */
01474   trusted_dirs = router_get_trusted_dir_servers();
01475   if (digestmap_size(cached_v2_networkstatus) >
01476       smartlist_len(trusted_dirs) + MAX_UNTRUSTED_NETWORKSTATUSES) {
01477     /* We need to remove the oldest untrusted networkstatus. */
01478     const char *oldest = NULL;
01479     time_t oldest_published = TIME_MAX;
01480     digestmap_iter_t *iter;
01481 
01482     for (iter = digestmap_iter_init(cached_v2_networkstatus);
01483          !digestmap_iter_done(iter);
01484          iter = digestmap_iter_next(cached_v2_networkstatus, iter)) {
01485       const char *ident;
01486       void *val;
01487       digestmap_iter_get(iter, &ident, &val);
01488       d = val;
01489       if (d->published < oldest_published &&
01490           !router_digest_is_trusted_dir(ident)) {
01491         oldest = ident;
01492         oldest_published = d->published;
01493       }
01494     }
01495     tor_assert(oldest);
01496     d = digestmap_remove(cached_v2_networkstatus, oldest);
01497     if (d)
01498       cached_dir_decref(d);
01499   }
01500 }
01501 
01505 void
01506 dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
01507                                            const char *flavor_name,
01508                                            const digests_t *digests,
01509                                            time_t published)
01510 {
01511   cached_dir_t *new_networkstatus;
01512   cached_dir_t *old_networkstatus;
01513   if (!cached_consensuses)
01514     cached_consensuses = strmap_new();
01515 
01516   new_networkstatus = new_cached_dir(tor_strdup(networkstatus), published);
01517   memcpy(&new_networkstatus->digests, digests, sizeof(digests_t));
01518   old_networkstatus = strmap_set(cached_consensuses, flavor_name,
01519                                  new_networkstatus);
01520   if (old_networkstatus)
01521     cached_dir_decref(old_networkstatus);
01522 }
01523 
01526 void
01527 dirserv_clear_old_networkstatuses(time_t cutoff)
01528 {
01529   if (!cached_v2_networkstatus)
01530     return;
01531 
01532   DIGESTMAP_FOREACH_MODIFY(cached_v2_networkstatus, id, cached_dir_t *, dir) {
01533     if (dir->published < cutoff) {
01534       char *fname;
01535       fname = networkstatus_get_cache_filename(id);
01536       if (file_status(fname) == FN_FILE) {
01537         log_info(LD_DIR, "Removing too-old untrusted networkstatus in %s",
01538                  fname);
01539         unlink(fname);
01540       }
01541       tor_free(fname);
01542       cached_dir_decref(dir);
01543       MAP_DEL_CURRENT(id);
01544     }
01545   } DIGESTMAP_FOREACH_END
01546 }
01547 
01550 void
01551 dirserv_clear_old_v1_info(time_t now)
01552 {
01553   if (cached_directory &&
01554       cached_directory->published < (now - MAX_V1_DIRECTORY_AGE)) {
01555     cached_dir_decref(cached_directory);
01556     cached_directory = NULL;
01557   }
01558   if (cached_runningrouters.published < (now - MAX_V1_RR_AGE)) {
01559     clear_cached_dir(&cached_runningrouters);
01560   }
01561 }
01562 
01568 static cached_dir_t *
01569 dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
01570                             cached_dir_t *auth_src,
01571                             time_t dirty, cached_dir_t *(*regenerate)(void),
01572                             const char *name,
01573                             dirinfo_type_t auth_type)
01574 {
01575   const or_options_t *options = get_options();
01576   int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) ||
01577                   (auth_type == V2_DIRINFO && authdir_mode_v2(options));
01578 
01579   if (!authority || authdir_mode_bridge(options)) {
01580     return cache_src;
01581   } else {
01582     /* We're authoritative. */
01583     if (regenerate != NULL) {
01584       if (dirty && dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
01585         if (!(auth_src = regenerate())) {
01586           log_err(LD_BUG, "Couldn't generate %s?", name);
01587           exit(1);
01588         }
01589       } else {
01590         log_info(LD_DIRSERV, "The %s is still clean; reusing.", name);
01591       }
01592     }
01593     return auth_src ? auth_src : cache_src;
01594   }
01595 }
01596 
01600 cached_dir_t *
01601 dirserv_get_directory(void)
01602 {
01603   return dirserv_pick_cached_dir_obj(cached_directory, the_directory,
01604                                      the_directory_is_dirty,
01605                                      dirserv_regenerate_directory,
01606                                      "v1 server directory", V1_DIRINFO);
01607 }
01608 
01613 static cached_dir_t *
01614 dirserv_regenerate_directory(void)
01615 {
01616   char *new_directory=NULL;
01617 
01618   if (dirserv_dump_directory_to_string(&new_directory,
01619                                        get_server_identity_key())) {
01620     log_warn(LD_BUG, "Error creating directory.");
01621     tor_free(new_directory);
01622     return NULL;
01623   }
01624   cached_dir_decref(the_directory);
01625   the_directory = new_cached_dir(new_directory, time(NULL));
01626   log_info(LD_DIRSERV,"New directory (size %d) has been built.",
01627            (int)the_directory->dir_len);
01628   log_debug(LD_DIRSERV,"New directory (size %d):\n%s",
01629             (int)the_directory->dir_len, the_directory->dir);
01630 
01631   the_directory_is_dirty = 0;
01632 
01633   /* Save the directory to disk so we re-load it quickly on startup.
01634    */
01635   dirserv_set_cached_directory(the_directory->dir, time(NULL), 0);
01636 
01637   return the_directory;
01638 }
01639 
01642 static cached_dir_t *
01643 generate_runningrouters(void)
01644 {
01645   char *s=NULL;
01646   char digest[DIGEST_LEN];
01647   char published[ISO_TIME_LEN+1];
01648   size_t len;
01649   crypto_pk_t *private_key = get_server_identity_key();
01650   char *identity_pkey; /* Identity key, DER64-encoded. */
01651   size_t identity_pkey_len;
01652 
01653   if (crypto_pk_write_public_key_to_string(private_key,&identity_pkey,
01654                                            &identity_pkey_len)<0) {
01655     log_warn(LD_BUG,"write identity_pkey to string failed!");
01656     goto err;
01657   }
01658   format_iso_time(published, time(NULL));
01659 
01660   len = 2048;
01661   s = tor_malloc_zero(len);
01662   tor_snprintf(s, len,
01663                "network-status\n"
01664                "published %s\n"
01665                "router-status %s\n"
01666                "dir-signing-key\n%s"
01667                "directory-signature %s\n",
01668                published, "", identity_pkey,
01669                get_options()->Nickname);
01670   tor_free(identity_pkey);
01671   if (router_get_runningrouters_hash(s,digest)) {
01672     log_warn(LD_BUG,"couldn't compute digest");
01673     goto err;
01674   }
01675   note_crypto_pk_op(SIGN_DIR);
01676   if (router_append_dirobj_signature(s, len, digest, DIGEST_LEN,
01677                                      private_key)<0)
01678     goto err;
01679 
01680   set_cached_dir(&the_runningrouters, s, time(NULL));
01681   runningrouters_is_dirty = 0;
01682 
01683   return &the_runningrouters;
01684  err:
01685   tor_free(s);
01686   return NULL;
01687 }
01688 
01692 cached_dir_t *
01693 dirserv_get_runningrouters(void)
01694 {
01695   return dirserv_pick_cached_dir_obj(
01696                          &cached_runningrouters, &the_runningrouters,
01697                          runningrouters_is_dirty,
01698                          generate_runningrouters,
01699                          "v1 network status list", V1_DIRINFO);
01700 }
01701 
01704 cached_dir_t *
01705 dirserv_get_consensus(const char *flavor_name)
01706 {
01707   if (!cached_consensuses)
01708     return NULL;
01709   return strmap_get(cached_consensuses, flavor_name);
01710 }
01711 
01713 static cached_dir_t *the_v2_networkstatus = NULL;
01714 
01717 static int
01718 should_generate_v2_networkstatus(void)
01719 {
01720   return authdir_mode_v2(get_options()) &&
01721     the_v2_networkstatus_is_dirty &&
01722     the_v2_networkstatus_is_dirty + DIR_REGEN_SLACK_TIME < time(NULL);
01723 }
01724 
01730 #define UPTIME_TO_GUARANTEE_STABLE (3600*24*30)
01731 
01733 #define MTBF_TO_GUARANTEE_STABLE (60*60*24*5)
01734 
01738 #define TIME_KNOWN_TO_GUARANTEE_FAMILIAR (8*24*60*60)
01739 
01741 #define WFU_TO_GUARANTEE_GUARD (0.98)
01742 
01743 /* Thresholds for server performance: set by
01744  * dirserv_compute_performance_thresholds, and used by
01745  * generate_v2_networkstatus */
01746 
01748 static uint32_t stable_uptime = 0; /* start at a safe value */
01750 static double stable_mtbf = 0.0;
01753 static int enough_mtbf_info = 0;
01756 static double guard_wfu = 0.0;
01759 static long guard_tk = 0;
01761 static uint32_t fast_bandwidth = 0;
01764 static uint32_t guard_bandwidth_including_exits = 0;
01767 static uint32_t guard_bandwidth_excluding_exits = 0;
01769 static uint64_t total_bandwidth = 0;
01771 static uint64_t total_exit_bandwidth = 0;
01772 
01775 static INLINE long
01776 real_uptime(const routerinfo_t *router, time_t now)
01777 {
01778   if (now < router->cache_info.published_on)
01779     return router->uptime;
01780   else
01781     return router->uptime + (now - router->cache_info.published_on);
01782 }
01783 
01789 static int
01790 dirserv_thinks_router_is_unreliable(time_t now,
01791                                     routerinfo_t *router,
01792                                     int need_uptime, int need_capacity)
01793 {
01794   if (need_uptime) {
01795     if (!enough_mtbf_info) {
01796       /* XXX024 Once most authorities are on v3, we should change the rule from
01797        * "use uptime if we don't have mtbf data" to "don't advertise Stable on
01798        * v3 if we don't have enough mtbf data."  Or maybe not, since if we ever
01799        * hit a point where we need to reset a lot of authorities at once,
01800        * none of them would be in a position to declare Stable.
01801        */
01802       long uptime = real_uptime(router, now);
01803       if ((unsigned)uptime < stable_uptime &&
01804           (unsigned)uptime < UPTIME_TO_GUARANTEE_STABLE)
01805         return 1;
01806     } else {
01807       double mtbf =
01808         rep_hist_get_stability(router->cache_info.identity_digest, now);
01809       if (mtbf < stable_mtbf &&
01810           mtbf < MTBF_TO_GUARANTEE_STABLE)
01811         return 1;
01812     }
01813   }
01814   if (need_capacity) {
01815     uint32_t bw = router_get_advertised_bandwidth(router);
01816     if (bw < fast_bandwidth)
01817       return 1;
01818   }
01819   return 0;
01820 }
01821 
01829 static int
01830 dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
01831                                 const node_t *node, time_t now)
01832 {
01833 
01834   long uptime;
01835 
01836   /* If we haven't been running for at least
01837    * get_options()->MinUptimeHidServDirectoryV2 seconds, we can't
01838    * have accurate data telling us a relay has been up for at least
01839    * that long. We also want to allow a bit of slack: Reachability
01840    * tests aren't instant. If we haven't been running long enough,
01841    * trust the relay. */
01842 
01843   if (stats_n_seconds_working >
01844       get_options()->MinUptimeHidServDirectoryV2 * 1.1)
01845     uptime = MIN(rep_hist_get_uptime(router->cache_info.identity_digest, now),
01846                  real_uptime(router, now));
01847   else
01848     uptime = real_uptime(router, now);
01849 
01850   /* XXX We shouldn't need to check dir_port, but we do because of
01851    * bug 1693. In the future, once relays set wants_to_be_hs_dir
01852    * correctly, we can revert to only checking dir_port if router's
01853    * version is too old. */
01854   /* XXX Unfortunately, we need to keep checking dir_port until all
01855    * *clients* suffering from bug 2722 are obsolete.  The first version
01856    * to fix the bug was 0.2.2.25-alpha. */
01857   return (router->wants_to_be_hs_dir && router->dir_port &&
01858           uptime >= get_options()->MinUptimeHidServDirectoryV2 &&
01859           node->is_running);
01860 }
01861 
01870 static void
01871 dirserv_compute_performance_thresholds(routerlist_t *rl)
01872 {
01873   int n_active, n_active_nonexit, n_familiar;
01874   uint32_t *uptimes, *bandwidths, *bandwidths_excluding_exits;
01875   long *tks;
01876   double *mtbfs, *wfus;
01877   time_t now = time(NULL);
01878   const or_options_t *options = get_options();
01879 
01880   /* initialize these all here, in case there are no routers */
01881   stable_uptime = 0;
01882   stable_mtbf = 0;
01883   fast_bandwidth = 0;
01884   guard_bandwidth_including_exits = 0;
01885   guard_bandwidth_excluding_exits = 0;
01886   guard_tk = 0;
01887   guard_wfu = 0;
01888   total_bandwidth = 0;
01889   total_exit_bandwidth = 0;
01890 
01891   /* Initialize arrays that will hold values for each router.  We'll
01892    * sort them and use that to compute thresholds. */
01893   n_active = n_active_nonexit = 0;
01894   /* Uptime for every active router. */
01895   uptimes = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers));
01896   /* Bandwidth for every active router. */
01897   bandwidths = tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers));
01898   /* Bandwidth for every active non-exit router. */
01899   bandwidths_excluding_exits =
01900     tor_malloc(sizeof(uint32_t)*smartlist_len(rl->routers));
01901   /* Weighted mean time between failure for each active router. */
01902   mtbfs = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
01903   /* Time-known for each active router. */
01904   tks = tor_malloc(sizeof(long)*smartlist_len(rl->routers));
01905   /* Weighted fractional uptime for each active router. */
01906   wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
01907 
01908   nodelist_assert_ok();
01909 
01910   /* Now, fill in the arrays. */
01911   SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
01912     routerinfo_t *ri = node->ri;
01913     if (ri && router_is_active(ri, node, now)) {
01914       const char *id = ri->cache_info.identity_digest;
01915       uint32_t bw;
01916       node->is_exit = (!router_exit_policy_rejects_all(ri) &&
01917                        exit_policy_is_general_exit(ri->exit_policy));
01918       uptimes[n_active] = (uint32_t)real_uptime(ri, now);
01919       mtbfs[n_active] = rep_hist_get_stability(id, now);
01920       tks  [n_active] = rep_hist_get_weighted_time_known(id, now);
01921       bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
01922       total_bandwidth += bw;
01923       if (node->is_exit && !node->is_bad_exit) {
01924         total_exit_bandwidth += bw;
01925       } else {
01926         bandwidths_excluding_exits[n_active_nonexit] = bw;
01927         ++n_active_nonexit;
01928       }
01929       ++n_active;
01930     }
01931   } SMARTLIST_FOREACH_END(node);
01932 
01933   /* Now, compute thresholds. */
01934   if (n_active) {
01935     /* The median uptime is stable. */
01936     stable_uptime = median_uint32(uptimes, n_active);
01937     /* The median mtbf is stable, if we have enough mtbf info */
01938     stable_mtbf = median_double(mtbfs, n_active);
01939     /* The 12.5th percentile bandwidth is fast. */
01940     fast_bandwidth = find_nth_uint32(bandwidths, n_active, n_active/8);
01941     /* (Now bandwidths is sorted.) */
01942     if (fast_bandwidth < ROUTER_REQUIRED_MIN_BANDWIDTH/2)
01943       fast_bandwidth = bandwidths[n_active/4];
01944     guard_bandwidth_including_exits = bandwidths[(n_active-1)/2];
01945     guard_tk = find_nth_long(tks, n_active, n_active/8);
01946   }
01947 
01948   if (guard_tk > TIME_KNOWN_TO_GUARANTEE_FAMILIAR)
01949     guard_tk = TIME_KNOWN_TO_GUARANTEE_FAMILIAR;
01950 
01951   {
01952     /* We can vote on a parameter for the minimum and maximum. */
01953     int32_t min_fast, max_fast;
01954     min_fast = networkstatus_get_param(NULL, "FastFlagMinThreshold",
01955                                        0, 0, INT32_MAX);
01956     max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold",
01957                                        INT32_MAX, min_fast, INT32_MAX);
01958     if (fast_bandwidth < (uint32_t)min_fast)
01959       fast_bandwidth = min_fast;
01960     if (fast_bandwidth > (uint32_t)max_fast)
01961       fast_bandwidth = max_fast;
01962   }
01963   /* Protect sufficiently fast nodes from being pushed out of the set
01964    * of Fast nodes. */
01965   if (options->AuthDirFastGuarantee &&
01966       fast_bandwidth > options->AuthDirFastGuarantee)
01967     fast_bandwidth = (uint32_t)options->AuthDirFastGuarantee;
01968 
01969   /* Now that we have a time-known that 7/8 routers are known longer than,
01970    * fill wfus with the wfu of every such "familiar" router. */
01971   n_familiar = 0;
01972 
01973   SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
01974       routerinfo_t *ri = node->ri;
01975       if (ri && router_is_active(ri, node, now)) {
01976         const char *id = ri->cache_info.identity_digest;
01977         long tk = rep_hist_get_weighted_time_known(id, now);
01978         if (tk < guard_tk)
01979           continue;
01980         wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now);
01981       }
01982   } SMARTLIST_FOREACH_END(node);
01983   if (n_familiar)
01984     guard_wfu = median_double(wfus, n_familiar);
01985   if (guard_wfu > WFU_TO_GUARANTEE_GUARD)
01986     guard_wfu = WFU_TO_GUARANTEE_GUARD;
01987 
01988   enough_mtbf_info = rep_hist_have_measured_enough_stability();
01989 
01990   if (n_active_nonexit) {
01991     guard_bandwidth_excluding_exits =
01992       median_uint32(bandwidths_excluding_exits, n_active_nonexit);
01993   }
01994 
01995   log(LOG_INFO, LD_DIRSERV,
01996       "Cutoffs: For Stable, %lu sec uptime, %lu sec MTBF. "
01997       "For Fast: %lu bytes/sec. "
01998       "For Guard: WFU %.03f%%, time-known %lu sec, "
01999       "and bandwidth %lu or %lu bytes/sec. We%s have enough stability data.",
02000       (unsigned long)stable_uptime,
02001       (unsigned long)stable_mtbf,
02002       (unsigned long)fast_bandwidth,
02003       guard_wfu*100,
02004       (unsigned long)guard_tk,
02005       (unsigned long)guard_bandwidth_including_exits,
02006       (unsigned long)guard_bandwidth_excluding_exits,
02007       enough_mtbf_info ? "" : " don't ");
02008 
02009   tor_free(uptimes);
02010   tor_free(mtbfs);
02011   tor_free(bandwidths);
02012   tor_free(bandwidths_excluding_exits);
02013   tor_free(tks);
02014   tor_free(wfus);
02015 }
02016 
02020 static char *
02021 version_from_platform(const char *platform)
02022 {
02023   if (platform && !strcmpstart(platform, "Tor ")) {
02024     const char *eos = find_whitespace(platform+4);
02025     if (eos && !strcmpstart(eos, " (r")) {
02026       /* XXXX Unify this logic with the other version extraction
02027        * logic in routerparse.c. */
02028       eos = find_whitespace(eos+1);
02029     }
02030     if (eos) {
02031       return tor_strndup(platform, eos-platform);
02032     }
02033   }
02034   return NULL;
02035 }
02036 
02051 int
02052 routerstatus_format_entry(char *buf, size_t buf_len,
02053                           const routerstatus_t *rs, const char *version,
02054                           routerstatus_format_type_t format)
02055 {
02056   int r;
02057   char *cp;
02058   char *summary;
02059 
02060   char published[ISO_TIME_LEN+1];
02061   char identity64[BASE64_DIGEST_LEN+1];
02062   char digest64[BASE64_DIGEST_LEN+1];
02063 
02064   format_iso_time(published, rs->published_on);
02065   digest_to_base64(identity64, rs->identity_digest);
02066   digest_to_base64(digest64, rs->descriptor_digest);
02067 
02068   r = tor_snprintf(buf, buf_len,
02069                    "r %s %s %s%s%s %s %d %d\n",
02070                    rs->nickname,
02071                    identity64,
02072                    (format==NS_V3_CONSENSUS_MICRODESC)?"":digest64,
02073                    (format==NS_V3_CONSENSUS_MICRODESC)?"":" ",
02074                    published,
02075                    fmt_addr32(rs->addr),
02076                    (int)rs->or_port,
02077                    (int)rs->dir_port);
02078   if (r<0) {
02079     log_warn(LD_BUG, "Not enough space in buffer.");
02080     return -1;
02081   }
02082 
02083   /* TODO: Maybe we want to pass in what we need to build the rest of
02084    * this here, instead of in the caller. Then we could use the
02085    * networkstatus_type_t values, with an additional control port value
02086    * added -MP */
02087   if (format == NS_V3_CONSENSUS || format == NS_V3_CONSENSUS_MICRODESC)
02088     return 0;
02089 
02090   cp = buf + strlen(buf);
02091   /* NOTE: Whenever this list expands, be sure to increase MAX_FLAG_LINE_LEN*/
02092   r = tor_snprintf(cp, buf_len - (cp-buf),
02093                    "s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
02094                   /* These must stay in alphabetical order. */
02095                    rs->is_authority?" Authority":"",
02096                    rs->is_bad_directory?" BadDirectory":"",
02097                    rs->is_bad_exit?" BadExit":"",
02098                    rs->is_exit?" Exit":"",
02099                    rs->is_fast?" Fast":"",
02100                    rs->is_possible_guard?" Guard":"",
02101                    rs->is_hs_dir?" HSDir":"",
02102                    rs->is_named?" Named":"",
02103                    rs->is_flagged_running?" Running":"",
02104                    rs->is_stable?" Stable":"",
02105                    rs->is_unnamed?" Unnamed":"",
02106                    rs->is_v2_dir?" V2Dir":"",
02107                    rs->is_valid?" Valid":"");
02108   if (r<0) {
02109     log_warn(LD_BUG, "Not enough space in buffer.");
02110     return -1;
02111   }
02112   cp += strlen(cp);
02113 
02114   /* length of "opt v \n" */
02115 #define V_LINE_OVERHEAD 7
02116   if (version && strlen(version) < MAX_V_LINE_LEN - V_LINE_OVERHEAD) {
02117     if (tor_snprintf(cp, buf_len - (cp-buf), "opt v %s\n", version)<0) {
02118       log_warn(LD_BUG, "Unable to print router version.");
02119       return -1;
02120     }
02121     cp += strlen(cp);
02122   }
02123 
02124   if (format != NS_V2) {
02125     const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest);
02126     uint32_t bw;
02127 
02128     if (format != NS_CONTROL_PORT) {
02129       /* Blow up more or less nicely if we didn't get anything or not the
02130        * thing we expected.
02131        */
02132       if (!desc) {
02133         char id[HEX_DIGEST_LEN+1];
02134         char dd[HEX_DIGEST_LEN+1];
02135 
02136         base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN);
02137         base16_encode(dd, sizeof(dd), rs->descriptor_digest, DIGEST_LEN);
02138         log_warn(LD_BUG, "Cannot get any descriptor for %s "
02139             "(wanted descriptor %s).",
02140             id, dd);
02141         return -1;
02142       };
02143 
02144       /* This assert can fire for the control port, because
02145        * it can request NS documents before all descriptors
02146        * have been fetched. */
02147       if (tor_memneq(desc->cache_info.signed_descriptor_digest,
02148             rs->descriptor_digest,
02149             DIGEST_LEN)) {
02150         char rl_d[HEX_DIGEST_LEN+1];
02151         char rs_d[HEX_DIGEST_LEN+1];
02152         char id[HEX_DIGEST_LEN+1];
02153 
02154         base16_encode(rl_d, sizeof(rl_d),
02155             desc->cache_info.signed_descriptor_digest, DIGEST_LEN);
02156         base16_encode(rs_d, sizeof(rs_d), rs->descriptor_digest, DIGEST_LEN);
02157         base16_encode(id, sizeof(id), rs->identity_digest, DIGEST_LEN);
02158         log_err(LD_BUG, "descriptor digest in routerlist does not match "
02159             "the one in routerstatus: %s vs %s "
02160             "(router %s)\n",
02161             rl_d, rs_d, id);
02162 
02163         tor_assert(tor_memeq(desc->cache_info.signed_descriptor_digest,
02164               rs->descriptor_digest,
02165               DIGEST_LEN));
02166       };
02167     }
02168 
02169     if (format == NS_CONTROL_PORT && rs->has_bandwidth) {
02170       bw = rs->bandwidth;
02171     } else {
02172       tor_assert(desc);
02173       bw = router_get_advertised_bandwidth_capped(desc) / 1000;
02174     }
02175     r = tor_snprintf(cp, buf_len - (cp-buf),
02176                      "w Bandwidth=%d\n", bw);
02177 
02178     if (r<0) {
02179       log_warn(LD_BUG, "Not enough space in buffer.");
02180       return -1;
02181     }
02182     cp += strlen(cp);
02183     if (format == NS_V3_VOTE && rs->has_measured_bw) {
02184       *--cp = '\0'; /* Kill "\n" */
02185       r = tor_snprintf(cp, buf_len - (cp-buf),
02186                        " Measured=%d\n", rs->measured_bw);
02187       if (r<0) {
02188         log_warn(LD_BUG, "Not enough space in buffer for weight line.");
02189         return -1;
02190       }
02191       cp += strlen(cp);
02192     }
02193 
02194     if (desc) {
02195       summary = policy_summarize(desc->exit_policy);
02196       r = tor_snprintf(cp, buf_len - (cp-buf), "p %s\n", summary);
02197       if (r<0) {
02198         log_warn(LD_BUG, "Not enough space in buffer.");
02199         tor_free(summary);
02200         return -1;
02201       }
02202       cp += strlen(cp);
02203       tor_free(summary);
02204     }
02205   }
02206 
02207   return 0;
02208 }
02209 
02215 static int
02216 _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
02217 {
02218   routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
02219   int first_is_auth, second_is_auth;
02220   uint32_t bw_first, bw_second;
02221   const node_t *node_first, *node_second;
02222   int first_is_running, second_is_running;
02223 
02224   /* we return -1 if first should appear before second... that is,
02225    * if first is a better router. */
02226   if (first->addr < second->addr)
02227     return -1;
02228   else if (first->addr > second->addr)
02229     return 1;
02230 
02231   /* Potentially, this next bit could cause k n lg n memcmp calls.  But in
02232    * reality, we will almost never get here, since addresses will usually be
02233    * different. */
02234 
02235   first_is_auth =
02236     router_digest_is_trusted_dir(first->cache_info.identity_digest);
02237   second_is_auth =
02238     router_digest_is_trusted_dir(second->cache_info.identity_digest);
02239 
02240   if (first_is_auth && !second_is_auth)
02241     return -1;
02242   else if (!first_is_auth && second_is_auth)
02243     return 1;
02244 
02245   node_first = node_get_by_id(first->cache_info.identity_digest);
02246   node_second = node_get_by_id(second->cache_info.identity_digest);
02247   first_is_running = node_first && node_first->is_running;
02248   second_is_running = node_second && node_second->is_running;
02249 
02250   if (first_is_running && !second_is_running)
02251     return -1;
02252   else if (!first_is_running && second_is_running)
02253     return 1;
02254 
02255   bw_first = router_get_advertised_bandwidth(first);
02256   bw_second = router_get_advertised_bandwidth(second);
02257 
02258   if (bw_first > bw_second)
02259      return -1;
02260   else if (bw_first < bw_second)
02261     return 1;
02262 
02263   /* They're equal! Compare by identity digest, so there's a
02264    * deterministic order and we avoid flapping. */
02265   return fast_memcmp(first->cache_info.identity_digest,
02266                      second->cache_info.identity_digest,
02267                      DIGEST_LEN);
02268 }
02269 
02273 static digestmap_t *
02274 get_possible_sybil_list(const smartlist_t *routers)
02275 {
02276   const or_options_t *options = get_options();
02277   digestmap_t *omit_as_sybil;
02278   smartlist_t *routers_by_ip = smartlist_new();
02279   uint32_t last_addr;
02280   int addr_count;
02281   /* Allow at most this number of Tor servers on a single IP address, ... */
02282   int max_with_same_addr = options->AuthDirMaxServersPerAddr;
02283   /* ... unless it's a directory authority, in which case allow more. */
02284   int max_with_same_addr_on_authority = options->AuthDirMaxServersPerAuthAddr;
02285   if (max_with_same_addr <= 0)
02286     max_with_same_addr = INT_MAX;
02287   if (max_with_same_addr_on_authority <= 0)
02288     max_with_same_addr_on_authority = INT_MAX;
02289 
02290   smartlist_add_all(routers_by_ip, routers);
02291   smartlist_sort(routers_by_ip, _compare_routerinfo_by_ip_and_bw);
02292   omit_as_sybil = digestmap_new();
02293 
02294   last_addr = 0;
02295   addr_count = 0;
02296   SMARTLIST_FOREACH(routers_by_ip, routerinfo_t *, ri,
02297     {
02298       if (last_addr != ri->addr) {
02299         last_addr = ri->addr;
02300         addr_count = 1;
02301       } else if (++addr_count > max_with_same_addr) {
02302         if (!router_addr_is_trusted_dir(ri->addr) ||
02303             addr_count > max_with_same_addr_on_authority)
02304           digestmap_set(omit_as_sybil, ri->cache_info.identity_digest, ri);
02305       }
02306     });
02307 
02308   smartlist_free(routers_by_ip);
02309   return omit_as_sybil;
02310 }
02311 
02314 static int
02315 is_router_version_good_for_possible_guard(const char *platform)
02316 {
02317   static int parsed_versions_initialized = 0;
02318   static tor_version_t first_good_0_2_1_guard_version;
02319   static tor_version_t first_good_0_2_2_guard_version;
02320   static tor_version_t first_good_later_guard_version;
02321 
02322   tor_version_t router_version;
02323 
02324   /* XXX024 This block should be extracted into its own function. */
02325   /* XXXX Begin code copied from tor_version_as_new_as (in routerparse.c) */
02326   {
02327     char *s, *s2, *start;
02328     char tmp[128];
02329 
02330     tor_assert(platform);
02331 
02332     /* nonstandard Tor; be safe and say yes */
02333     if (strcmpstart(platform,"Tor "))
02334       return 1;
02335 
02336     start = (char *)eat_whitespace(platform+3);
02337     if (!*start) return 0;
02338     s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
02339     s2 = (char*)eat_whitespace(s);
02340     if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
02341       s = (char*)find_whitespace(s2);
02342 
02343     if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
02344       return 0;
02345     strlcpy(tmp, start, s-start+1);
02346 
02347     if (tor_version_parse(tmp, &router_version)<0) {
02348       log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
02349       return 1; /* be safe and say yes */
02350     }
02351   }
02352   /* XXXX End code copied from tor_version_as_new_as (in routerparse.c) */
02353 
02354   if (!parsed_versions_initialized) {
02355     /* CVE-2011-2769 was fixed on the relay side in Tor versions
02356      * 0.2.1.31, 0.2.2.34, and 0.2.3.6-alpha. */
02357     tor_assert(tor_version_parse("0.2.1.31",
02358                                  &first_good_0_2_1_guard_version)>=0);
02359     tor_assert(tor_version_parse("0.2.2.34",
02360                                  &first_good_0_2_2_guard_version)>=0);
02361     tor_assert(tor_version_parse("0.2.3.6-alpha",
02362                                  &first_good_later_guard_version)>=0);
02363 
02364     /* Don't parse these constant version strings once for every relay
02365      * for every vote. */
02366     parsed_versions_initialized = 1;
02367   }
02368 
02369   return ((tor_version_same_series(&first_good_0_2_1_guard_version,
02370                                    &router_version) &&
02371            tor_version_compare(&first_good_0_2_1_guard_version,
02372                                &router_version) <= 0) ||
02373           (tor_version_same_series(&first_good_0_2_2_guard_version,
02374                                    &router_version) &&
02375            tor_version_compare(&first_good_0_2_2_guard_version,
02376                                &router_version) <= 0) ||
02377           (tor_version_compare(&first_good_later_guard_version,
02378                                &router_version) <= 0));
02379 }
02380 
02388 void
02389 set_routerstatus_from_routerinfo(routerstatus_t *rs,
02390                                  node_t *node,
02391                                  routerinfo_t *ri,
02392                                  time_t now,
02393                                  int naming, int listbadexits,
02394                                  int listbaddirs, int vote_on_hsdirs)
02395 {
02396   const or_options_t *options = get_options();
02397   int unstable_version =
02398     !tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs");
02399   uint32_t routerbw = router_get_advertised_bandwidth(ri);
02400 
02401   memset(rs, 0, sizeof(routerstatus_t));
02402 
02403   rs->is_authority =
02404     router_digest_is_trusted_dir(ri->cache_info.identity_digest);
02405 
02406   /* Already set by compute_performance_thresholds. */
02407   rs->is_exit = node->is_exit;
02408   rs->is_stable = node->is_stable =
02409     router_is_active(ri, node, now) &&
02410     !dirserv_thinks_router_is_unreliable(now, ri, 1, 0) &&
02411     !unstable_version;
02412   rs->is_fast = node->is_fast =
02413     router_is_active(ri, node, now) &&
02414     !dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
02415   rs->is_flagged_running = node->is_running; /* computed above */
02416 
02417   if (naming) {
02418     uint32_t name_status = dirserv_get_name_status(
02419                                               node->identity, ri->nickname);
02420     rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
02421     rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
02422   }
02423   rs->is_valid = node->is_valid;
02424 
02425   if (node->is_fast &&
02426       ((options->AuthDirGuardBWGuarantee &&
02427         routerbw >= options->AuthDirGuardBWGuarantee) ||
02428        routerbw >= MIN(guard_bandwidth_including_exits,
02429                        guard_bandwidth_excluding_exits)) &&
02430       is_router_version_good_for_possible_guard(ri->platform)) {
02431     long tk = rep_hist_get_weighted_time_known(
02432                                       node->identity, now);
02433     double wfu = rep_hist_get_weighted_fractional_uptime(
02434                                       node->identity, now);
02435     rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
02436   } else {
02437     rs->is_possible_guard = 0;
02438   }
02439 
02440   rs->is_bad_directory = listbaddirs && node->is_bad_directory;
02441   rs->is_bad_exit = listbadexits && node->is_bad_exit;
02442   node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
02443   rs->is_hs_dir = vote_on_hsdirs && node->is_hs_dir;
02444   rs->is_v2_dir = ri->dir_port != 0;
02445 
02446   if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
02447     rs->is_named = rs->is_unnamed = 0;
02448 
02449   rs->published_on = ri->cache_info.published_on;
02450   memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
02451   memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
02452          DIGEST_LEN);
02453   rs->addr = ri->addr;
02454   strlcpy(rs->nickname, ri->nickname, sizeof(rs->nickname));
02455   rs->or_port = ri->or_port;
02456   rs->dir_port = ri->dir_port;
02457 }
02458 
02463 static void
02464 clear_status_flags_on_sybil(routerstatus_t *rs)
02465 {
02466   rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
02467     rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
02468     rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit =
02469     rs->is_bad_directory = 0;
02470   /* FFFF we might want some mechanism to check later on if we
02471    * missed zeroing any flags: it's easy to add a new flag but
02472    * forget to add it to this clause. */
02473 }
02474 
02480 int
02481 measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line)
02482 {
02483   char *line = tor_strdup(orig_line);
02484   char *cp = line;
02485   int got_bw = 0;
02486   int got_node_id = 0;
02487   char *strtok_state; /* lame sauce d'jour */
02488   cp = tor_strtok_r(cp, " \t", &strtok_state);
02489 
02490   if (!cp) {
02491     log_warn(LD_DIRSERV, "Invalid line in bandwidth file: %s",
02492              escaped(orig_line));
02493     tor_free(line);
02494     return -1;
02495   }
02496 
02497   if (orig_line[strlen(orig_line)-1] != '\n') {
02498     log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s",
02499              escaped(orig_line));
02500     tor_free(line);
02501     return -1;
02502   }
02503 
02504   do {
02505     if (strcmpstart(cp, "bw=") == 0) {
02506       int parse_ok = 0;
02507       char *endptr;
02508       if (got_bw) {
02509         log_warn(LD_DIRSERV, "Double bw= in bandwidth file line: %s",
02510                  escaped(orig_line));
02511         tor_free(line);
02512         return -1;
02513       }
02514       cp+=strlen("bw=");
02515 
02516       out->bw = tor_parse_long(cp, 0, 0, LONG_MAX, &parse_ok, &endptr);
02517       if (!parse_ok || (*endptr && !TOR_ISSPACE(*endptr))) {
02518         log_warn(LD_DIRSERV, "Invalid bandwidth in bandwidth file line: %s",
02519                  escaped(orig_line));
02520         tor_free(line);
02521         return -1;
02522       }
02523       got_bw=1;
02524     } else if (strcmpstart(cp, "node_id=$") == 0) {
02525       if (got_node_id) {
02526         log_warn(LD_DIRSERV, "Double node_id= in bandwidth file line: %s",
02527                  escaped(orig_line));
02528         tor_free(line);
02529         return -1;
02530       }
02531       cp+=strlen("node_id=$");
02532 
02533       if (strlen(cp) != HEX_DIGEST_LEN ||
02534           base16_decode(out->node_id, DIGEST_LEN, cp, HEX_DIGEST_LEN)) {
02535         log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s",
02536                  escaped(orig_line));
02537         tor_free(line);
02538         return -1;
02539       }
02540       strlcpy(out->node_hex, cp, sizeof(out->node_hex));
02541       got_node_id=1;
02542     }
02543   } while ((cp = tor_strtok_r(NULL, " \t", &strtok_state)));
02544 
02545   if (got_bw && got_node_id) {
02546     tor_free(line);
02547     return 0;
02548   } else {
02549     log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s",
02550              escaped(orig_line));
02551     tor_free(line);
02552     return -1;
02553   }
02554 }
02555 
02561 int
02562 measured_bw_line_apply(measured_bw_line_t *parsed_line,
02563                        smartlist_t *routerstatuses)
02564 {
02565   routerstatus_t *rs = NULL;
02566   if (!routerstatuses)
02567     return 0;
02568 
02569   rs = smartlist_bsearch(routerstatuses, parsed_line->node_id,
02570                          compare_digest_to_routerstatus_entry);
02571 
02572   if (rs) {
02573     rs->has_measured_bw = 1;
02574     rs->measured_bw = (uint32_t)parsed_line->bw;
02575   } else {
02576     log_info(LD_DIRSERV, "Node ID %s not found in routerstatus list",
02577              parsed_line->node_hex);
02578   }
02579 
02580   return rs != NULL;
02581 }
02582 
02587 int
02588 dirserv_read_measured_bandwidths(const char *from_file,
02589                                  smartlist_t *routerstatuses)
02590 {
02591   char line[256];
02592   FILE *fp = tor_fopen_cloexec(from_file, "r");
02593   int applied_lines = 0;
02594   time_t file_time;
02595   int ok;
02596   if (fp == NULL) {
02597     log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s",
02598              from_file);
02599     return -1;
02600   }
02601 
02602   if (!fgets(line, sizeof(line), fp)
02603           || !strlen(line) || line[strlen(line)-1] != '\n') {
02604     log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s",
02605              escaped(line));
02606     fclose(fp);
02607     return -1;
02608   }
02609 
02610   line[strlen(line)-1] = '\0';
02611   file_time = tor_parse_ulong(line, 10, 0, ULONG_MAX, &ok, NULL);
02612   if (!ok) {
02613     log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s",
02614              escaped(line));
02615     fclose(fp);
02616     return -1;
02617   }
02618 
02619   if ((time(NULL) - file_time) > MAX_MEASUREMENT_AGE) {
02620     log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u",
02621              (unsigned)(time(NULL) - file_time));
02622     fclose(fp);
02623     return -1;
02624   }
02625 
02626   if (routerstatuses)
02627     smartlist_sort(routerstatuses, compare_routerstatus_entries);
02628 
02629   while (!feof(fp)) {
02630     measured_bw_line_t parsed_line;
02631     if (fgets(line, sizeof(line), fp) && strlen(line)) {
02632       if (measured_bw_line_parse(&parsed_line, line) != -1) {
02633         if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0)
02634           applied_lines++;
02635       }
02636     }
02637   }
02638 
02639   fclose(fp);
02640   log_info(LD_DIRSERV,
02641            "Bandwidth measurement file successfully read. "
02642            "Applied %d measurements.", applied_lines);
02643   return 0;
02644 }
02645 
02648 networkstatus_t *
02649 dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
02650                                         authority_cert_t *cert)
02651 {
02652   const or_options_t *options = get_options();
02653   networkstatus_t *v3_out = NULL;
02654   uint32_t addr;
02655   char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
02656   const char *contact;
02657   smartlist_t *routers, *routerstatuses;
02658   char identity_digest[DIGEST_LEN];
02659   char signing_key_digest[DIGEST_LEN];
02660   int naming = options->NamingAuthoritativeDir;
02661   int listbadexits = options->AuthDirListBadExits;
02662   int listbaddirs = options->AuthDirListBadDirs;
02663   int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2;
02664   routerlist_t *rl = router_get_routerlist();
02665   time_t now = time(NULL);
02666   time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
02667   networkstatus_voter_info_t *voter = NULL;
02668   vote_timing_t timing;
02669   digestmap_t *omit_as_sybil = NULL;
02670   const int vote_on_reachability = running_long_enough_to_decide_unreachable();
02671   smartlist_t *microdescriptors = NULL;
02672 
02673   tor_assert(private_key);
02674   tor_assert(cert);
02675 
02676   if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) {
02677     log_warn(LD_NET, "Couldn't resolve my hostname");
02678     return NULL;
02679   }
02680   if (!strchr(hostname, '.')) {
02681     tor_free(hostname);
02682     hostname = tor_dup_ip(addr);
02683   }
02684   if (crypto_pk_get_digest(private_key, signing_key_digest)<0) {
02685     log_err(LD_BUG, "Error computing signing key digest");
02686     return NULL;
02687   }
02688   if (crypto_pk_get_digest(cert->identity_key, identity_digest)<0) {
02689     log_err(LD_BUG, "Error computing identity key digest");
02690     return NULL;
02691   }
02692 
02693   if (options->VersioningAuthoritativeDir) {
02694     client_versions = format_versions_list(options->RecommendedClientVersions);
02695     server_versions = format_versions_list(options->RecommendedServerVersions);
02696   }
02697 
02698   contact = get_options()->ContactInfo;
02699   if (!contact)
02700     contact = "(none)";
02701 
02702   /* precompute this part, since we need it to decide what "stable"
02703    * means. */
02704   SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
02705     dirserv_set_router_is_running(ri, now);
02706   });
02707 
02708   dirserv_compute_performance_thresholds(rl);
02709 
02710   routers = smartlist_new();
02711   smartlist_add_all(routers, rl->routers);
02712   routers_sort_by_identity(routers);
02713   omit_as_sybil = get_possible_sybil_list(routers);
02714 
02715   routerstatuses = smartlist_new();
02716   microdescriptors = smartlist_new();
02717 
02718   SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
02719     if (ri->cache_info.published_on >= cutoff) {
02720       routerstatus_t *rs;
02721       vote_routerstatus_t *vrs;
02722       microdesc_t *md;
02723       node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
02724       if (!node)
02725         continue;
02726 
02727       vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
02728       rs = &vrs->status;
02729       set_routerstatus_from_routerinfo(rs, node, ri, now,
02730                                        naming, listbadexits, listbaddirs,
02731                                        vote_on_hsdirs);
02732 
02733       if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
02734         clear_status_flags_on_sybil(rs);
02735 
02736       if (!vote_on_reachability)
02737         rs->is_flagged_running = 0;
02738 
02739       vrs->version = version_from_platform(ri->platform);
02740       md = dirvote_create_microdescriptor(ri);
02741       if (md) {
02742         char buf[128];
02743         vote_microdesc_hash_t *h;
02744         dirvote_format_microdesc_vote_line(buf, sizeof(buf), md);
02745         h = tor_malloc(sizeof(vote_microdesc_hash_t));
02746         h->microdesc_hash_line = tor_strdup(buf);
02747         h->next = NULL;
02748         vrs->microdesc = h;
02749         md->last_listed = now;
02750         smartlist_add(microdescriptors, md);
02751       }
02752 
02753       smartlist_add(routerstatuses, vrs);
02754     }
02755   } SMARTLIST_FOREACH_END(ri);
02756 
02757   {
02758     smartlist_t *added =
02759       microdescs_add_list_to_cache(get_microdesc_cache(),
02760                                    microdescriptors, SAVED_NOWHERE, 0);
02761     smartlist_free(added);
02762     smartlist_free(microdescriptors);
02763   }
02764 
02765   smartlist_free(routers);
02766   digestmap_free(omit_as_sybil, NULL);
02767 
02768   if (options->V3BandwidthsFile) {
02769     dirserv_read_measured_bandwidths(options->V3BandwidthsFile,
02770                                      routerstatuses);
02771   }
02772 
02773   v3_out = tor_malloc_zero(sizeof(networkstatus_t));
02774 
02775   v3_out->type = NS_TYPE_VOTE;
02776   dirvote_get_preferred_voting_intervals(&timing);
02777   v3_out->published = now;
02778   {
02779     char tbuf[ISO_TIME_LEN+1];
02780     networkstatus_t *current_consensus =
02781       networkstatus_get_live_consensus(now);
02782     long last_consensus_interval; /* only used to pick a valid_after */
02783     if (current_consensus)
02784       last_consensus_interval = current_consensus->fresh_until -
02785         current_consensus->valid_after;
02786     else
02787       last_consensus_interval = options->TestingV3AuthInitialVotingInterval;
02788     v3_out->valid_after =
02789       dirvote_get_start_of_next_interval(now, (int)last_consensus_interval);
02790     format_iso_time(tbuf, v3_out->valid_after);
02791     log_notice(LD_DIR,"Choosing valid-after time in vote as %s: "
02792                "consensus_set=%d, last_interval=%d",
02793                tbuf, current_consensus?1:0, (int)last_consensus_interval);
02794   }
02795   v3_out->fresh_until = v3_out->valid_after + timing.vote_interval;
02796   v3_out->valid_until = v3_out->valid_after +
02797     (timing.vote_interval * timing.n_intervals_valid);
02798   v3_out->vote_seconds = timing.vote_delay;
02799   v3_out->dist_seconds = timing.dist_delay;
02800   tor_assert(v3_out->vote_seconds > 0);
02801   tor_assert(v3_out->dist_seconds > 0);
02802   tor_assert(timing.n_intervals_valid > 0);
02803 
02804   v3_out->client_versions = client_versions;
02805   v3_out->server_versions = server_versions;
02806   v3_out->known_flags = smartlist_new();
02807   smartlist_split_string(v3_out->known_flags,
02808                 "Authority Exit Fast Guard Stable V2Dir Valid",
02809                 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
02810   if (vote_on_reachability)
02811     smartlist_add(v3_out->known_flags, tor_strdup("Running"));
02812   if (listbaddirs)
02813     smartlist_add(v3_out->known_flags, tor_strdup("BadDirectory"));
02814   if (listbadexits)
02815     smartlist_add(v3_out->known_flags, tor_strdup("BadExit"));
02816   if (naming) {
02817     smartlist_add(v3_out->known_flags, tor_strdup("Named"));
02818     smartlist_add(v3_out->known_flags, tor_strdup("Unnamed"));
02819   }
02820   if (vote_on_hsdirs)
02821     smartlist_add(v3_out->known_flags, tor_strdup("HSDir"));
02822   smartlist_sort_strings(v3_out->known_flags);
02823 
02824   if (options->ConsensusParams) {
02825     v3_out->net_params = smartlist_new();
02826     smartlist_split_string(v3_out->net_params,
02827                            options->ConsensusParams, NULL, 0, 0);
02828     smartlist_sort_strings(v3_out->net_params);
02829   }
02830 
02831   voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
02832   voter->nickname = tor_strdup(options->Nickname);
02833   memcpy(voter->identity_digest, identity_digest, DIGEST_LEN);
02834   voter->sigs = smartlist_new();
02835   voter->address = hostname;
02836   voter->addr = addr;
02837   voter->dir_port = router_get_advertised_dir_port(options, 0);
02838   voter->or_port = router_get_advertised_or_port(options);
02839   voter->contact = tor_strdup(contact);
02840   if (options->V3AuthUseLegacyKey) {
02841     authority_cert_t *c = get_my_v3_legacy_cert();
02842     if (c) {
02843       if (crypto_pk_get_digest(c->identity_key, voter->legacy_id_digest)) {
02844         log_warn(LD_BUG, "Unable to compute digest of legacy v3 identity key");
02845         memset(voter->legacy_id_digest, 0, DIGEST_LEN);
02846       }
02847     }
02848   }
02849 
02850   v3_out->voters = smartlist_new();
02851   smartlist_add(v3_out->voters, voter);
02852   v3_out->cert = authority_cert_dup(cert);
02853   v3_out->routerstatus_list = routerstatuses;
02854   /* Note: networkstatus_digest is unset; it won't get set until we actually
02855    * format the vote. */
02856 
02857   return v3_out;
02858 }
02859 
02863 static cached_dir_t *
02864 generate_v2_networkstatus_opinion(void)
02865 {
02866   cached_dir_t *r = NULL;
02867   size_t len, identity_pkey_len;
02868   char *status = NULL, *client_versions = NULL, *server_versions = NULL,
02869     *identity_pkey = NULL, *hostname = NULL;
02870   char *outp, *endp;
02871   const or_options_t *options = get_options();
02872   char fingerprint[FINGERPRINT_LEN+1];
02873   char published[ISO_TIME_LEN+1];
02874   char digest[DIGEST_LEN];
02875   uint32_t addr;
02876   crypto_pk_t *private_key;
02877   routerlist_t *rl = router_get_routerlist();
02878   time_t now = time(NULL);
02879   time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
02880   int naming = options->NamingAuthoritativeDir;
02881   int versioning = options->VersioningAuthoritativeDir;
02882   int listbaddirs = options->AuthDirListBadDirs;
02883   int listbadexits = options->AuthDirListBadExits;
02884   int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2;
02885   const char *contact;
02886   char *version_lines = NULL;
02887   smartlist_t *routers = NULL;
02888   digestmap_t *omit_as_sybil = NULL;
02889 
02890   private_key = get_server_identity_key();
02891 
02892   if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) {
02893     log_warn(LD_NET, "Couldn't resolve my hostname");
02894     goto done;
02895   }
02896 
02897   format_iso_time(published, now);
02898 
02899   client_versions = format_versions_list(options->RecommendedClientVersions);
02900   server_versions = format_versions_list(options->RecommendedServerVersions);
02901 
02902   if (crypto_pk_write_public_key_to_string(private_key, &identity_pkey,
02903                                            &identity_pkey_len)<0) {
02904     log_warn(LD_BUG,"Writing public key to string failed.");
02905     goto done;
02906   }
02907 
02908   if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) {
02909     log_err(LD_BUG, "Error computing fingerprint");
02910     goto done;
02911   }
02912 
02913   contact = options->ContactInfo;
02914   if (!contact)
02915     contact = "(none)";
02916 
02917   if (versioning) {
02918     tor_asprintf(&version_lines,
02919                  "client-versions %s\nserver-versions %s\n",
02920                  client_versions, server_versions);
02921   } else {
02922     version_lines = tor_strdup("");
02923   }
02924 
02925   len = 4096+strlen(client_versions)+strlen(server_versions);
02926   len += identity_pkey_len*2;
02927   len += (RS_ENTRY_LEN)*smartlist_len(rl->routers);
02928 
02929   status = tor_malloc(len);
02930   tor_snprintf(status, len,
02931                "network-status-version 2\n"
02932                "dir-source %s %s %d\n"
02933                "fingerprint %s\n"
02934                "contact %s\n"
02935                "published %s\n"
02936                "dir-options%s%s%s%s\n"
02937                "%s" /* client version line, server version line. */
02938                "dir-signing-key\n%s",
02939                hostname, fmt_addr32(addr),
02940                (int)router_get_advertised_dir_port(options, 0),
02941                fingerprint,
02942                contact,
02943                published,
02944                naming ? " Names" : "",
02945                listbaddirs ? " BadDirectories" : "",
02946                listbadexits ? " BadExits" : "",
02947                versioning ? " Versions" : "",
02948                version_lines,
02949                identity_pkey);
02950   outp = status + strlen(status);
02951   endp = status + len;
02952 
02953   /* precompute this part, since we need it to decide what "stable"
02954    * means. */
02955   SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
02956     dirserv_set_router_is_running(ri, now);
02957   });
02958 
02959   dirserv_compute_performance_thresholds(rl);
02960 
02961   routers = smartlist_new();
02962   smartlist_add_all(routers, rl->routers);
02963   routers_sort_by_identity(routers);
02964 
02965   omit_as_sybil = get_possible_sybil_list(routers);
02966 
02967   SMARTLIST_FOREACH(routers, routerinfo_t *, ri, {
02968     if (ri->cache_info.published_on >= cutoff) {
02969       routerstatus_t rs;
02970       char *version = version_from_platform(ri->platform);
02971       node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
02972       if (!node) {
02973         tor_free(version);
02974         continue;
02975       }
02976       set_routerstatus_from_routerinfo(&rs, node, ri, now,
02977                                        naming, listbadexits, listbaddirs,
02978                                        vote_on_hsdirs);
02979 
02980       if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
02981         clear_status_flags_on_sybil(&rs);
02982 
02983       if (routerstatus_format_entry(outp, endp-outp, &rs, version, NS_V2)) {
02984         log_warn(LD_BUG, "Unable to print router status.");
02985         tor_free(version);
02986         goto done;
02987       }
02988       tor_free(version);
02989       outp += strlen(outp);
02990     }
02991   });
02992 
02993   if (tor_snprintf(outp, endp-outp, "directory-signature %s\n",
02994                    options->Nickname)<0) {
02995     log_warn(LD_BUG, "Unable to write signature line.");
02996     goto done;
02997   }
02998   if (router_get_networkstatus_v2_hash(status, digest)<0) {
02999     log_warn(LD_BUG, "Unable to hash network status");
03000     goto done;
03001   }
03002   outp += strlen(outp);
03003 
03004   note_crypto_pk_op(SIGN_DIR);
03005   if (router_append_dirobj_signature(outp,endp-outp,digest,DIGEST_LEN,
03006                                      private_key)<0) {
03007     log_warn(LD_BUG, "Unable to sign router status.");
03008     goto done;
03009   }
03010 
03011   {
03012     networkstatus_v2_t *ns;
03013     if (!(ns = networkstatus_v2_parse_from_string(status))) {
03014       log_err(LD_BUG,"Generated a networkstatus we couldn't parse.");
03015       goto done;
03016     }
03017     networkstatus_v2_free(ns);
03018   }
03019 
03020   {
03021     cached_dir_t **ns_ptr = &the_v2_networkstatus;
03022     if (*ns_ptr)
03023       cached_dir_decref(*ns_ptr);
03024     *ns_ptr = new_cached_dir(status, now);
03025     status = NULL; /* So it doesn't get double-freed. */
03026     the_v2_networkstatus_is_dirty = 0;
03027     router_set_networkstatus_v2((*ns_ptr)->dir, now, NS_GENERATED, NULL);
03028     r = *ns_ptr;
03029   }
03030 
03031  done:
03032   tor_free(client_versions);
03033   tor_free(server_versions);
03034   tor_free(version_lines);
03035   tor_free(status);
03036   tor_free(hostname);
03037   tor_free(identity_pkey);
03038   smartlist_free(routers);
03039   digestmap_free(omit_as_sybil, NULL);
03040   return r;
03041 }
03042 
03046 void
03047 dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
03048                                           const char *key)
03049 {
03050   tor_assert(result);
03051 
03052   if (!cached_v2_networkstatus)
03053     cached_v2_networkstatus = digestmap_new();
03054 
03055   if (should_generate_v2_networkstatus())
03056     generate_v2_networkstatus_opinion();
03057 
03058   if (!strcmp(key,"authority")) {
03059     if (authdir_mode_v2(get_options())) {
03060       const routerinfo_t *me = router_get_my_routerinfo();
03061       if (me)
03062         smartlist_add(result,
03063                       tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
03064     }
03065   } else if (!strcmp(key, "all")) {
03066     if (digestmap_size(cached_v2_networkstatus)) {
03067       digestmap_iter_t *iter;
03068       iter = digestmap_iter_init(cached_v2_networkstatus);
03069       while (!digestmap_iter_done(iter)) {
03070         const char *ident;
03071         void *val;
03072         digestmap_iter_get(iter, &ident, &val);
03073         smartlist_add(result, tor_memdup(ident, DIGEST_LEN));
03074         iter = digestmap_iter_next(cached_v2_networkstatus, iter);
03075       }
03076     } else {
03077       SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
03078                   trusted_dir_server_t *, ds,
03079                   if (ds->type & V2_DIRINFO)
03080                     smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN)));
03081     }
03082     smartlist_sort_digests(result);
03083     if (smartlist_len(result) == 0)
03084       log_info(LD_DIRSERV,
03085                "Client requested 'all' network status objects; we have none.");
03086   } else if (!strcmpstart(key, "fp/")) {
03087     dir_split_resource_into_fingerprints(key+3, result, NULL,
03088                                          DSR_HEX|DSR_SORT_UNIQ);
03089   }
03090 }
03091 
03097 void
03098 dirserv_get_networkstatus_v2(smartlist_t *result,
03099                              const char *key)
03100 {
03101   cached_dir_t *cached;
03102   smartlist_t *fingerprints = smartlist_new();
03103   tor_assert(result);
03104 
03105   if (!cached_v2_networkstatus)
03106     cached_v2_networkstatus = digestmap_new();
03107 
03108   dirserv_get_networkstatus_v2_fingerprints(fingerprints, key);
03109   SMARTLIST_FOREACH(fingerprints, const char *, fp,
03110     {
03111       if (router_digest_is_me(fp) && should_generate_v2_networkstatus())
03112         generate_v2_networkstatus_opinion();
03113       cached = digestmap_get(cached_v2_networkstatus, fp);
03114       if (cached) {
03115         smartlist_add(result, cached);
03116       } else {
03117         char hexbuf[HEX_DIGEST_LEN+1];
03118         base16_encode(hexbuf, sizeof(hexbuf), fp, DIGEST_LEN);
03119         log_info(LD_DIRSERV, "Don't know about any network status with "
03120                  "fingerprint '%s'", hexbuf);
03121       }
03122     });
03123   SMARTLIST_FOREACH(fingerprints, char *, cp, tor_free(cp));
03124   smartlist_free(fingerprints);
03125 }
03126 
03132 int
03133 dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
03134                                     const char **msg, int for_unencrypted_conn,
03135                                     int is_extrainfo)
03136 {
03137   int by_id = 1;
03138   *msg = NULL;
03139 
03140   if (!strcmp(key, "all")) {
03141     routerlist_t *rl = router_get_routerlist();
03142     SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
03143                       smartlist_add(fps_out,
03144                       tor_memdup(r->cache_info.identity_digest, DIGEST_LEN)));
03145     /* Treat "all" requests as if they were unencrypted */
03146     for_unencrypted_conn = 1;
03147   } else if (!strcmp(key, "authority")) {
03148     const routerinfo_t *ri = router_get_my_routerinfo();
03149     if (ri)
03150       smartlist_add(fps_out,
03151                     tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN));
03152   } else if (!strcmpstart(key, "d/")) {
03153     by_id = 0;
03154     key += strlen("d/");
03155     dir_split_resource_into_fingerprints(key, fps_out, NULL,
03156                                          DSR_HEX|DSR_SORT_UNIQ);
03157   } else if (!strcmpstart(key, "fp/")) {
03158     key += strlen("fp/");
03159     dir_split_resource_into_fingerprints(key, fps_out, NULL,
03160                                          DSR_HEX|DSR_SORT_UNIQ);
03161   } else {
03162     *msg = "Key not recognized";
03163     return -1;
03164   }
03165 
03166   if (for_unencrypted_conn) {
03167     /* Remove anything that insists it not be sent unencrypted. */
03168     SMARTLIST_FOREACH_BEGIN(fps_out, char *, cp) {
03169         const signed_descriptor_t *sd;
03170         if (by_id)
03171           sd = get_signed_descriptor_by_fp(cp,is_extrainfo,0);
03172         else if (is_extrainfo)
03173           sd = extrainfo_get_by_descriptor_digest(cp);
03174         else
03175           sd = router_get_by_descriptor_digest(cp);
03176         if (sd && !sd->send_unencrypted) {
03177           tor_free(cp);
03178           SMARTLIST_DEL_CURRENT(fps_out, cp);
03179         }
03180     } SMARTLIST_FOREACH_END(cp);
03181   }
03182 
03183   if (!smartlist_len(fps_out)) {
03184     *msg = "Servers unavailable";
03185     return -1;
03186   }
03187   return 0;
03188 }
03189 
03208 int
03209 dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
03210                         const char **msg)
03211 {
03212   *msg = NULL;
03213 
03214   if (!strcmp(key, "/tor/server/all")) {
03215     routerlist_t *rl = router_get_routerlist();
03216     SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
03217                       smartlist_add(descs_out, &(r->cache_info)));
03218   } else if (!strcmp(key, "/tor/server/authority")) {
03219     const routerinfo_t *ri = router_get_my_routerinfo();
03220     if (ri)
03221       smartlist_add(descs_out, (void*) &(ri->cache_info));
03222   } else if (!strcmpstart(key, "/tor/server/d/")) {
03223     smartlist_t *digests = smartlist_new();
03224     key += strlen("/tor/server/d/");
03225     dir_split_resource_into_fingerprints(key, digests, NULL,
03226                                          DSR_HEX|DSR_SORT_UNIQ);
03227     SMARTLIST_FOREACH(digests, const char *, d,
03228        {
03229          signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
03230          if (sd)
03231            smartlist_add(descs_out,sd);
03232        });
03233     SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
03234     smartlist_free(digests);
03235   } else if (!strcmpstart(key, "/tor/server/fp/")) {
03236     smartlist_t *digests = smartlist_new();
03237     time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
03238     key += strlen("/tor/server/fp/");
03239     dir_split_resource_into_fingerprints(key, digests, NULL,
03240                                          DSR_HEX|DSR_SORT_UNIQ);
03241     SMARTLIST_FOREACH(digests, const char *, d,
03242        {
03243          if (router_digest_is_me(d)) {
03244            /* make sure desc_routerinfo exists */
03245            const routerinfo_t *ri = router_get_my_routerinfo();
03246            if (ri)
03247              smartlist_add(descs_out, (void*) &(ri->cache_info));
03248          } else {
03249            const routerinfo_t *ri = router_get_by_id_digest(d);
03250            /* Don't actually serve a descriptor that everyone will think is
03251             * expired.  This is an (ugly) workaround to keep buggy 0.1.1.10
03252             * Tors from downloading descriptors that they will throw away.
03253             */
03254            if (ri && ri->cache_info.published_on > cutoff)
03255              smartlist_add(descs_out, (void*) &(ri->cache_info));
03256          }
03257        });
03258     SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
03259     smartlist_free(digests);
03260   } else {
03261     *msg = "Key not recognized";
03262     return -1;
03263   }
03264 
03265   if (!smartlist_len(descs_out)) {
03266     *msg = "Servers unavailable";
03267     return -1;
03268   }
03269   return 0;
03270 }
03271 
03278 void
03279 dirserv_orconn_tls_done(const char *address,
03280                         uint16_t or_port,
03281                         const char *digest_rcvd)
03282 {
03283   routerinfo_t *ri;
03284   time_t now = time(NULL);
03285   tor_assert(address);
03286   tor_assert(digest_rcvd);
03287 
03288   ri = router_get_mutable_by_digest(digest_rcvd);
03289 
03290   if (ri == NULL)
03291     return;
03292 
03293   if (!strcasecmp(address, ri->address) && or_port == ri->or_port) {
03294     /* Found the right router.  */
03295     if (!authdir_mode_bridge(get_options()) ||
03296         ri->purpose == ROUTER_PURPOSE_BRIDGE) {
03297       /* This is a bridge or we're not a bridge authorititative --
03298          mark it as reachable.  */
03299       tor_addr_t addr, *addrp=NULL;
03300       log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.",
03301                router_describe(ri),
03302                address, ri->or_port);
03303       if (tor_addr_parse(&addr, ri->address) != -1)
03304         addrp = &addr;
03305       else
03306         log_warn(LD_BUG, "Couldn't parse IP address \"%s\"", ri->address);
03307       rep_hist_note_router_reachable(digest_rcvd, addrp, or_port, now);
03308       ri->last_reachable = now;
03309     }
03310   }
03311 }
03312 
03316 int
03317 dirserv_should_launch_reachability_test(const routerinfo_t *ri,
03318                                         const routerinfo_t *ri_old)
03319 {
03320   if (!authdir_mode_handles_descs(get_options(), ri->purpose))
03321     return 0;
03322   if (!ri_old) {
03323     /* New router: Launch an immediate reachability test, so we will have an
03324      * opinion soon in case we're generating a consensus soon */
03325     return 1;
03326   }
03327   if (ri_old->is_hibernating && !ri->is_hibernating) {
03328     /* It just came out of hibernation; launch a reachability test */
03329     return 1;
03330   }
03331   if (! routers_have_same_or_addr(ri, ri_old)) {
03332     /* Address or port changed; launch a reachability test */
03333     return 1;
03334   }
03335   return 0;
03336 }
03337 
03341 void
03342 dirserv_single_reachability_test(time_t now, routerinfo_t *router)
03343 {
03344   tor_addr_t router_addr;
03345   log_debug(LD_OR,"Testing reachability of %s at %s:%u.",
03346             router->nickname, router->address, router->or_port);
03347   /* Remember when we started trying to determine reachability */
03348   if (!router->testing_since)
03349     router->testing_since = now;
03350   tor_addr_from_ipv4h(&router_addr, router->addr);
03351   connection_or_connect(&router_addr, router->or_port,
03352                         router->cache_info.identity_digest);
03353 }
03354 
03362 void
03363 dirserv_test_reachability(time_t now)
03364 {
03365   /* XXX decide what to do here; see or-talk thread "purging old router
03366    * information, revocation." -NM
03367    * We can't afford to mess with this in 0.1.2.x. The reason is that
03368    * if we stop doing reachability tests on some of routerlist, then
03369    * we'll for-sure think they're down, which may have unexpected
03370    * effects in other parts of the code. It doesn't hurt much to do
03371    * the testing, and directory authorities are easy to upgrade. Let's
03372    * wait til 0.2.0. -RD */
03373 //  time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
03374   routerlist_t *rl = router_get_routerlist();
03375   static char ctr = 0;
03376   int bridge_auth = authdir_mode_bridge(get_options());
03377 
03378   SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, router) {
03379     const char *id_digest = router->cache_info.identity_digest;
03380     if (router_is_me(router))
03381       continue;
03382     if (bridge_auth && router->purpose != ROUTER_PURPOSE_BRIDGE)
03383       continue; /* bridge authorities only test reachability on bridges */
03384 //    if (router->cache_info.published_on > cutoff)
03385 //      continue;
03386     if ((((uint8_t)id_digest[0]) % REACHABILITY_MODULO_PER_TEST) == ctr) {
03387       dirserv_single_reachability_test(now, router);
03388     }
03389   } SMARTLIST_FOREACH_END(router);
03390   ctr = (ctr + 1) % REACHABILITY_MODULO_PER_TEST; /* increment ctr */
03391 }
03392 
03397 static cached_dir_t *
03398 lookup_cached_dir_by_fp(const char *fp)
03399 {
03400   cached_dir_t *d = NULL;
03401   if (tor_digest_is_zero(fp) && cached_consensuses)
03402     d = strmap_get(cached_consensuses, "ns");
03403   else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses &&
03404            (d = strmap_get(cached_consensuses, fp))) {
03405     /* this here interface is a nasty hack XXXX024 */;
03406   } else if (router_digest_is_me(fp) && the_v2_networkstatus)
03407     d = the_v2_networkstatus;
03408   else if (cached_v2_networkstatus)
03409     d = digestmap_get(cached_v2_networkstatus, fp);
03410   return d;
03411 }
03412 
03419 int
03420 dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff)
03421 {
03422   int found_any = 0;
03423   SMARTLIST_FOREACH(fps, char *, digest,
03424   {
03425     cached_dir_t *d = lookup_cached_dir_by_fp(digest);
03426     if (!d)
03427       continue;
03428     found_any = 1;
03429     if (d->published <= cutoff) {
03430       tor_free(digest);
03431       SMARTLIST_DEL_CURRENT(fps, digest);
03432     }
03433   });
03434 
03435   return found_any;
03436 }
03437 
03442 static const signed_descriptor_t *
03443 get_signed_descriptor_by_fp(const char *fp, int extrainfo,
03444                             time_t publish_cutoff)
03445 {
03446   if (router_digest_is_me(fp)) {
03447     if (extrainfo)
03448       return &(router_get_my_extrainfo()->cache_info);
03449     else
03450       return &(router_get_my_routerinfo()->cache_info);
03451   } else {
03452     const routerinfo_t *ri = router_get_by_id_digest(fp);
03453     if (ri &&
03454         ri->cache_info.published_on > publish_cutoff) {
03455       if (extrainfo)
03456         return extrainfo_get_by_descriptor_digest(
03457                                      ri->cache_info.extra_info_digest);
03458       else
03459         return &ri->cache_info;
03460     }
03461   }
03462   return NULL;
03463 }
03464 
03468 int
03469 dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src)
03470 {
03471   time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH;
03472   SMARTLIST_FOREACH(fps, const char *, fp, {
03473       switch (spool_src)
03474       {
03475         case DIR_SPOOL_EXTRA_BY_DIGEST:
03476           if (extrainfo_get_by_descriptor_digest(fp)) return 1;
03477           break;
03478         case DIR_SPOOL_SERVER_BY_DIGEST:
03479           if (router_get_by_descriptor_digest(fp)) return 1;
03480           break;
03481         case DIR_SPOOL_EXTRA_BY_FP:
03482         case DIR_SPOOL_SERVER_BY_FP:
03483           if (get_signed_descriptor_by_fp(fp,
03484                 spool_src == DIR_SPOOL_EXTRA_BY_FP, publish_cutoff))
03485             return 1;
03486           break;
03487       }
03488   });
03489   return 0;
03490 }
03491 
03494 int
03495 dirserv_have_any_microdesc(const smartlist_t *fps)
03496 {
03497   microdesc_cache_t *cache = get_microdesc_cache();
03498   SMARTLIST_FOREACH(fps, const char *, fp,
03499                     if (microdesc_cache_lookup_by_digest256(cache, fp))
03500                       return 1);
03501   return 0;
03502 }
03503 
03512 size_t
03513 dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
03514                            int compressed)
03515 {
03516   size_t result;
03517   tor_assert(fps);
03518   if (is_serverdescs) {
03519     int n = smartlist_len(fps);
03520     const routerinfo_t *me = router_get_my_routerinfo();
03521     result = (me?me->cache_info.signed_descriptor_len:2048) * n;
03522     if (compressed)
03523       result /= 2; /* observed compressibility is between 35 and 55%. */
03524   } else {
03525     result = 0;
03526     SMARTLIST_FOREACH(fps, const char *, digest, {
03527         cached_dir_t *dir = lookup_cached_dir_by_fp(digest);
03528         if (dir)
03529           result += compressed ? dir->dir_z_len : dir->dir_len;
03530       });
03531   }
03532   return result;
03533 }
03534 
03537 size_t
03538 dirserv_estimate_microdesc_size(const smartlist_t *fps, int compressed)
03539 {
03540   size_t result = smartlist_len(fps) * microdesc_average_size(NULL);
03541   if (compressed)
03542     result /= 2;
03543   return result;
03544 }
03545 
03548 #define DIRSERV_BUFFER_MIN 16384
03549 
03553 static int
03554 connection_dirserv_finish_spooling(dir_connection_t *conn)
03555 {
03556   if (conn->zlib_state) {
03557     connection_write_to_buf_zlib("", 0, conn, 1);
03558     tor_zlib_free(conn->zlib_state);
03559     conn->zlib_state = NULL;
03560   }
03561   conn->dir_spool_src = DIR_SPOOL_NONE;
03562   return 0;
03563 }
03564 
03571 static int
03572 connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
03573 {
03574   int by_fp = (conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP ||
03575                conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP);
03576   int extra = (conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP ||
03577                conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_DIGEST);
03578   time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH;
03579 
03580   const or_options_t *options = get_options();
03581 
03582   while (smartlist_len(conn->fingerprint_stack) &&
03583          connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
03584     const char *body;
03585     char *fp = smartlist_pop_last(conn->fingerprint_stack);
03586     const signed_descriptor_t *sd = NULL;
03587     if (by_fp) {
03588       sd = get_signed_descriptor_by_fp(fp, extra, publish_cutoff);
03589     } else {
03590       sd = extra ? extrainfo_get_by_descriptor_digest(fp)
03591         : router_get_by_descriptor_digest(fp);
03592     }
03593     tor_free(fp);
03594     if (!sd)
03595       continue;
03596     if (!connection_dir_is_encrypted(conn) && !sd->send_unencrypted) {
03597       /* we did this check once before (so we could have an accurate size
03598        * estimate and maybe send a 404 if somebody asked for only bridges on a
03599        * connection), but we need to do it again in case a previously
03600        * unknown bridge descriptor has shown up between then and now. */
03601       continue;
03602     }
03603 
03606     if (options->BridgeAuthoritativeDir && by_fp) {
03607       const routerinfo_t *router =
03608           router_get_by_id_digest(sd->identity_digest);
03609       /* router can be NULL here when the bridge auth is asked for its own
03610        * descriptor. */
03611       if (router && router->purpose == ROUTER_PURPOSE_BRIDGE)
03612         rep_hist_note_desc_served(sd->identity_digest);
03613     }
03614     body = signed_descriptor_get_body(sd);
03615     if (conn->zlib_state) {
03616       /* XXXX024 This 'last' business should actually happen on the last
03617        * routerinfo, not on the last fingerprint. */
03618       int last = ! smartlist_len(conn->fingerprint_stack);
03619       connection_write_to_buf_zlib(body, sd->signed_descriptor_len, conn,
03620                                    last);
03621       if (last) {
03622         tor_zlib_free(conn->zlib_state);
03623         conn->zlib_state = NULL;
03624       }
03625     } else {
03626       connection_write_to_buf(body,
03627                               sd->signed_descriptor_len,
03628                               TO_CONN(conn));
03629     }
03630   }
03631 
03632   if (!smartlist_len(conn->fingerprint_stack)) {
03633     /* We just wrote the last one; finish up. */
03634     conn->dir_spool_src = DIR_SPOOL_NONE;
03635     smartlist_free(conn->fingerprint_stack);
03636     conn->fingerprint_stack = NULL;
03637   }
03638   return 0;
03639 }
03640 
03647 static int
03648 connection_dirserv_add_microdescs_to_outbuf(dir_connection_t *conn)
03649 {
03650   microdesc_cache_t *cache = get_microdesc_cache();
03651   while (smartlist_len(conn->fingerprint_stack) &&
03652          connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
03653     char *fp256 = smartlist_pop_last(conn->fingerprint_stack);
03654     microdesc_t *md = microdesc_cache_lookup_by_digest256(cache, fp256);
03655     tor_free(fp256);
03656     if (!md)
03657       continue;
03658     if (conn->zlib_state) {
03659       /* XXXX024 This 'last' business should actually happen on the last
03660        * routerinfo, not on the last fingerprint. */
03661       int last = !smartlist_len(conn->fingerprint_stack);
03662       connection_write_to_buf_zlib(md->body, md->bodylen, conn, last);
03663       if (last) {
03664         tor_zlib_free(conn->zlib_state);
03665         conn->zlib_state = NULL;
03666       }
03667     } else {
03668       connection_write_to_buf(md->body, md->bodylen, TO_CONN(conn));
03669     }
03670   }
03671   if (!smartlist_len(conn->fingerprint_stack)) {
03672     conn->dir_spool_src = DIR_SPOOL_NONE;
03673     smartlist_free(conn->fingerprint_stack);
03674     conn->fingerprint_stack = NULL;
03675   }
03676   return 0;
03677 }
03678 
03685 static int
03686 connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
03687 {
03688   ssize_t bytes;
03689   int64_t remaining;
03690 
03691   bytes = DIRSERV_BUFFER_MIN - connection_get_outbuf_len(TO_CONN(conn));
03692   tor_assert(bytes > 0);
03693   tor_assert(conn->cached_dir);
03694   if (bytes < 8192)
03695     bytes = 8192;
03696   remaining = conn->cached_dir->dir_z_len - conn->cached_dir_offset;
03697   if (bytes > remaining)
03698     bytes = (ssize_t) remaining;
03699 
03700   if (conn->zlib_state) {
03701     connection_write_to_buf_zlib(
03702                              conn->cached_dir->dir_z + conn->cached_dir_offset,
03703                              bytes, conn, bytes == remaining);
03704   } else {
03705     connection_write_to_buf(conn->cached_dir->dir_z + conn->cached_dir_offset,
03706                             bytes, TO_CONN(conn));
03707   }
03708   conn->cached_dir_offset += bytes;
03709   if (conn->cached_dir_offset == (int)conn->cached_dir->dir_z_len) {
03710     /* We just wrote the last one; finish up. */
03711     connection_dirserv_finish_spooling(conn);
03712     cached_dir_decref(conn->cached_dir);
03713     conn->cached_dir = NULL;
03714   }
03715   return 0;
03716 }
03717 
03726 static int
03727 connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn)
03728 {
03729 
03730   while (connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
03731     if (conn->cached_dir) {
03732       int uncompressing = (conn->zlib_state != NULL);
03733       int r = connection_dirserv_add_dir_bytes_to_outbuf(conn);
03734       if (conn->dir_spool_src == DIR_SPOOL_NONE) {
03735         /* add_dir_bytes thinks we're done with the cached_dir.  But we
03736          * may have more cached_dirs! */
03737         conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
03738         /* This bit is tricky.  If we were uncompressing the last
03739          * networkstatus, we may need to make a new zlib object to
03740          * uncompress the next one. */
03741         if (uncompressing && ! conn->zlib_state &&
03742             conn->fingerprint_stack &&
03743             smartlist_len(conn->fingerprint_stack)) {
03744           conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
03745         }
03746       }
03747       if (r) return r;
03748     } else if (conn->fingerprint_stack &&
03749                smartlist_len(conn->fingerprint_stack)) {
03750       /* Add another networkstatus; start serving it. */
03751       char *fp = smartlist_pop_last(conn->fingerprint_stack);
03752       cached_dir_t *d = lookup_cached_dir_by_fp(fp);
03753       tor_free(fp);
03754       if (d) {
03755         ++d->refcnt;
03756         conn->cached_dir = d;
03757         conn->cached_dir_offset = 0;
03758       }
03759     } else {
03760       connection_dirserv_finish_spooling(conn);
03761       smartlist_free(conn->fingerprint_stack);
03762       conn->fingerprint_stack = NULL;
03763       return 0;
03764     }
03765   }
03766   return 0;
03767 }
03768 
03771 int
03772 connection_dirserv_flushed_some(dir_connection_t *conn)
03773 {
03774   tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING);
03775 
03776   if (connection_get_outbuf_len(TO_CONN(conn)) >= DIRSERV_BUFFER_MIN)
03777     return 0;
03778 
03779   switch (conn->dir_spool_src) {
03780     case DIR_SPOOL_EXTRA_BY_DIGEST:
03781     case DIR_SPOOL_EXTRA_BY_FP:
03782     case DIR_SPOOL_SERVER_BY_DIGEST:
03783     case DIR_SPOOL_SERVER_BY_FP:
03784       return connection_dirserv_add_servers_to_outbuf(conn);
03785     case DIR_SPOOL_MICRODESC:
03786       return connection_dirserv_add_microdescs_to_outbuf(conn);
03787     case DIR_SPOOL_CACHED_DIR:
03788       return connection_dirserv_add_dir_bytes_to_outbuf(conn);
03789     case DIR_SPOOL_NETWORKSTATUS:
03790       return connection_dirserv_add_networkstatus_bytes_to_outbuf(conn);
03791     case DIR_SPOOL_NONE:
03792     default:
03793       return 0;
03794   }
03795 }
03796 
03798 void
03799 dirserv_free_all(void)
03800 {
03801   dirserv_free_fingerprint_list();
03802 
03803   cached_dir_decref(the_directory);
03804   clear_cached_dir(&the_runningrouters);
03805   cached_dir_decref(the_v2_networkstatus);
03806   cached_dir_decref(cached_directory);
03807   clear_cached_dir(&cached_runningrouters);
03808 
03809   digestmap_free(cached_v2_networkstatus, _free_cached_dir);
03810   cached_v2_networkstatus = NULL;
03811   strmap_free(cached_consensuses, _free_cached_dir);
03812   cached_consensuses = NULL;
03813 }
03814