[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r8523: Make "is a v1 authority", "is a v2 authority", and "is a hid (in tor/trunk: . doc src/or)



Author: nickm
Date: 2006-09-28 19:57:59 -0400 (Thu, 28 Sep 2006)
New Revision: 8523

Modified:
   tor/trunk/
   tor/trunk/ChangeLog
   tor/trunk/doc/TODO
   tor/trunk/doc/tor.1.in
   tor/trunk/src/or/config.c
   tor/trunk/src/or/directory.c
   tor/trunk/src/or/dirserv.c
   tor/trunk/src/or/or.h
   tor/trunk/src/or/router.c
   tor/trunk/src/or/routerlist.c
Log:
 r8977@Kushana:  nickm | 2006-09-28 19:56:41 -0400
 Make "is a v1 authority", "is a v2 authority", and "is a hidden service authority" into separate flags so we can eventually migrate more trust away from moria.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r8977] on c95137ef-5f19-0410-b913-86e773d04f59

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/ChangeLog	2006-09-28 23:57:59 UTC (rev 8523)
@@ -27,6 +27,10 @@
       directory authorities don't think it's a good guard, treat it as if it
       were unlisted: stop using it as a guard, and throw it off the guards
       list if it stays that way for a long time.
+    - Allow directory authorities to be marked separately as authorities for
+      the v1 directory protocol, the v2 directory protocol, and as hidden
+      service directories.  This should make it easier to migrate trust away
+      from one of the two authorities currently running on Moria.
 
   o Security Fixes, minor:
     - If a client asked for a server by name, and we didn't have a

Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/doc/TODO	2006-09-28 23:57:59 UTC (rev 8523)
@@ -35,13 +35,16 @@
       D The right thing here is to revamp our node selection implementation.
         (Deferred until oprofile says this matters.)
     o make it configurable, so people can turn it on or off.
+N - Test guard unreachable logic; make sure that we actually attempt to
+    connect to guards that we think are unreachable from time to time.
+    Make sure that we don't freak out when the network is down.
 N - Clients stop dumping old descriptors if the network-statuses
     claim they're still valid.
 R . If we fail to connect via an exit enclave, (warn and) try again
     without demanding that exit node.
     - And recognize when extending to the enclave node is failing,
       so we can abandon then too.
-N - We need a separate list of "hidserv authorities" if we want to
+  o We need a separate list of "hidserv authorities" if we want to
     retire moria1 from the main list.
 P - Figure out why dll's compiled in mingw don't work right in Winxp.
 P - Figure out why openssl 0.9.8c "make test" fails at sha256t test.
@@ -58,6 +61,12 @@
 N   - Specify general event system
 R   - Specify actual events.
 
+N - Have (and document) a BEGIN_DIR relay cell that means "Connect to your
+    directory port."
+    - Specify
+    - Implement
+    - Use for something, so we can be sure it works.
+
 x - We should ship with a list of stable dir mirrors -- they're not
     trusted like the authorities, but they'll provide more robustness
     and diversity for bootstrapping clients.

Modified: tor/trunk/doc/tor.1.in
===================================================================
--- tor/trunk/doc/tor.1.in	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/doc/tor.1.in	2006-09-28 23:57:59 UTC (rev 8523)
@@ -98,14 +98,19 @@
 Store working data in DIR (Default: @LOCALSTATEDIR@/lib/tor)
 .LP
 .TP
-\fBDirServer \fR[\fInickname\fR] [\fBv1\fR] \fIaddress\fR\fB:\fIport fingerprint\fP
+\fBDirServer \fR[\fInickname\fR] [\fBflags\fR] \fIaddress\fR\fB:\fIport fingerprint\fP
 Use a nonstandard authoritative directory server at the provided
 address and port, with the specified key fingerprint.  This option can
 be repeated many times, for multiple authoritative directory
-servers.  If the "v1" option is provided, Tor will use this server as an
+servers.  Flags are separated by spaces, and determine what kind of an
+authority this directory is.  By default, every authority is authoritative
+for current ("v2")-style directories, unless the "no-v2" flag is given.  If the "v1" flags is provided, Tor will use this server as an
 authority for old-style (v1) directories as well.  (Only directory mirrors
-care about this.) If no \fBdirserver\fP line is given, Tor will use the default
-directory servers: moria1, moria2, and tor26.  NOTE: this option is intended
+care about this.)  Tor will use this server as an authority for hidden
+service information if the "hs" flag is set, or if the "v1" flag is set and
+the "no-hs" flag is \fBnot\fP set.
+If no \fBdirserver\fP line is given, Tor will use the default
+directory servers.  NOTE: this option is intended
 for setting up a private Tor network with its own directory authorities.  If
 you use it, you will be distinguishable from other users, because you won't
 believe the same authorities they do.

