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

[or-cvs] r9963: Initial code to parse extra-info documents as described in p (in tor/trunk: . doc doc/spec/proposals src/or)



Author: nickm
Date: 2007-04-16 00:17:58 -0400 (Mon, 16 Apr 2007)
New Revision: 9963

Modified:
   tor/trunk/
   tor/trunk/doc/TODO
   tor/trunk/doc/spec/proposals/104-short-descriptors.txt
   tor/trunk/src/or/or.h
   tor/trunk/src/or/routerlist.c
   tor/trunk/src/or/routerparse.c
Log:
 r12385@catbus:  nickm | 2007-04-15 22:55:58 -0400
 Initial code to parse extra-info documents as described in proposal 104.  This is making me realize that the parsing code in routerparse.c is a little daft.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r12385] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO	2007-04-15 23:49:37 UTC (rev 9962)
+++ tor/trunk/doc/TODO	2007-04-16 04:17:58 UTC (rev 9963)
@@ -54,7 +54,13 @@
 Things we'd like to do in 0.2.0.x:
   - Proposals:
     - 101: Voting on the Tor Directory System
-    - 104: Long and Short Router Descriptors (by Jun 1)
+    . 104: Long and Short Router Descriptors (by Jun 1)
+      . Finalize proposal
+      - Implement parsing for extra-info documents; have authorities
+        accept them and serve them from specified URLs
+      - Have routers generate and upload extra-info documents.
+      - Implement option to download and cache extra-info documents.
+      - Drop bandwidth history from router-descriptors
     - 105: Version negotiation for the Tor protocol (finalize by Jun 1)
   - Refactoring:
     - Make resolves no longer use edge_connection_t unless they are actually

Modified: tor/trunk/doc/spec/proposals/104-short-descriptors.txt
===================================================================
--- tor/trunk/doc/spec/proposals/104-short-descriptors.txt	2007-04-15 23:49:37 UTC (rev 9962)
+++ tor/trunk/doc/spec/proposals/104-short-descriptors.txt	2007-04-16 04:17:58 UTC (rev 9963)
@@ -57,7 +57,7 @@
 
     An "extra info" descriptor contains the following fields:
 
-    "extra-info" Nickname IP Fingerprint
+    "extra-info" Nickname Fingerprint
         Identifies what router this is an extra info descriptor for.
         Fingerprint is encoded in hex (using upper-case letters), with
         no spaces.
@@ -67,7 +67,7 @@
 
     "read-history"
     "write-history"
-        As currently documented in dir-spec.txt.
+        As currently documented in dir-spec.txt.  Optional.
 
     "router-signature" NL Signature NL
 
@@ -99,7 +99,8 @@
 
        "caches-extra-info"
           Present if this router is a directory cache that provides
-          extra-info documents.
+          extra-info documents, or an authority that handles extra-info
+          documents.
 
      (Since implementations before 0.1.2.5-alpha required that "opt" keyword
      precede any unrecognized entry with "opt", these keys MUST be preceded

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2007-04-15 23:49:37 UTC (rev 9962)
+++ tor/trunk/src/or/or.h	2007-04-16 04:17:58 UTC (rev 9963)
@@ -1080,10 +1080,12 @@
   smartlist_t *declared_family; /**< Nicknames of router which this router
                                  * claims are its family. */
   char *contact_info; /**< Declared contact info for this router. */
+  char extra_info_digest[DIGEST_LEN]; /**< DOCDOC */
   unsigned int is_hibernating:1; /**< Whether the router claims to be
                                   * hibernating */
   unsigned int has_old_dnsworkers:1; /**< Whether the router is using
                                       * dnsworker code. */
+  unsigned int caches_extra_info:1; /**< DOCDOC */
 
   /* local info */
   unsigned int is_running:1; /**< As far as we know, is this OR currently
@@ -1121,6 +1123,13 @@
   int routerlist_index;
 } routerinfo_t;
 
+/** DOCDOC */
+typedef struct extrainfo_t {
+  signed_descriptor_t cache_info;
+  char nickname[MAX_NICKNAME_LEN+1];
+  char *pending_sig;
+} extrainfo_t;
+
 /** Contents of a single router entry in a network status object.
  */
 typedef struct routerstatus_t {
@@ -2991,6 +3000,8 @@
 void routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx,
                        int make_old);
 void routerinfo_free(routerinfo_t *router);
+void extrainfo_free(extrainfo_t *extrainfo);
+
 void routerstatus_free(routerstatus_t *routerstatus);
 void networkstatus_free(networkstatus_t *networkstatus);
 void routerlist_free_all(void);
@@ -3076,6 +3087,7 @@
 int router_get_dir_hash(const char *s, char *digest);
 int router_get_runningrouters_hash(const char *s, char *digest);
 int router_get_networkstatus_v2_hash(const char *s, char *digest);
+int router_get_extrainfo_hash(const char *s, char *digest);
 int router_append_dirobj_signature(char *buf, size_t buf_len,
                                    const char *digest,
                                    crypto_pk_env_t *private_key);
@@ -3091,6 +3103,8 @@
 int router_parse_directory(const char *str);
 routerinfo_t *router_parse_entry_from_string(const char *s, const char *end,
                                              int cache_copy);
+extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
+                                      int cache_copy, digestmap_t *routermap);
 addr_policy_t *router_parse_addr_policy_from_string(const char *s,
                                                     int assume_action);
 version_status_t tor_version_is_obsolete(const char *myversion,

Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c	2007-04-15 23:49:37 UTC (rev 9962)
+++ tor/trunk/src/or/routerlist.c	2007-04-16 04:17:58 UTC (rev 9963)
@@ -1506,6 +1506,17 @@
   tor_free(router);
 }
 
+/** DOCDOC */
+void
+extrainfo_free(extrainfo_t *extrainfo)
+{
+  if (!extrainfo)
+    return;
+  tor_free(extrainfo->cache_info.signed_descriptor_body);
+  tor_free(extrainfo->pending_sig);
+  tor_free(extrainfo);
+}
+
 /** Release storage held by <b>sd</b>. */
 static void
 signed_descriptor_free(signed_descriptor_t *sd)

Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c	2007-04-15 23:49:37 UTC (rev 9962)
+++ tor/trunk/src/or/routerparse.c	2007-04-16 04:17:58 UTC (rev 9963)
@@ -56,6 +56,9 @@
   K_S,
   K_V,
   K_EVENTDNS,
+  K_EXTRA_INFO,
+  K_EXTRA_INFO_DIGEST,
+  K_CACHES_EXTRA_INFO,
   _UNRECOGNIZED,
   _ERR,
   _EOF,
@@ -106,7 +109,8 @@
   NETSTATUS = 4,  /**< v2 or later ("versioned") network status. */
   ANYSIGNED = 7,  /**< Any "full" document (that is, not a router status.) */
   RTRSTATUS = 8,  /**< Router-status portion of a versioned network status. */
-  ANY = 15,       /**< Appears in any document type. */
+  EXTRAINFO = 16, /**< DOCDOC */
+  ANY = 31,       /**< Appears in any document type. */
 } where_syntax;
 
 /** Table mapping keywords to token value and to argument rules. */
@@ -125,12 +129,12 @@
   { "signed-directory",    K_SIGNED_DIRECTORY,    NO_ARGS, NO_OBJ,  DIR },
   { "signing-key",         K_SIGNING_KEY,         NO_ARGS, NEED_KEY,RTR },
   { "onion-key",           K_ONION_KEY,           NO_ARGS, NEED_KEY,RTR },