Modified: tor/trunk/src/or/config.c
===================================================================
--- tor/trunk/src/or/config.c	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/src/or/config.c	2006-09-28 23:57:59 UTC (rev 8523)
@@ -3244,7 +3244,8 @@
   char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
   uint16_t port;
   char digest[DIGEST_LEN];
-  int is_v1_authority = 0;
+  int is_v1_authority = 0, is_hidserv_authority = 0,
+    is_not_hidserv_authority = 0, is_v2_authority = 1;
 
   items = smartlist_create();
   smartlist_split_string(items, line, NULL,
@@ -3260,13 +3261,29 @@
     smartlist_del_keeporder(items, 0);
   }
 
-  if (!strcmp(smartlist_get(items, 0), "v1")) {
-    char *v1 = smartlist_get(items, 0);
-    tor_free(v1);
-    is_v1_authority = 1;
+  while (smartlist_len(items)) {
+    char *flag = smartlist_get(items, 0);
+    if (TOR_ISDIGIT(flag[0]))
+      break;
+    if (!strcasecmp(flag, "v1")) {
+      is_v1_authority = is_hidserv_authority = 1;
+    } else if (!strcasecmp(flag, "hs")) {
+      is_hidserv_authority = 1;
+    } else if (!strcasecmp(flag, "no-hs")) {
+      is_not_hidserv_authority = 1;
+    } else if (!strcasecmp(flag, "no-v2")) {
+      is_v2_authority = 0;
+    } else {
+      log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
+               flag);
+    }
+    tor_free(flag);
     smartlist_del_keeporder(items, 0);
   }
 