-  { "router-signature",    K_ROUTER_SIGNATURE,    NO_ARGS, NEED_OBJ,RTR },
+  { "router-signature",    K_ROUTER_SIGNATURE,    NO_ARGS, NEED_OBJ,RTR|EXTRAINFO },
   { "running-routers",     K_RUNNING_ROUTERS,     ARGS,    NO_OBJ,  DIR },
   { "router-status",       K_ROUTER_STATUS,       ARGS,    NO_OBJ,  DIR },
   { "bandwidth",           K_BANDWIDTH,           ARGS,    NO_OBJ,  RTR },
   { "platform",            K_PLATFORM,        CONCAT_ARGS, NO_OBJ,  RTR },
-  { "published",           K_PUBLISHED,       CONCAT_ARGS, NO_OBJ, ANYSIGNED },
+  { "published",           K_PUBLISHED,       CONCAT_ARGS, NO_OBJ, ANYSIGNED|EXTRAINFO },
   { "opt",                 K_OPT,             CONCAT_ARGS, OBJ_OK, ANY },
   { "contact",             K_CONTACT,         CONCAT_ARGS, NO_OBJ, ANYSIGNED },
   { "network-status",      K_NETWORK_STATUS,      NO_ARGS, NO_OBJ,  DIR },
@@ -140,8 +144,8 @@
   { "family",              K_FAMILY,              ARGS,    NO_OBJ,  RTR },
   { "fingerprint",         K_FINGERPRINT,     CONCAT_ARGS, NO_OBJ, ANYSIGNED },
   { "hibernating",         K_HIBERNATING,         ARGS,    NO_OBJ,  RTR },
-  { "read-history",        K_READ_HISTORY,        ARGS,    NO_OBJ,  RTR },
-  { "write-history",       K_WRITE_HISTORY,       ARGS,    NO_OBJ,  RTR },
+  { "read-history",        K_READ_HISTORY,        ARGS,    NO_OBJ,  RTR|EXTRAINFO },
+  { "write-history",       K_WRITE_HISTORY,       ARGS,    NO_OBJ,  RTR|EXTRAINFO },
   { "network-status-version", K_NETWORK_STATUS_VERSION,
                                                   ARGS,    NO_OBJ, NETSTATUS },
   { "dir-source",          K_DIR_SOURCE,          ARGS,    NO_OBJ, NETSTATUS },
@@ -149,6 +153,9 @@
   { "client-versions",     K_CLIENT_VERSIONS,     ARGS,    NO_OBJ, NETSTATUS },
   { "server-versions",     K_SERVER_VERSIONS,     ARGS,    NO_OBJ, NETSTATUS },
   { "eventdns",            K_EVENTDNS,            ARGS,    NO_OBJ, RTR },
+  { "extra-info",          K_EXTRA_INFO,          ARGS,    NO_OBJ, EXTRAINFO },
+  { "extra-info-digest",   K_EXTRA_INFO_DIGEST,   ARGS,    NO_OBJ, RTR },
+  { "caches-extra-info",   K_CACHES_EXTRA_INFO,   NO_ARGS, NO_OBJ, RTR },
   { NULL, _NIL, NO_ARGS, NO_OBJ, ANY }
 };
 
@@ -213,6 +220,14 @@
                             "network-status-version","\ndirectory-signature");
 }
 
+/** DOCDOC
+ */
+int
+router_get_extrainfo_hash(const char *s, char *digest)
+{
+  return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature");
+}
+
 /** Helper: used to generate signatures for routers, directories and
  * network-status objects.  Given a digest in <b>digest</b> and a secret
  * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
@@ -934,6 +949,19 @@
     }
   }
 
+  if ((tok = find_first_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
+    router->caches_extra_info = 1;
+
+  if ((tok = find_first_by_keyword(tokens, K_EXTRA_INFO_DIGEST)) &&
+      tok->n_args) {
+    if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
+      base16_decode(router->extra_info_digest, DIGEST_LEN, tok->args[0],
+                    HEX_DIGEST_LEN);
+    } else {
+      log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
+    }
+  }
+
   if (!(tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE))) {
     log_warn(LD_DIR, "Missing router signature");
     goto err;
@@ -983,6 +1011,124 @@
   return router;
 }
 
+/* DOCDOC */
+extrainfo_t *
+extrainfo_parse_entry_from_string(const char *s, const char *end,
+                                  int cache_copy, digestmap_t *routermap)
+{
+  extrainfo_t *extrainfo = NULL;
+  char signed_digest[128];
+  char digest[128];
+  smartlist_t *tokens = NULL;
+  directory_token_t *tok;
+  int t;
+  crypto_pk_env_t *key = NULL;
+  routerinfo_t *router;
+
+  if (!end) {
+    end = s + strlen(s);
+  }
+
+  /* point 'end' to a point immediately after the final newline. */
+  while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
+    --end;
+
+  if (router_get_extrainfo_hash(s, digest) < 0) {
+    log_warn(LD_DIR, "Couldn't compute router hash.");
+    return NULL;
+  }
+  tokens = smartlist_create();
+  if (tokenize_string(s,end,tokens,EXTRAINFO)) {
+    log_warn(LD_DIR, "Error tokeninzing router descriptor.");
+    goto err;
+  }
+
+  if (smartlist_len(tokens) < 2) {
+    log_warn(LD_DIR, "Impossibly short router descriptor.");
+    goto err;
+  }
+
+  tok = smartlist_get(tokens,0);
+  if (tok->tp != K_EXTRA_INFO) {
+    log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
+    goto err;
+  }
+
+  extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
+  if (cache_copy)
+    extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
+  extrainfo->cache_info.signed_descriptor_len = end-s;
+  memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
+
+  if (tok->n_args < 2) {
+    log_warn(LD_DIR,"Insufficient arguments to \"extra-info\"");
+    goto err;
+  }
+  if (!is_legal_nickname(tok->args[0])) {
+    log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
+    goto err;
+  }
+  strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
+  if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
+      base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
+                    tok->args[1], HEX_DIGEST_LEN)) {
+    log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
+             escaped(tok->args[1]));
+    goto err;
+  }
+
+  if (!(tok = find_first_by_keyword(tokens, K_PUBLISHED))) {
+    log_warn(LD_DIR,"No published time on \"extra-info\"");
+    goto err;
+  }
+  if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
+    log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
+             escaped(tok->args[0]));
+    goto err;
+  }
+
+  if (routermap &&
+      (router = digestmap_get(routermap,
+                              extrainfo->cache_info.identity_digest))) {
+    key = router->identity_pkey;
+  }
+
+  if (!(tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE))) {
+    log_warn(LD_DIR, "Missing router signature");
+    goto err;
+  }
+  if (strcmp(tok->object_type, "SIGNATURE") || tok->object_size != 128) {
+    log_warn(LD_DIR, "Bad object type or length on router signature");
+    goto err;
+  }
+
+  if (key) {
+    note_crypto_pk_op(VERIFY_RTR);
+    if ((t=crypto_pk_public_checksig(key, signed_digest,
+                                     tok->object_body, 128)) != 20) {
+      log_warn(LD_DIR, "Invalid signature %d",t);
+      goto err;
+    }
+    if (memcmp(digest, signed_digest, DIGEST_LEN)) {
+      log_warn(LD_DIR, "Mismatched signature");
+      goto err;
+    }
+  } else {
+    extrainfo->pending_sig = tor_memdup(tok->object_body, 128);
+  }
+
+  goto done;
+ err:
+  // extrainfo_free(extrainfo); // DOCDOC
+  extrainfo = NULL;
+ done:
+  if (tokens) {
+    SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
+    smartlist_free(tokens);
+  }
+  return extrainfo;
+}
+
 /** Helper: given a string <b>s</b>, return the start of the next router-status
  * object (starting with "r " at the start of a line).  If none is found,
  * return the start of the next directory signature.  If none is found, return