+  if (is_not_hidserv_authority)
+    is_hidserv_authority = 0;
+
   if (smartlist_len(items) < 2) {
     log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
     goto err;
@@ -3295,7 +3312,9 @@
   if (!validate_only) {
     log_debug(LD_DIR, "Trusted dirserver at %s:%d (%s)", address, (int)port,
               (char*)smartlist_get(items,1));
-    add_trusted_dir_server(nickname, address, port, digest, is_v1_authority);
+    add_trusted_dir_server(nickname, address, port, digest, is_v1_authority,
+                           is_v2_authority, is_hidserv_authority);
+
   }
 
   r = 0;

Modified: tor/trunk/src/or/directory.c
===================================================================
--- tor/trunk/src/or/directory.c	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/src/or/directory.c	2006-09-28 23:57:59 UTC (rev 8523)
@@ -90,20 +90,23 @@
 {
   smartlist_t *dirservers;
   int post_via_tor;
-  int post_to_v1_only;
+  int post_to_hidserv_only;
 
   dirservers = router_get_trusted_dir_servers();
   tor_assert(dirservers);
   /* Only old dirservers handle rendezvous descriptor publishing. */
-  post_to_v1_only = (purpose == DIR_PURPOSE_UPLOAD_RENDDESC);
+  post_to_hidserv_only = (purpose == DIR_PURPOSE_UPLOAD_RENDDESC);
   /* This tries dirservers which we believe to be down, but ultimately, that's
    * harmless, and we may as well err on the side of getting things uploaded.
    */
   SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
     {
       routerstatus_t *rs = &(ds->fake_status);
-      if (post_to_v1_only && !ds->is_v1_authority)
+      if (post_to_hidserv_only && !ds->is_hidserv_authority)
         continue;
+      if (!post_to_hidserv_only &&
+          !(ds->is_v1_authority || ds->is_v2_authority))
+        continue;
       post_via_tor = purpose_is_private(purpose) ||
               !fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
       directory_initiate_command_routerstatus(rs, purpose, post_via_tor,
@@ -124,26 +127,37 @@
   or_options_t *options = get_options();
   int prefer_authority = server_mode(options) && options->DirPort != 0;
   int directconn = !purpose_is_private(purpose);
+  authority_type_t type;
 
-  int need_v1_support = purpose == DIR_PURPOSE_FETCH_DIR ||
-                        purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
-                        purpose == DIR_PURPOSE_FETCH_RENDDESC;
-  int need_v2_support = purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
-                        purpose == DIR_PURPOSE_FETCH_SERVERDESC;
+  switch (purpose) {
+    case DIR_PURPOSE_FETCH_NETWORKSTATUS:
+    case DIR_PURPOSE_FETCH_SERVERDESC:
+      type = V2_AUTHORITY;
+      break;
+    case DIR_PURPOSE_FETCH_DIR:
+    case DIR_PURPOSE_FETCH_RUNNING_LIST:
+      type = V1_AUTHORITY;
+      break;
+    case DIR_PURPOSE_FETCH_RENDDESC:
+      type = HIDSERV_AUTHORITY;
+      break;
+    default:
+      log_warn(LD_BUG, "Unexpected purpose %d", (int)purpose);
+      return;
+  }
 
-  if (!options->FetchServerDescriptors &&
-      (need_v1_support || need_v2_support))
+  if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
     return;
 
   if (directconn) {
     if (prefer_authority) {
       /* only ask authdirservers, and don't ask myself */
-      rs = router_pick_trusteddirserver(need_v1_support, 1, 1,
+      rs = router_pick_trusteddirserver(type, 1, 1,
                                         retry_if_no_servers);
     }
     if (!rs) {
       /* anybody with a non-zero dirport will do */
-      rs = router_pick_directory_server(1, 1, need_v2_support,
+      rs = router_pick_directory_server(1, 1, type==V2_AUTHORITY,
                                         retry_if_no_servers);
       if (!rs) {
         const char *which;
@@ -158,7 +172,7 @@
         log_info(LD_DIR,
                  "No router found for %s; falling back to dirserver list",
                  which);
-        rs = router_pick_trusteddirserver(need_v1_support, 1, 1,
+        rs = router_pick_trusteddirserver(type, 1, 1,
                                           retry_if_no_servers);
         if (!rs)
           directconn = 0; /* last resort: try routing it via Tor */
@@ -169,10 +183,11 @@
     /* Never use fascistfirewall; we're going via Tor. */
     if (purpose == DIR_PURPOSE_FETCH_RENDDESC) {
       /* only ask authdirservers, any of them will do */
-      rs = router_pick_trusteddirserver(1, 0, 0, retry_if_no_servers);
+      rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, 0, 0,
+                                        retry_if_no_servers);
     } else {
       /* anybody with a non-zero dirport will do. Disregard firewalls. */
-      rs = router_pick_directory_server(1, 0, need_v2_support,
+      rs = router_pick_directory_server(1, 0, type == V2_AUTHORITY,
                                         retry_if_no_servers);
       /* If we have any hope of building an indirect conn, we know some router
        * descriptors.  If (rs==NULL), we can't build circuits anyway, so

Modified: tor/trunk/src/or/dirserv.c
===================================================================
--- tor/trunk/src/or/dirserv.c	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/src/or/dirserv.c	2006-09-28 23:57:59 UTC (rev 8523)
@@ -1025,7 +1025,7 @@
       digestmap_iter_get(iter, &ident, &val);
       d = val;
       if (d->published < oldest_published &&
-          !router_get_trusteddirserver_by_digest(ident)) {
+          !router_digest_is_trusted_dir(ident)) {
         oldest = ident;
         oldest_published = d->published;
       }

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/src/or/or.h	2006-09-28 23:57:59 UTC (rev 8523)
@@ -2506,8 +2506,14 @@
   char digest[DIGEST_LEN]; /**< Digest of identity key */
   unsigned int is_running:1; /**< True iff we think this server is running. */
   /** True iff this server is an authority for the older ("v1") directory
-   * protocol.  (All authorities are v2 authorities.) */
+   * protocol. */
   unsigned int is_v1_authority:1;
+  /** True iff this server is an authority for the newer ("v2") directory
+   * protocol. */
+  unsigned int is_v2_authority:1;
+  /** True iff this server is an authority for hidden services */
+  unsigned int is_hidserv_authority:1;
+
   int n_networkstatus_failures; /**< How many times have we asked for this
                                  * server's network-status unsuccessfully? */
   routerstatus_t fake_status; /**< Used when we need to pass this trusted
@@ -2524,7 +2530,10 @@
                                              int fascistfirewall,
                                              int for_v2_directory,
                                              int retry_if_no_servers);
-routerstatus_t *router_pick_trusteddirserver(int need_v1_authority,
+typedef enum {
+  V1_AUTHORITY, V2_AUTHORITY, HIDSERV_AUTHORITY,
+} authority_type_t;
+routerstatus_t *router_pick_trusteddirserver(authority_type_t type,
                                              int requireother,
                                              int fascistfirewall,
                                              int retry_if_no_servers);
@@ -2592,7 +2601,8 @@
 
 void add_trusted_dir_server(const char *nickname,
                             const char *address, uint16_t port,
-                            const char *digest, int is_v1_authority);
+                            const char *digest, int is_v1_authority,
+                            int is_v2_authority, int is_hidserv_authority);
 void clear_trusted_dir_servers(void);
 int any_trusted_dir_is_v1_authority(void);
 networkstatus_t *networkstatus_get_by_digest(const char *digest);

Modified: tor/trunk/src/or/router.c
===================================================================
--- tor/trunk/src/or/router.c	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/src/or/router.c	2006-09-28 23:57:59 UTC (rev 8523)
@@ -361,8 +361,10 @@
   crypto_pk_get_digest(get_identity_key(), digest);
   if (!router_digest_is_trusted_dir(digest)) {
     add_trusted_dir_server(options->Nickname, NULL,
-                           (uint16_t)options->DirPort, digest,
-                           options->V1AuthoritativeDir);
+                          (uint16_t)options->DirPort, digest,
+                          options->V1AuthoritativeDir, /* v1 authority */
+                          1, /* v2 authority */
+                          options->V1AuthoritativeDir /* hidserv authority */);
   }
   return 0; /* success */
 }

Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c	2006-09-28 23:57:56 UTC (rev 8522)
+++ tor/trunk/src/or/routerlist.c	2006-09-28 23:57:59 UTC (rev 8523)
@@ -22,7 +22,7 @@
                                                          int fascistfirewall,
                                                          int for_v2_directory);
 static routerstatus_t *router_pick_trusteddirserver_impl(
-                 int need_v1_authority, int requireother, int fascistfirewall);
+                 authority_type_t type, int requireother, int fascistfirewall);
 static void mark_all_trusteddirservers_up(void);
 static int router_nickname_matches(routerinfo_t *router, const char *nickname);
 static void routerstatus_list_update_from_networkstatus(time_t now);
@@ -97,6 +97,19 @@
  * listed by the authorities  */
 static int have_warned_about_new_version = 0;
 
+/** Return the number of v2 directory authorities */
+static INLINE int
+get_n_v2_authorities(void)
+{
+  int n = 0;
+  if (!trusted_dir_servers)
+    return 0;
+  SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
+                    if (ds->is_v2_authority)
+                      ++n);
+  return n;
+}
+
 /** Repopulate our list of network_status_t objects from the list cached on
  * disk.  Return 0 on success, -1 on failure. */
 int
@@ -465,14 +478,14 @@
  * Other args are as in router_pick_trusteddirserver_impl().
  */
 routerstatus_t *
-router_pick_trusteddirserver(int need_v1_authority,
+router_pick_trusteddirserver(authority_type_t type,
                              int requireother,
                              int fascistfirewall,
                              int retry_if_no_servers)
 {
   routerstatus_t *choice;
 
-  choice = router_pick_trusteddirserver_impl(need_v1_authority,
+  choice = router_pick_trusteddirserver_impl(type,
                                              requireother, fascistfirewall);
   if (choice || !retry_if_no_servers)
     return choice;
@@ -480,7 +493,7 @@
   log_info(LD_DIR,
            "No trusted dirservers are reachable. Trying them all again.");
   mark_all_trusteddirservers_up();
-  return router_pick_trusteddirserver_impl(need_v1_authority,
+  return router_pick_trusteddirserver_impl(type,
                                            requireother, fascistfirewall);
 }
 
@@ -540,7 +553,7 @@
  * system.
  */
 static routerstatus_t *
-router_pick_trusteddirserver_impl(int need_v1_authority,
+router_pick_trusteddirserver_impl(authority_type_t type,
                                   int requireother, int fascistfirewall)
 {
   smartlist_t *sl;
@@ -555,8 +568,12 @@
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
     {
       if (!d->is_running) continue;
-      if (need_v1_authority && !d->is_v1_authority)
+      if (type == V1_AUTHORITY && !d->is_v1_authority)
         continue;
+      if (type == V2_AUTHORITY && !d->is_v2_authority)
+        continue;
+      if (type == HIDSERV_AUTHORITY && !d->is_hidserv_authority)
+        continue;
       if (requireother && me && router_digest_is_me(d->digest))
           continue;
       if (fascistfirewall) {
@@ -1310,9 +1327,7 @@
 static int
 max_descriptors_per_router(void)
 {
-  int n_authorities = 0;
-  if (trusted_dir_servers)
-    n_authorities = smartlist_len(trusted_dir_servers);
+  int n_authorities = get_n_v2_authorities();
   return (n_authorities < 5) ? 5 : n_authorities;
 }
 
@@ -2219,7 +2234,8 @@
   }
   base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
   if (!(trusted_dir =
-        router_get_trusteddirserver_by_digest(ns->identity_digest))) {
+        router_get_trusteddirserver_by_digest(ns->identity_digest))
+      || !trusted_dir->is_v2_authority) {
     log_info(LD_DIR, "Network status was signed, but not by an authoritative "
              "directory we recognize.");
     if (!get_options()->DirPort) {
@@ -2536,6 +2552,8 @@
     SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
        {
          char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */
+         if (!ds->is_v2_authority)
+           continue;
          if (router_digest_is_me(ds->digest))
            continue;
          if (connection_get_by_type_addr_port_purpose(
@@ -2594,17 +2612,19 @@
    * *one* if the most recent one's publication time is under
    * NETWORKSTATUS_CLIENT_DL_INTERVAL.
    */
-  if (!trusted_dir_servers || !smartlist_len(trusted_dir_servers))
+  if (!get_n_v2_authorities())
     return;
-  n_dirservers = n_running_dirservers = smartlist_len(trusted_dir_servers);
+  n_dirservers = n_running_dirservers = 0;
   missing = smartlist_create();
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
      {
        networkstatus_t *ns = networkstatus_get_by_digest(ds->digest);
-       if (ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES) {
-         --n_running_dirservers;
+       if (!ds->is_v2_authority)
          continue;
-       }
+       ++n_dirservers;
+       if (ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES)
+         continue;
+       ++n_running_dirservers;
        if (ns && ns->published_on > now-NETWORKSTATUS_MAX_AGE)
          ++n_live;
        else
@@ -2649,6 +2669,8 @@
       if (i >= n_dirservers)
         i = 0;
       ds = smartlist_get(trusted_dir_servers, i);
+      if (! ds->is_v2_authority)
+        continue;
       if (n_failed < n_dirservers &&
           ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES) {
         ++n_failed;
@@ -2726,7 +2748,8 @@
  * <b>address</b> is NULL, add ourself. */
 void
 add_trusted_dir_server(const char *nickname, const char *address,
-                       uint16_t port, const char *digest, int is_v1_authority)
+                       uint16_t port, const char *digest, int is_v1_authority,
+                       int is_v2_authority, int is_hidserv_authority)
 {
   trusted_dir_server_t *ent;
   uint32_t a;
@@ -2760,6 +2783,8 @@
   ent->dir_port = port;
   ent->is_running = 1;
   ent->is_v1_authority = is_v1_authority;
+  ent->is_v2_authority = is_v2_authority;
+  ent->is_hidserv_authority = is_hidserv_authority;
   memcpy(ent->digest, digest, DIGEST_LEN);
 
   dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0);
@@ -3115,8 +3140,8 @@
   if (!warned_conflicts)
     warned_conflicts = smartlist_create();
 
-  n_trusted = smartlist_len(trusted_dir_servers);
   n_statuses = smartlist_len(networkstatus_list);
+  n_trusted = get_n_v2_authorities();
 
   if (n_statuses <= n_trusted/2) {
     /* Not enough statuses to adjust status. */
@@ -3620,8 +3645,8 @@
     return;
   }
 
-  if (networkstatus_list && smartlist_len(networkstatus_list) <=
-                            smartlist_len(trusted_dir_servers)/2) {
+  if (networkstatus_list &&
+      smartlist_len(networkstatus_list) <= get_n_v2_authorities()/2) {
     log_info(LD_DIR,
              "Not enough networkstatus documents to launch requests.");
   }
@@ -3859,7 +3884,7 @@
     res = 0;
     goto done;
   }
-  n_authorities = smartlist_len(trusted_dir_servers);
+  n_authorities = get_n_v2_authorities();
   n_ns = smartlist_len(networkstatus_list);
   if (n_ns<=n_authorities/2) {
     log_info(LD_DIR,
@@ -3904,6 +3929,8 @@
 
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
     {
+      if (!ds->is_v2_authority)
+        continue;
       /* If we don't have the status, and we haven't failed to get the status,
        * we haven't tried to get the status. */
       if (!networkstatus_get_by_digest(ds->digest) &&