routerparse.c
上传用户:awang829
上传日期:2019-07-14
资源大小:2356k
文件大小:134k
源码类别:

网络

开发平台:

Unix_Linux

  1.   }
  2.   tok = find_by_keyword(tokens, K_DIR_SOURCE);
  3.   tor_assert(tok->n_args >= 3);
  4.   ns->source_address = tor_strdup(tok->args[0]);
  5.   if (tor_inet_aton(tok->args[1], &in) == 0) {
  6.     log_warn(LD_DIR, "Error parsing network-status source address %s",
  7.              escaped(tok->args[1]));
  8.     goto err;
  9.   }
  10.   ns->source_addr = ntohl(in.s_addr);
  11.   ns->source_dirport =
  12.     (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
  13.   if (ns->source_dirport == 0) {
  14.     log_warn(LD_DIR, "Directory source without dirport; skipping.");
  15.     goto err;
  16.   }
  17.   tok = find_by_keyword(tokens, K_FINGERPRINT);
  18.   tor_assert(tok->n_args);
  19.   if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
  20.                     strlen(tok->args[0]))) {
  21.     log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
  22.              escaped(tok->args[0]));
  23.     goto err;
  24.   }
  25.   if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
  26.     tor_assert(tok->n_args);
  27.     ns->contact = tor_strdup(tok->args[0]);
  28.   }
  29.   tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
  30.   tor_assert(tok->key);
  31.   ns->signing_key = tok->key;
  32.   tok->key = NULL;
  33.   if (crypto_pk_get_digest(ns->signing_key, tmp_digest)<0) {
  34.     log_warn(LD_DIR, "Couldn't compute signing key digest");
  35.     goto err;
  36.   }
  37.   if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
  38.     log_warn(LD_DIR,
  39.              "network-status fingerprint did not match dir-signing-key");
  40.     goto err;
  41.   }
  42.   if ((tok = find_opt_by_keyword(tokens, K_DIR_OPTIONS))) {
  43.     for (i=0; i < tok->n_args; ++i) {
  44.       if (!strcmp(tok->args[i], "Names"))
  45.         ns->binds_names = 1;
  46.       if (!strcmp(tok->args[i], "Versions"))
  47.         ns->recommends_versions = 1;
  48.       if (!strcmp(tok->args[i], "BadExits"))
  49.         ns->lists_bad_exits = 1;
  50.       if (!strcmp(tok->args[i], "BadDirectories"))
  51.         ns->lists_bad_directories = 1;
  52.     }
  53.   }
  54.   if (ns->recommends_versions) {
  55.     if (!(tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
  56.       log_warn(LD_DIR, "Missing client-versions on versioning directory");
  57.       goto err;
  58.     }
  59.     ns->client_versions = tor_strdup(tok->args[0]);
  60.     if (!(tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS)) ||
  61.         tok->n_args<1) {
  62.       log_warn(LD_DIR, "Missing server-versions on versioning directory");
  63.       goto err;
  64.     }
  65.     ns->server_versions = tor_strdup(tok->args[0]);
  66.   }
  67.   tok = find_by_keyword(tokens, K_PUBLISHED);
  68.   tor_assert(tok->n_args == 1);
  69.   if (parse_iso_time(tok->args[0], &ns->published_on) < 0) {
  70.      goto err;
  71.   }
  72.   ns->entries = smartlist_create();
  73.   s = eos;
  74.   SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  75.   smartlist_clear(tokens);
  76.   memarea_clear(area);
  77.   while (!strcmpstart(s, "r ")) {
  78.     routerstatus_t *rs;
  79.     if ((rs = routerstatus_parse_entry_from_string(area, &s, tokens,
  80.                                                    NULL, NULL, 0)))
  81.       smartlist_add(ns->entries, rs);
  82.   }
  83.   smartlist_sort(ns->entries, _compare_routerstatus_entries);
  84.   smartlist_uniq(ns->entries, _compare_routerstatus_entries,
  85.                  _free_duplicate_routerstatus_entry);
  86.   if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) {
  87.     log_warn(LD_DIR, "Error tokenizing network-status footer.");
  88.     goto err;
  89.   }
  90.   if (smartlist_len(footer_tokens) < 1) {
  91.     log_warn(LD_DIR, "Too few items in network-status footer.");
  92.     goto err;
  93.   }
  94.   tok = smartlist_get(footer_tokens, smartlist_len(footer_tokens)-1);
  95.   if (tok->tp != K_DIRECTORY_SIGNATURE) {
  96.     log_warn(LD_DIR,
  97.              "Expected network-status footer to end with a signature.");
  98.     goto err;
  99.   }
  100.   note_crypto_pk_op(VERIFY_DIR);
  101.   if (check_signature_token(ns_digest, tok, ns->signing_key, 0,
  102.                             "network-status") < 0)
  103.     goto err;
  104.   goto done;
  105.  err:
  106.   if (ns)
  107.     networkstatus_v2_free(ns);
  108.   ns = NULL;
  109.  done:
  110.   SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  111.   smartlist_free(tokens);
  112.   SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
  113.   smartlist_free(footer_tokens);
  114.   if (area) {
  115.     DUMP_AREA(area, "v2 networkstatus");
  116.     memarea_drop_all(area);
  117.   }
  118.   return ns;
  119. }
  120. /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
  121.  * ns_type), from <b>s</b>, and return the result.  Return NULL on failure. */
  122. networkstatus_t *
  123. networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
  124.                                      networkstatus_type_t ns_type)
  125. {
  126.   smartlist_t *tokens = smartlist_create();
  127.   smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
  128.   networkstatus_voter_info_t *voter = NULL;
  129.   networkstatus_t *ns = NULL;
  130.   char ns_digest[DIGEST_LEN];
  131.   const char *cert, *end_of_header, *end_of_footer;
  132.   directory_token_t *tok;
  133.   int ok;
  134.   struct in_addr in;
  135.   int i, inorder, n_signatures = 0;
  136.   memarea_t *area = NULL, *rs_area = NULL;
  137.   tor_assert(s);
  138.   if (eos_out)
  139.     *eos_out = NULL;
  140.   if (router_get_networkstatus_v3_hash(s, ns_digest)) {
  141.     log_warn(LD_DIR, "Unable to compute digest of network-status");
  142.     goto err;
  143.   }
  144.   area = memarea_new();
  145.   end_of_header = find_start_of_next_routerstatus(s);
  146.   if (tokenize_string(area, s, end_of_header, tokens,
  147.                       (ns_type == NS_TYPE_CONSENSUS) ?
  148.                       networkstatus_consensus_token_table :
  149.                       networkstatus_token_table, 0)) {
  150.     log_warn(LD_DIR, "Error tokenizing network-status vote header");
  151.     goto err;
  152.   }
  153.   ns = tor_malloc_zero(sizeof(networkstatus_t));
  154.   memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
  155.   if (ns_type != NS_TYPE_CONSENSUS) {
  156.     const char *end_of_cert = NULL;
  157.     if (!(cert = strstr(s, "ndir-key-certificate-version")))
  158.       goto err;
  159.     ++cert;
  160.     ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
  161.     if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
  162.       goto err;
  163.   }
  164.   tok = find_by_keyword(tokens, K_VOTE_STATUS);
  165.   tor_assert(tok->n_args);
  166.   if (!strcmp(tok->args[0], "vote")) {
  167.     ns->type = NS_TYPE_VOTE;
  168.   } else if (!strcmp(tok->args[0], "consensus")) {
  169.     ns->type = NS_TYPE_CONSENSUS;
  170.   } else if (!strcmp(tok->args[0], "opinion")) {
  171.     ns->type = NS_TYPE_OPINION;
  172.   } else {
  173.     log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
  174.              escaped(tok->args[0]));
  175.     goto err;
  176.   }
  177.   if (ns_type != ns->type) {
  178.     log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
  179.     goto err;
  180.   }
  181.   if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
  182.     tok = find_by_keyword(tokens, K_PUBLISHED);
  183.     if (parse_iso_time(tok->args[0], &ns->published))
  184.       goto err;
  185.     ns->supported_methods = smartlist_create();
  186.     tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
  187.     if (tok) {
  188.       for (i=0; i < tok->n_args; ++i)
  189.         smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
  190.     } else {
  191.       smartlist_add(ns->supported_methods, tor_strdup("1"));
  192.     }
  193.   } else {
  194.     tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
  195.     if (tok) {
  196.       ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
  197.                                                  &ok, NULL);
  198.       if (!ok)
  199.         goto err;
  200.     } else {
  201.       ns->consensus_method = 1;
  202.     }
  203.   }
  204.   tok = find_by_keyword(tokens, K_VALID_AFTER);
  205.   if (parse_iso_time(tok->args[0], &ns->valid_after))
  206.     goto err;
  207.   tok = find_by_keyword(tokens, K_FRESH_UNTIL);
  208.   if (parse_iso_time(tok->args[0], &ns->fresh_until))
  209.     goto err;
  210.   tok = find_by_keyword(tokens, K_VALID_UNTIL);
  211.   if (parse_iso_time(tok->args[0], &ns->valid_until))
  212.     goto err;
  213.   tok = find_by_keyword(tokens, K_VOTING_DELAY);
  214.   tor_assert(tok->n_args >= 2);
  215.   ns->vote_seconds =
  216.     (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
  217.   if (!ok)
  218.     goto err;
  219.   ns->dist_seconds =
  220.     (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
  221.   if (!ok)
  222.     goto err;
  223.   if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) {
  224.     log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
  225.     goto err;
  226.   }
  227.   if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) {
  228.     log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
  229.     goto err;
  230.   }
  231.   if (ns->vote_seconds < MIN_VOTE_SECONDS) {
  232.     log_warn(LD_DIR, "Vote seconds is too short");
  233.     goto err;
  234.   }
  235.   if (ns->dist_seconds < MIN_DIST_SECONDS) {
  236.     log_warn(LD_DIR, "Dist seconds is too short");
  237.     goto err;
  238.   }
  239.   if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
  240.     ns->client_versions = tor_strdup(tok->args[0]);
  241.   }
  242.   if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
  243.     ns->server_versions = tor_strdup(tok->args[0]);
  244.   }
  245.   tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
  246.   ns->known_flags = smartlist_create();
  247.   inorder = 1;
  248.   for (i = 0; i < tok->n_args; ++i) {
  249.     smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
  250.     if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
  251.       log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
  252.       inorder = 0;
  253.     }
  254.   }
  255.   if (!inorder) {
  256.     log_warn(LD_DIR, "known-flags not in order");
  257.     goto err;
  258.   }
  259.   tok = find_opt_by_keyword(tokens, K_PARAMS);
  260.   if (tok) {
  261.     inorder = 1;
  262.     ns->net_params = smartlist_create();
  263.     for (i = 0; i < tok->n_args; ++i) {
  264.       int ok=0;
  265.       char *eq = strchr(tok->args[i], '=');
  266.       if (!eq) {
  267.         log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
  268.         goto err;
  269.       }
  270.       tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
  271.       if (!ok) {
  272.         log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
  273.         goto err;
  274.       }
  275.       if (i > 0 && strcmp(tok->args[i-1], tok->args[i]) >= 0) {
  276.         log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
  277.         inorder = 0;
  278.       }
  279.       smartlist_add(ns->net_params, tor_strdup(tok->args[i]));
  280.     }
  281.     if (!inorder) {
  282.       log_warn(LD_DIR, "params not in order");
  283.       goto err;
  284.     }
  285.   }
  286.   ns->voters = smartlist_create();
  287.   SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
  288.     tok = _tok;
  289.     if (tok->tp == K_DIR_SOURCE) {
  290.       tor_assert(tok->n_args >= 6);
  291.       if (voter)
  292.         smartlist_add(ns->voters, voter);
  293.       voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
  294.       if (ns->type != NS_TYPE_CONSENSUS)
  295.         memcpy(voter->vote_digest, ns_digest, DIGEST_LEN);
  296.       voter->nickname = tor_strdup(tok->args[0]);
  297.       if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
  298.           base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
  299.                         tok->args[1], HEX_DIGEST_LEN) < 0) {
  300.         log_warn(LD_DIR, "Error decoding identity digest %s in "
  301.                  "network-status vote.", escaped(tok->args[1]));
  302.         goto err;
  303.       }
  304.       if (ns->type != NS_TYPE_CONSENSUS &&
  305.           memcmp(ns->cert->cache_info.identity_digest,
  306.                  voter->identity_digest, DIGEST_LEN)) {
  307.         log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
  308.         goto err;
  309.       }
  310.       voter->address = tor_strdup(tok->args[2]);
  311.       if (!tor_inet_aton(tok->args[3], &in)) {
  312.         log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
  313.                  escaped(tok->args[3]));
  314.         goto err;
  315.       }
  316.       voter->addr = ntohl(in.s_addr);
  317.       voter->dir_port = (uint16_t)
  318.         tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
  319.       if (!ok)
  320.         goto err;
  321.       voter->or_port = (uint16_t)
  322.         tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
  323.       if (!ok)
  324.         goto err;
  325.     } else if (tok->tp == K_CONTACT) {
  326.       if (!voter || voter->contact) {
  327.         log_warn(LD_DIR, "contact element is out of place.");
  328.         goto err;
  329.       }
  330.       voter->contact = tor_strdup(tok->args[0]);
  331.     } else if (tok->tp == K_VOTE_DIGEST) {
  332.       tor_assert(ns->type == NS_TYPE_CONSENSUS);
  333.       tor_assert(tok->n_args >= 1);
  334.       if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
  335.         log_warn(LD_DIR, "vote-digest element is out of place.");
  336.         goto err;
  337.       }
  338.       if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
  339.         base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
  340.                       tok->args[0], HEX_DIGEST_LEN) < 0) {
  341.         log_warn(LD_DIR, "Error decoding vote digest %s in "
  342.                  "network-status consensus.", escaped(tok->args[0]));
  343.         goto err;
  344.       }
  345.     }
  346.   } SMARTLIST_FOREACH_END(_tok);
  347.   if (voter) {
  348.     smartlist_add(ns->voters, voter);
  349.     voter = NULL;
  350.   }
  351.   if (smartlist_len(ns->voters) == 0) {
  352.     log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
  353.     goto err;
  354.   } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
  355.     log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
  356.     goto err;
  357.   }
  358.   if (ns->type != NS_TYPE_CONSENSUS &&
  359.       (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
  360.     int bad = 1;
  361.     if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
  362.       networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
  363.       if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
  364.                         tok->args[0], HEX_DIGEST_LEN)<0)
  365.         bad = 1;
  366.       else
  367.         bad = 0;
  368.     }
  369.     if (bad) {
  370.       log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
  371.                escaped(tok->args[0]));
  372.     }
  373.   }
  374.   /* Parse routerstatus lines. */
  375.   rs_tokens = smartlist_create();
  376.   rs_area = memarea_new();
  377.   s = end_of_header;
  378.   ns->routerstatus_list = smartlist_create();
  379.   while (!strcmpstart(s, "r ")) {
  380.     if (ns->type != NS_TYPE_CONSENSUS) {
  381.       vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
  382.       if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
  383.                                                rs, 0))
  384.         smartlist_add(ns->routerstatus_list, rs);
  385.       else {
  386.         tor_free(rs->version);
  387.         tor_free(rs);
  388.       }
  389.     } else {
  390.       routerstatus_t *rs;
  391.       if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
  392.                                                      NULL, NULL,
  393.                                                      ns->consensus_method)))
  394.         smartlist_add(ns->routerstatus_list, rs);
  395.     }
  396.   }
  397.   for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
  398.     routerstatus_t *rs1, *rs2;
  399.     if (ns->type != NS_TYPE_CONSENSUS) {
  400.       vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
  401.       vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
  402.       rs1 = &a->status; rs2 = &b->status;
  403.     } else {
  404.       rs1 = smartlist_get(ns->routerstatus_list, i-1);
  405.       rs2 = smartlist_get(ns->routerstatus_list, i);
  406.     }
  407.     if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
  408.       log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
  409.                "digest");
  410.       goto err;
  411.     }
  412.   }
  413.   /* Parse footer; check signature. */
  414.   footer_tokens = smartlist_create();
  415.   if ((end_of_footer = strstr(s, "nnetwork-status-version ")))
  416.     ++end_of_footer;
  417.   else
  418.     end_of_footer = s + strlen(s);
  419.   if (tokenize_string(area,s, end_of_footer, footer_tokens,
  420.                       networkstatus_vote_footer_token_table, 0)) {
  421.     log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
  422.     goto err;
  423.   }
  424.   SMARTLIST_FOREACH(footer_tokens, directory_token_t *, _tok,
  425.   {
  426.     char declared_identity[DIGEST_LEN];
  427.     networkstatus_voter_info_t *v;
  428.     tok = _tok;
  429.     if (tok->tp != K_DIRECTORY_SIGNATURE)
  430.       continue;
  431.     tor_assert(tok->n_args >= 2);
  432.     if (!tok->object_type ||
  433.         strcmp(tok->object_type, "SIGNATURE") ||
  434.         tok->object_size < 128 || tok->object_size > 512) {
  435.       log_warn(LD_DIR, "Bad object type or length on directory-signature");
  436.       goto err;
  437.     }
  438.     if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
  439.         base16_decode(declared_identity, sizeof(declared_identity),
  440.                       tok->args[0], HEX_DIGEST_LEN) < 0) {
  441.       log_warn(LD_DIR, "Error decoding declared identity %s in "
  442.                "network-status vote.", escaped(tok->args[0]));
  443.       goto err;
  444.     }
  445.     if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
  446.       log_warn(LD_DIR, "ID on signature on network-status vote does not match "
  447.                "any declared directory source.");
  448.       goto err;
  449.     }
  450.     if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
  451.         base16_decode(v->signing_key_digest, sizeof(v->signing_key_digest),
  452.                       tok->args[1], HEX_DIGEST_LEN) < 0) {
  453.       log_warn(LD_DIR, "Error decoding declared digest %s in "
  454.                "network-status vote.", escaped(tok->args[1]));
  455.       goto err;
  456.     }
  457.     if (ns->type != NS_TYPE_CONSENSUS) {
  458.       if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
  459.                  DIGEST_LEN)) {
  460.         log_warn(LD_DIR, "Digest mismatch between declared and actual on "
  461.                  "network-status vote.");
  462.         goto err;
  463.       }
  464.     }
  465.     if (ns->type != NS_TYPE_CONSENSUS) {
  466.       if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0,
  467.                                 "network-status vote"))
  468.         goto err;
  469.       v->good_signature = 1;
  470.     } else {
  471.       if (tok->object_size >= INT_MAX)
  472.         goto err;
  473.       /* We already parsed a vote from this voter. Use the first one. */
  474.       if (v->signature) {
  475.         log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus "
  476.                    "that contains two votes from the same voter. Ignoring "
  477.                    "the second vote.");
  478.         continue;
  479.       }
  480.       v->signature = tor_memdup(tok->object_body, tok->object_size);
  481.       v->signature_len = (int) tok->object_size;
  482.     }
  483.     ++n_signatures;
  484.   });
  485.   if (! n_signatures) {
  486.     log_warn(LD_DIR, "No signatures on networkstatus vote.");
  487.     goto err;
  488.   }
  489.   if (eos_out)
  490.     *eos_out = end_of_footer;
  491.   goto done;
  492.  err:
  493.   if (ns)
  494.     networkstatus_vote_free(ns);
  495.   ns = NULL;
  496.  done:
  497.   if (tokens) {
  498.     SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  499.     smartlist_free(tokens);
  500.   }
  501.   if (voter) {
  502.     tor_free(voter->nickname);
  503.     tor_free(voter->address);
  504.     tor_free(voter->contact);
  505.     tor_free(voter->signature);
  506.     tor_free(voter);
  507.   }
  508.   if (rs_tokens) {
  509.     SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_free(t));
  510.     smartlist_free(rs_tokens);
  511.   }
  512.   if (footer_tokens) {
  513.     SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
  514.     smartlist_free(footer_tokens);
  515.   }
  516.   if (area) {
  517.     DUMP_AREA(area, "v3 networkstatus");
  518.     memarea_drop_all(area);
  519.   }
  520.   if (rs_area)
  521.     memarea_drop_all(rs_area);
  522.   return ns;
  523. }
  524. /** Parse a detached v3 networkstatus signature document between <b>s</b> and
  525.  * <b>eos</b> and return the result.  Return -1 on failure. */
  526. ns_detached_signatures_t *
  527. networkstatus_parse_detached_signatures(const char *s, const char *eos)
  528. {
  529.   /* XXXX there is too much duplicate shared between this function and
  530.    * networkstatus_parse_vote_from_string(). */
  531.   directory_token_t *tok;
  532.   memarea_t *area = NULL;
  533.   smartlist_t *tokens = smartlist_create();
  534.   ns_detached_signatures_t *sigs =
  535.     tor_malloc_zero(sizeof(ns_detached_signatures_t));
  536.   if (!eos)
  537.     eos = s + strlen(s);
  538.   area = memarea_new();
  539.   if (tokenize_string(area,s, eos, tokens,
  540.                       networkstatus_detached_signature_token_table, 0)) {
  541.     log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
  542.     goto err;
  543.   }
  544.   tok = find_by_keyword(tokens, K_CONSENSUS_DIGEST);
  545.   if (strlen(tok->args[0]) != HEX_DIGEST_LEN) {
  546.     log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
  547.              "networkstatus signatures");
  548.     goto err;
  549.   }
  550.   if (base16_decode(sigs->networkstatus_digest, DIGEST_LEN,
  551.                     tok->args[0], strlen(tok->args[0])) < 0) {
  552.     log_warn(LD_DIR, "Bad encoding on on consensus-digest in detached "
  553.              "networkstatus signatures");
  554.     goto err;
  555.   }
  556.   tok = find_by_keyword(tokens, K_VALID_AFTER);
  557.   if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
  558.     log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
  559.     goto err;
  560.   }
  561.   tok = find_by_keyword(tokens, K_FRESH_UNTIL);
  562.   if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
  563.     log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
  564.     goto err;
  565.   }
  566.   tok = find_by_keyword(tokens, K_VALID_UNTIL);
  567.   if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
  568.     log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
  569.     goto err;
  570.   }
  571.   sigs->signatures = smartlist_create();
  572.   SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
  573.     {
  574.       char id_digest[DIGEST_LEN];
  575.       char sk_digest[DIGEST_LEN];
  576.       networkstatus_voter_info_t *voter;
  577.       tok = _tok;
  578.       if (tok->tp != K_DIRECTORY_SIGNATURE)
  579.         continue;
  580.       tor_assert(tok->n_args >= 2);
  581.       if (!tok->object_type ||
  582.           strcmp(tok->object_type, "SIGNATURE") ||
  583.           tok->object_size < 128 || tok->object_size > 512) {
  584.         log_warn(LD_DIR, "Bad object type or length on directory-signature");
  585.         goto err;
  586.       }
  587.       if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
  588.           base16_decode(id_digest, sizeof(id_digest),
  589.                         tok->args[0], HEX_DIGEST_LEN) < 0) {
  590.         log_warn(LD_DIR, "Error decoding declared identity %s in "
  591.                  "network-status vote.", escaped(tok->args[0]));
  592.         goto err;
  593.       }
  594.       if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
  595.           base16_decode(sk_digest, sizeof(sk_digest),
  596.                         tok->args[1], HEX_DIGEST_LEN) < 0) {
  597.         log_warn(LD_DIR, "Error decoding declared digest %s in "
  598.                  "network-status vote.", escaped(tok->args[1]));
  599.         goto err;
  600.       }
  601.       voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
  602.       memcpy(voter->identity_digest, id_digest, DIGEST_LEN);
  603.       memcpy(voter->signing_key_digest, sk_digest, DIGEST_LEN);
  604.       if (tok->object_size >= INT_MAX)
  605.         goto err;
  606.       voter->signature = tor_memdup(tok->object_body, tok->object_size);
  607.       voter->signature_len = (int) tok->object_size;
  608.       smartlist_add(sigs->signatures, voter);
  609.     });
  610.   goto done;
  611.  err:
  612.   ns_detached_signatures_free(sigs);
  613.   sigs = NULL;
  614.  done:
  615.   SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  616.   smartlist_free(tokens);
  617.   if (area) {
  618.     DUMP_AREA(area, "detached signatures");
  619.     memarea_drop_all(area);
  620.   }
  621.   return sigs;
  622. }
  623. /** Parse the addr policy in the string <b>s</b> and return it.  If
  624.  * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
  625.  * ADDR_POLICY_REJECT) for items that specify no action.
  626.  */
  627. addr_policy_t *
  628. router_parse_addr_policy_item_from_string(const char *s, int assume_action)
  629. {
  630.   directory_token_t *tok = NULL;
  631.   const char *cp, *eos;
  632.   /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
  633.    * But note that there can be an arbitrary amount of space between the
  634.    * accept and the address:mask/port element. */
  635.   char line[TOR_ADDR_BUF_LEN*2 + 32];
  636.   addr_policy_t *r;
  637.   memarea_t *area = NULL;
  638.   s = eat_whitespace(s);
  639.   if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
  640.     if (tor_snprintf(line, sizeof(line), "%s %s",
  641.                assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
  642.       log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
  643.       return NULL;
  644.     }
  645.     cp = line;
  646.     tor_strlower(line);
  647.   } else { /* assume an already well-formed address policy line */
  648.     cp = s;
  649.   }
  650.   eos = cp + strlen(cp);
  651.   area = memarea_new();
  652.   tok = get_next_token(area, &cp, eos, routerdesc_token_table);
  653.   if (tok->tp == _ERR) {
  654.     log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
  655.     goto err;
  656.   }
  657.   if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
  658.       tok->tp != K_REJECT && tok->tp != K_REJECT6) {
  659.     log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
  660.     goto err;
  661.   }
  662.   r = router_parse_addr_policy(tok);
  663.   goto done;
  664.  err:
  665.   r = NULL;
  666.  done:
  667.   token_free(tok);
  668.   if (area) {
  669.     DUMP_AREA(area, "policy item");
  670.     memarea_drop_all(area);
  671.   }
  672.   return r;
  673. }
  674. /** Add an exit policy stored in the token <b>tok</b> to the router info in
  675.  * <b>router</b>.  Return 0 on success, -1 on failure. */
  676. static int
  677. router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
  678. {
  679.   addr_policy_t *newe;
  680.   newe = router_parse_addr_policy(tok);
  681.   if (!newe)
  682.     return -1;
  683.   if (! router->exit_policy)
  684.     router->exit_policy = smartlist_create();
  685.   if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
  686.        tor_addr_family(&newe->addr) == AF_INET)
  687.       ||
  688.       ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
  689.        tor_addr_family(&newe->addr) == AF_INET6)) {
  690.     log_warn(LD_DIR, "Mismatch between field type and address type in exit "
  691.              "policy");
  692.     addr_policy_free(newe);
  693.     return -1;
  694.   }
  695.   smartlist_add(router->exit_policy, newe);
  696.   return 0;
  697. }
  698. /** Given a K_ACCEPT or K_REJECT token and a router, create and return
  699.  * a new exit_policy_t corresponding to the token. */
  700. static addr_policy_t *
  701. router_parse_addr_policy(directory_token_t *tok)
  702. {
  703.   addr_policy_t newe;
  704.   char *arg;
  705.   tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
  706.              tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
  707.   if (tok->n_args != 1)
  708.     return NULL;
  709.   arg = tok->args[0];
  710.   if (!strcmpstart(arg,"private"))
  711.     return router_parse_addr_policy_private(tok);
  712.   memset(&newe, 0, sizeof(newe));
  713.   if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
  714.     newe.policy_type = ADDR_POLICY_REJECT;
  715.   else
  716.     newe.policy_type = ADDR_POLICY_ACCEPT;
  717.   if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits,
  718.                                 &newe.prt_min, &newe.prt_max) < 0) {
  719.     log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
  720.     return NULL;
  721.   }
  722.   return addr_policy_get_canonical_entry(&newe);
  723. }
  724. /** Parse an exit policy line of the format "accept/reject private:...".
  725.  * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
  726.  * router descriptors until earlier versions are obsolete.
  727.  */
  728. static addr_policy_t *
  729. router_parse_addr_policy_private(directory_token_t *tok)
  730. {
  731.   const char *arg;
  732.   uint16_t port_min, port_max;
  733.   addr_policy_t result;
  734.   arg = tok->args[0];
  735.   if (strcmpstart(arg, "private"))
  736.     return NULL;
  737.   arg += strlen("private");
  738.   arg = (char*) eat_whitespace(arg);
  739.   if (!arg || *arg != ':')
  740.     return NULL;
  741.   if (parse_port_range(arg+1, &port_min, &port_max)<0)
  742.     return NULL;
  743.   memset(&result, 0, sizeof(result));
  744.   if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
  745.     result.policy_type = ADDR_POLICY_REJECT;
  746.   else
  747.     result.policy_type = ADDR_POLICY_ACCEPT;
  748.   result.is_private = 1;
  749.   result.prt_min = port_min;
  750.   result.prt_max = port_max;
  751.   return addr_policy_get_canonical_entry(&result);
  752. }
  753. /** Log and exit if <b>t</b> is malformed */
  754. void
  755. assert_addr_policy_ok(smartlist_t *lst)
  756. {
  757.   if (!lst) return;
  758.   SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
  759.     tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
  760.                t->policy_type == ADDR_POLICY_ACCEPT);
  761.     tor_assert(t->prt_min <= t->prt_max);
  762.   });
  763. }
  764. /*
  765.  * Low-level tokenizer for router descriptors and directories.
  766.  */
  767. /** Free all resources allocated for <b>tok</b> */
  768. static void
  769. token_free(directory_token_t *tok)
  770. {
  771.   tor_assert(tok);
  772.   if (tok->key)
  773.     crypto_free_pk_env(tok->key);
  774. }
  775. #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
  776. #define ALLOC(sz) memarea_alloc(area,sz)
  777. #define STRDUP(str) memarea_strdup(area,str)
  778. #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
  779. #define RET_ERR(msg)                                               
  780.   STMT_BEGIN                                                       
  781.     if (tok) token_free(tok);                                      
  782.     tok = ALLOC_ZERO(sizeof(directory_token_t));                   
  783.     tok->tp = _ERR;                                                
  784.     tok->error = STRDUP(msg);                                      
  785.     goto done_tokenizing;                                          
  786.   STMT_END
  787. /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
  788.  * the object syntax of <b>o_syn</b>.  Allocate all storage in <b>area</b>.
  789.  * Return <b>tok</b> on success, or a new _ERR token if the token didn't
  790.  * conform to the syntax we wanted.
  791.  **/
  792. static INLINE directory_token_t *
  793. token_check_object(memarea_t *area, const char *kwd,
  794.                    directory_token_t *tok, obj_syntax o_syn)
  795. {
  796.   char ebuf[128];
  797.   switch (o_syn) {
  798.     case NO_OBJ:
  799.       /* No object is allowed for this token. */
  800.       if (tok->object_body) {
  801.         tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
  802.         RET_ERR(ebuf);
  803.       }
  804.       if (tok->key) {
  805.         tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
  806.         RET_ERR(ebuf);
  807.       }
  808.       break;
  809.     case NEED_OBJ:
  810.       /* There must be a (non-key) object. */
  811.       if (!tok->object_body) {
  812.         tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
  813.         RET_ERR(ebuf);
  814.       }
  815.       break;
  816.     case NEED_KEY_1024: /* There must be a 1024-bit public key. */
  817.     case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
  818.       if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
  819.         tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
  820.                      kwd, (int)crypto_pk_keysize(tok->key));
  821.         RET_ERR(ebuf);
  822.       }
  823.       /* fall through */
  824.     case NEED_KEY: /* There must be some kind of key. */
  825.       if (!tok->key) {
  826.         tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
  827.         RET_ERR(ebuf);
  828.       }
  829.       if (o_syn != NEED_SKEY_1024) {
  830.         if (crypto_pk_key_is_private(tok->key)) {
  831.           tor_snprintf(ebuf, sizeof(ebuf),
  832.                "Private key given for %s, which wants a public key", kwd);
  833.           RET_ERR(ebuf);
  834.         }
  835.       } else { /* o_syn == NEED_SKEY_1024 */
  836.         if (!crypto_pk_key_is_private(tok->key)) {
  837.           tor_snprintf(ebuf, sizeof(ebuf),
  838.                "Public key given for %s, which wants a private key", kwd);
  839.           RET_ERR(ebuf);
  840.         }
  841.       }
  842.       break;
  843.     case OBJ_OK:
  844.       /* Anything goes with this token. */
  845.       break;
  846.   }
  847.  done_tokenizing:
  848.   return tok;
  849. }
  850. /** Helper: parse space-separated arguments from the string <b>s</b> ending at
  851.  * <b>eol</b>, and store them in the args field of <b>tok</b>.  Store the
  852.  * number of parsed elements into the n_args field of <b>tok</b>.  Allocate
  853.  * all storage in <b>area</b>.  Return the number of arguments parsed, or
  854.  * return -1 if there was an insanely high number of arguments. */
  855. static INLINE int
  856. get_token_arguments(memarea_t *area, directory_token_t *tok,
  857.                     const char *s, const char *eol)
  858. {
  859. /** Largest number of arguments we'll accept to any token, ever. */
  860. #define MAX_ARGS 512
  861.   char *mem = memarea_strndup(area, s, eol-s);
  862.   char *cp = mem;
  863.   int j = 0;
  864.   char *args[MAX_ARGS];
  865.   while (*cp) {
  866.     if (j == MAX_ARGS)
  867.       return -1;
  868.     args[j++] = cp;
  869.     cp = (char*)find_whitespace(cp);
  870.     if (!cp || !*cp)
  871.       break; /* End of the line. */
  872.     *cp++ = '';
  873.     cp = (char*)eat_whitespace(cp);
  874.   }
  875.   tok->n_args = j;
  876.   tok->args = memarea_memdup(area, args, j*sizeof(char*));
  877.   return j;
  878. #undef MAX_ARGS
  879. }
  880. /** Helper function: read the next token from *s, advance *s to the end of the
  881.  * token, and return the parsed token.  Parse *<b>s</b> according to the list
  882.  * of tokens in <b>table</b>.
  883.  */
  884. static directory_token_t *
  885. get_next_token(memarea_t *area,
  886.                const char **s, const char *eos, token_rule_t *table)
  887. {
  888.   const char *next, *eol, *obstart;
  889.   size_t obname_len;
  890.   int i;
  891.   directory_token_t *tok;
  892.   obj_syntax o_syn = NO_OBJ;
  893.   char ebuf[128];
  894.   const char *kwd = "";
  895.   tor_assert(area);
  896.   tok = ALLOC_ZERO(sizeof(directory_token_t));
  897.   tok->tp = _ERR;
  898.   /* Set *s to first token, eol to end-of-line, next to after first token */
  899.   *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
  900.   tor_assert(eos >= *s);
  901.   eol = memchr(*s, 'n', eos-*s);
  902.   if (!eol)
  903.     eol = eos;
  904.   next = find_whitespace_eos(*s, eol);
  905.   if (!strcmp_len(*s, "opt", next-*s)) {
  906.     /* Skip past an "opt" at the start of the line. */
  907.     *s = eat_whitespace_eos_no_nl(next, eol);
  908.     next = find_whitespace_eos(*s, eol);
  909.   } else if (*s == eos) {  /* If no "opt", and end-of-line, line is invalid */
  910.     RET_ERR("Unexpected EOF");
  911.   }
  912.   /* Search the table for the appropriate entry.  (I tried a binary search
  913.    * instead, but it wasn't any faster.) */
  914.   for (i = 0; table[i].t ; ++i) {
  915.     if (!strcmp_len(*s, table[i].t, next-*s)) {
  916.       /* We've found the keyword. */
  917.       kwd = table[i].t;
  918.       tok->tp = table[i].v;
  919.       o_syn = table[i].os;
  920.       *s = eat_whitespace_eos_no_nl(next, eol);
  921.       /* We go ahead whether there are arguments or not, so that tok->args is
  922.        * always set if we want arguments. */
  923.       if (table[i].concat_args) {
  924.         /* The keyword takes the line as a single argument */
  925.         tok->args = ALLOC(sizeof(char*));
  926.         tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
  927.         tok->n_args = 1;
  928.       } else {
  929.         /* This keyword takes multiple arguments. */
  930.         if (get_token_arguments(area, tok, *s, eol)<0) {
  931.           tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
  932.           RET_ERR(ebuf);
  933.         }
  934.         *s = eol;
  935.       }
  936.       if (tok->n_args < table[i].min_args) {
  937.         tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
  938.         RET_ERR(ebuf);
  939.       } else if (tok->n_args > table[i].max_args) {
  940.         tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
  941.         RET_ERR(ebuf);
  942.       }
  943.       break;
  944.     }
  945.   }
  946.   if (tok->tp == _ERR) {
  947.     /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
  948.     if (**s == '@')
  949.       tok->tp = _A_UNKNOWN;
  950.     else
  951.       tok->tp = K_OPT;
  952.     tok->args = ALLOC(sizeof(char*));
  953.     tok->args[0] = STRNDUP(*s, eol-*s);
  954.     tok->n_args = 1;
  955.     o_syn = OBJ_OK;
  956.   }
  957.   /* Check whether there's an object present */
  958.   *s = eat_whitespace_eos(eol, eos);  /* Scan from end of first line */
  959.   tor_assert(eos >= *s);
  960.   eol = memchr(*s, 'n', eos-*s);
  961.   if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
  962.     goto check_object;
  963.   obstart = *s; /* Set obstart to start of object spec */
  964.   if (*s+16 >= eol || memchr(*s+11,'',eol-*s-16) || /* no short lines, */
  965.       strcmp_len(eol-5, "-----", 5)) {          /* nuls or invalid endings */
  966.     RET_ERR("Malformed object: bad begin line");
  967.   }
  968.   tok->object_type = STRNDUP(*s+11, eol-*s-16);
  969.   obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
  970.   *s = eol+1;    /* Set *s to possible start of object data (could be eos) */
  971.   /* Go to the end of the object */
  972.   next = tor_memstr(*s, eos-*s, "-----END ");
  973.   if (!next) {
  974.     RET_ERR("Malformed object: missing object end line");
  975.   }
  976.   tor_assert(eos >= next);
  977.   eol = memchr(next, 'n', eos-next);
  978.   if (!eol)  /* end-of-line marker, or eos if there's no 'n' */
  979.     eol = eos;
  980.   /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
  981.   if ((size_t)(eol-next) != 9+obname_len+5 ||
  982.       strcmp_len(next+9, tok->object_type, obname_len) ||
  983.       strcmp_len(eol-5, "-----", 5)) {
  984.     snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
  985.              tok->object_type);
  986.     ebuf[sizeof(ebuf)-1] = '';
  987.     RET_ERR(ebuf);
  988.   }
  989.   if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
  990.     tok->key = crypto_new_pk_env();
  991.     if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
  992.       RET_ERR("Couldn't parse public key.");
  993.   } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
  994.     tok->key = crypto_new_pk_env();
  995.     if (crypto_pk_read_private_key_from_string(tok->key, obstart))
  996.       RET_ERR("Couldn't parse private key.");
  997.   } else { /* If it's something else, try to base64-decode it */
  998.     int r;
  999.     tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
  1000.     r = base64_decode(tok->object_body, next-*s, *s, next-*s);
  1001.     if (r<0)
  1002.       RET_ERR("Malformed object: bad base64-encoded data");
  1003.     tok->object_size = r;
  1004.   }
  1005.   *s = eol;
  1006.  check_object:
  1007.   tok = token_check_object(area, kwd, tok, o_syn);
  1008.  done_tokenizing:
  1009.   return tok;
  1010. #undef RET_ERR
  1011. #undef ALLOC
  1012. #undef ALLOC_ZERO
  1013. #undef STRDUP
  1014. #undef STRNDUP
  1015. }
  1016. /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
  1017.  * them to <b>out</b>.  Parse according to the token rules in <b>table</b>.
  1018.  * Caller must free tokens in <b>out</b>.  If <b>end</b> is NULL, use the
  1019.  * entire string.
  1020.  */
  1021. static int
  1022. tokenize_string(memarea_t *area,
  1023.                 const char *start, const char *end, smartlist_t *out,
  1024.                 token_rule_t *table, int flags)
  1025. {
  1026.   const char **s;
  1027.   directory_token_t *tok = NULL;
  1028.   int counts[_NIL];
  1029.   int i;
  1030.   int first_nonannotation;
  1031.   int prev_len = smartlist_len(out);
  1032.   tor_assert(area);
  1033.   s = &start;
  1034.   if (!end)
  1035.     end = start+strlen(start);
  1036.   for (i = 0; i < _NIL; ++i)
  1037.     counts[i] = 0;
  1038.   while (*s < end && (!tok || tok->tp != _EOF)) {
  1039.     tok = get_next_token(area, s, end, table);
  1040.     if (tok->tp == _ERR) {
  1041.       log_warn(LD_DIR, "parse error: %s", tok->error);
  1042.       token_free(tok);
  1043.       return -1;
  1044.     }
  1045.     ++counts[tok->tp];
  1046.     smartlist_add(out, tok);
  1047.     *s = eat_whitespace_eos(*s, end);
  1048.   }
  1049.   if (flags & TS_NOCHECK)
  1050.     return 0;
  1051.   if ((flags & TS_ANNOTATIONS_OK)) {
  1052.     first_nonannotation = -1;
  1053.     for (i = 0; i < smartlist_len(out); ++i) {
  1054.       tok = smartlist_get(out, i);
  1055.       if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
  1056.         first_nonannotation = i;
  1057.         break;
  1058.       }
  1059.     }
  1060.     if (first_nonannotation < 0) {
  1061.       log_warn(LD_DIR, "parse error: item contains only annotations");
  1062.       return -1;
  1063.     }
  1064.     for (i=first_nonannotation;  i < smartlist_len(out); ++i) {
  1065.       tok = smartlist_get(out, i);
  1066.       if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
  1067.         log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
  1068.         return -1;
  1069.       }
  1070.     }
  1071.     if ((flags & TS_NO_NEW_ANNOTATIONS)) {
  1072.       if (first_nonannotation != prev_len) {
  1073.         log_warn(LD_DIR, "parse error: Unexpected annotations.");
  1074.         return -1;
  1075.       }
  1076.     }
  1077.   } else {
  1078.     for (i=0;  i < smartlist_len(out); ++i) {
  1079.       tok = smartlist_get(out, i);
  1080.       if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
  1081.         log_warn(LD_DIR, "parse error: no annotations allowed.");
  1082.         return -1;
  1083.       }
  1084.     }
  1085.     first_nonannotation = 0;
  1086.   }
  1087.   for (i = 0; table[i].t; ++i) {
  1088.     if (counts[table[i].v] < table[i].min_cnt) {
  1089.       log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
  1090.       return -1;
  1091.     }
  1092.     if (counts[table[i].v] > table[i].max_cnt) {
  1093.       log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
  1094.       return -1;
  1095.     }
  1096.     if (table[i].pos & AT_START) {
  1097.       if (smartlist_len(out) < 1 ||
  1098.           (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
  1099.         log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
  1100.         return -1;
  1101.       }
  1102.     }
  1103.     if (table[i].pos & AT_END) {
  1104.       if (smartlist_len(out) < 1 ||
  1105.           (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
  1106.         log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
  1107.         return -1;
  1108.       }
  1109.     }
  1110.   }
  1111.   return 0;
  1112. }
  1113. /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
  1114.  * NULL if no such keyword is found.
  1115.  */
  1116. static directory_token_t *
  1117. find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
  1118. {
  1119.   SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
  1120.   return NULL;
  1121. }
  1122. /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
  1123.  * with an assert if no such keyword is found.
  1124.  */
  1125. static directory_token_t *
  1126. _find_by_keyword(smartlist_t *s, directory_keyword keyword,
  1127.                  const char *keyword_as_string)
  1128. {
  1129.   directory_token_t *tok = find_opt_by_keyword(s, keyword);
  1130.   if (PREDICT_UNLIKELY(!tok)) {
  1131.     log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
  1132.          "been validated. Internal error.", keyword_as_string, (int)keyword);
  1133.     tor_assert(tok);
  1134.   }
  1135.   return tok;
  1136. }
  1137. /** Return a newly allocated smartlist of all accept or reject tokens in
  1138.  * <b>s</b>.
  1139.  */
  1140. static smartlist_t *
  1141. find_all_exitpolicy(smartlist_t *s)
  1142. {
  1143.   smartlist_t *out = smartlist_create();
  1144.   SMARTLIST_FOREACH(s, directory_token_t *, t,
  1145.       if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
  1146.           t->tp == K_REJECT || t->tp == K_REJECT6)
  1147.         smartlist_add(out,t));
  1148.   return out;
  1149. }
  1150. /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
  1151.  * occurrence of <b>start_str</b> through the first instance of c after the
  1152.  * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
  1153.  * <b>digest</b>; return 0 on success.
  1154.  *
  1155.  * If no such substring exists, return -1.
  1156.  */
  1157. static int
  1158. router_get_hash_impl(const char *s, char *digest,
  1159.                      const char *start_str,
  1160.                      const char *end_str, char end_c)
  1161. {
  1162.   char *start, *end;
  1163.   start = strstr(s, start_str);
  1164.   if (!start) {
  1165.     log_warn(LD_DIR,"couldn't find start of hashed material "%s"",start_str);
  1166.     return -1;
  1167.   }
  1168.   if (start != s && *(start-1) != 'n') {
  1169.     log_warn(LD_DIR,
  1170.              "first occurrence of "%s" is not at the start of a line",
  1171.              start_str);
  1172.     return -1;
  1173.   }
  1174.   end = strstr(start+strlen(start_str), end_str);
  1175.   if (!end) {
  1176.     log_warn(LD_DIR,"couldn't find end of hashed material "%s"",end_str);
  1177.     return -1;
  1178.   }
  1179.   end = strchr(end+strlen(end_str), end_c);
  1180.   if (!end) {
  1181.     log_warn(LD_DIR,"couldn't find EOL");
  1182.     return -1;
  1183.   }
  1184.   ++end;
  1185.   if (crypto_digest(digest, start, end-start)) {
  1186.     log_warn(LD_BUG,"couldn't compute digest");
  1187.     return -1;
  1188.   }
  1189.   return 0;
  1190. }
  1191. /** Parse the Tor version of the platform string <b>platform</b>,
  1192.  * and compare it to the version in <b>cutoff</b>. Return 1 if
  1193.  * the router is at least as new as the cutoff, else return 0.
  1194.  */
  1195. int
  1196. tor_version_as_new_as(const char *platform, const char *cutoff)
  1197. {
  1198.   tor_version_t cutoff_version, router_version;
  1199.   char *s, *s2, *start;
  1200.   char tmp[128];
  1201.   tor_assert(platform);
  1202.   if (tor_version_parse(cutoff, &cutoff_version)<0) {
  1203.     log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
  1204.     return 0;
  1205.   }
  1206.   if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
  1207.     return 1;
  1208.   start = (char *)eat_whitespace(platform+3);
  1209.   if (!*start) return 0;
  1210.   s = (char *)find_whitespace(start); /* also finds '', which is fine */
  1211.   s2 = (char*)eat_whitespace(s);
  1212.   if (!strcmpstart(s2, "(r"))
  1213.     s = (char*)find_whitespace(s2);
  1214.   if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
  1215.     return 0;
  1216.   strlcpy(tmp, start, s-start+1);
  1217.   if (tor_version_parse(tmp, &router_version)<0) {
  1218.     log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
  1219.     return 1; /* be safe and say yes */
  1220.   }
  1221.   /* Here's why we don't need to do any special handling for svn revisions:
  1222.    * - If neither has an svn revision, we're fine.
  1223.    * - If the router doesn't have an svn revision, we can't assume that it
  1224.    *   is "at least" any svn revision, so we need to return 0.
  1225.    * - If the target version doesn't have an svn revision, any svn revision
  1226.    *   (or none at all) is good enough, so return 1.
  1227.    * - If both target and router have an svn revision, we compare them.
  1228.    */
  1229.   return tor_version_compare(&router_version, &cutoff_version) >= 0;
  1230. }
  1231. /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
  1232.  * Return 0 on success, -1 on failure. */
  1233. int
  1234. tor_version_parse(const char *s, tor_version_t *out)
  1235. {
  1236.   char *eos=NULL;
  1237.   const char *cp=NULL;
  1238.   /* Format is:
  1239.    *   "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
  1240.    */
  1241.   tor_assert(s);
  1242.   tor_assert(out);
  1243.   memset(out, 0, sizeof(tor_version_t));
  1244.   if (!strcasecmpstart(s, "Tor "))
  1245.     s += 4;
  1246.   /* Get major. */
  1247.   out->major = (int)strtol(s,&eos,10);
  1248.   if (!eos || eos==s || *eos != '.') return -1;
  1249.   cp = eos+1;
  1250.   /* Get minor */
  1251.   out->minor = (int) strtol(cp,&eos,10);
  1252.   if (!eos || eos==cp || *eos != '.') return -1;
  1253.   cp = eos+1;
  1254.   /* Get micro */
  1255.   out->micro = (int) strtol(cp,&eos,10);
  1256.   if (!eos || eos==cp) return -1;
  1257.   if (!*eos) {
  1258.     out->status = VER_RELEASE;
  1259.     out->patchlevel = 0;
  1260.     return 0;
  1261.   }
  1262.   cp = eos;
  1263.   /* Get status */
  1264.   if (*cp == '.') {
  1265.     out->status = VER_RELEASE;
  1266.     ++cp;
  1267.   } else if (0==strncmp(cp, "pre", 3)) {
  1268.     out->status = VER_PRE;
  1269.     cp += 3;
  1270.   } else if (0==strncmp(cp, "rc", 2)) {
  1271.     out->status = VER_RC;
  1272.     cp += 2;
  1273.   } else {
  1274.     return -1;
  1275.   }
  1276.   /* Get patchlevel */
  1277.   out->patchlevel = (int) strtol(cp,&eos,10);
  1278.   if (!eos || eos==cp) return -1;
  1279.   cp = eos;
  1280.   /* Get status tag. */
  1281.   if (*cp == '-' || *cp == '.')
  1282.     ++cp;
  1283.   eos = (char*) find_whitespace(cp);
  1284.   if (eos-cp >= (int)sizeof(out->status_tag))
  1285.     strlcpy(out->status_tag, cp, sizeof(out->status_tag));
  1286.   else {
  1287.     memcpy(out->status_tag, cp, eos-cp);
  1288.     out->status_tag[eos-cp] = 0;
  1289.   }
  1290.   cp = eat_whitespace(eos);
  1291.   if (!strcmpstart(cp, "(r")) {
  1292.     cp += 2;
  1293.     out->svn_revision = (int) strtol(cp,&eos,10);
  1294.   }
  1295.   return 0;
  1296. }
  1297. /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
  1298.  * b. */
  1299. int
  1300. tor_version_compare(tor_version_t *a, tor_version_t *b)
  1301. {
  1302.   int i;
  1303.   tor_assert(a);
  1304.   tor_assert(b);
  1305.   if ((i = a->major - b->major))
  1306.     return i;
  1307.   else if ((i = a->minor - b->minor))
  1308.     return i;
  1309.   else if ((i = a->micro - b->micro))
  1310.     return i;
  1311.   else if ((i = a->status - b->status))
  1312.     return i;
  1313.   else if ((i = a->patchlevel - b->patchlevel))
  1314.     return i;
  1315.   else if ((i = strcmp(a->status_tag, b->status_tag)))
  1316.     return i;
  1317.   else
  1318.     return a->svn_revision - b->svn_revision;
  1319. }
  1320. /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
  1321.  */
  1322. static int
  1323. tor_version_same_series(tor_version_t *a, tor_version_t *b)
  1324. {
  1325.   tor_assert(a);
  1326.   tor_assert(b);
  1327.   return ((a->major == b->major) &&
  1328.           (a->minor == b->minor) &&
  1329.           (a->micro == b->micro));
  1330. }
  1331. /** Helper: Given pointers to two strings describing tor versions, return -1
  1332.  * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
  1333.  * Used to sort a list of versions. */
  1334. static int
  1335. _compare_tor_version_str_ptr(const void **_a, const void **_b)
  1336. {
  1337.   const char *a = *_a, *b = *_b;
  1338.   int ca, cb;
  1339.   tor_version_t va, vb;
  1340.   ca = tor_version_parse(a, &va);
  1341.   cb = tor_version_parse(b, &vb);
  1342.   /* If they both parse, compare them. */
  1343.   if (!ca && !cb)
  1344.     return tor_version_compare(&va,&vb);
  1345.   /* If one parses, it comes first. */
  1346.   if (!ca && cb)
  1347.     return -1;
  1348.   if (ca && !cb)
  1349.     return 1;
  1350.   /* If neither parses, compare strings.  Also, the directory server admin
  1351.   ** needs to be smacked upside the head.  But Tor is tolerant and gentle. */
  1352.   return strcmp(a,b);
  1353. }
  1354. /** Sort a list of string-representations of versions in ascending order. */
  1355. void
  1356. sort_version_list(smartlist_t *versions, int remove_duplicates)
  1357. {
  1358.   smartlist_sort(versions, _compare_tor_version_str_ptr);
  1359.   if (remove_duplicates)
  1360.     smartlist_uniq(versions, _compare_tor_version_str_ptr, _tor_free);
  1361. }
  1362. /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
  1363.  * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
  1364.  * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
  1365.  * encrypted introduction points to the newly allocated
  1366.  * *<b>intro_points_encrypted_out</b>, their encrypted size to
  1367.  * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
  1368.  * to *<b>encoded_size_out</b>, and a pointer to the possibly next
  1369.  * descriptor to *<b>next_out</b>; return 0 for success (including validation)
  1370.  * and -1 for failure.
  1371.  */
  1372. int
  1373. rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
  1374.                                  char *desc_id_out,
  1375.                                  char **intro_points_encrypted_out,
  1376.                                  size_t *intro_points_encrypted_size_out,
  1377.                                  size_t *encoded_size_out,
  1378.                                  const char **next_out, const char *desc)
  1379. {
  1380.   rend_service_descriptor_t *result =
  1381.                             tor_malloc_zero(sizeof(rend_service_descriptor_t));
  1382.   char desc_hash[DIGEST_LEN];
  1383.   const char *eos;
  1384.   smartlist_t *tokens = smartlist_create();
  1385.   directory_token_t *tok;
  1386.   char secret_id_part[DIGEST_LEN];
  1387.   int i, version, num_ok=1;
  1388.   smartlist_t *versions;
  1389.   char public_key_hash[DIGEST_LEN];
  1390.   char test_desc_id[DIGEST_LEN];
  1391.   memarea_t *area = NULL;
  1392.   tor_assert(desc);
  1393.   /* Check if desc starts correctly. */
  1394.   if (strncmp(desc, "rendezvous-service-descriptor ",
  1395.               strlen("rendezvous-service-descriptor "))) {
  1396.     log_info(LD_REND, "Descriptor does not start correctly.");
  1397.     goto err;
  1398.   }
  1399.   /* Compute descriptor hash for later validation. */
  1400.   if (router_get_hash_impl(desc, desc_hash,
  1401.                            "rendezvous-service-descriptor ",
  1402.                            "nsignature", 'n') < 0) {
  1403.     log_warn(LD_REND, "Couldn't compute descriptor hash.");
  1404.     goto err;
  1405.   }
  1406.   /* Determine end of string. */
  1407.   eos = strstr(desc, "nrendezvous-service-descriptor ");
  1408.   if (!eos)
  1409.     eos = desc + strlen(desc);
  1410.   else
  1411.     eos = eos + 1;
  1412.   /* Check length. */
  1413.   if (strlen(desc) > REND_DESC_MAX_SIZE) {
  1414.     log_warn(LD_REND, "Descriptor length is %i which exceeds "
  1415.              "maximum rendezvous descriptor size of %i kilobytes.",
  1416.              (int)strlen(desc), REND_DESC_MAX_SIZE);
  1417.     goto err;
  1418.   }
  1419.   /* Tokenize descriptor. */
  1420.   area = memarea_new();
  1421.   if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
  1422.     log_warn(LD_REND, "Error tokenizing descriptor.");
  1423.     goto err;
  1424.   }
  1425.   /* Set next to next descriptor, if available. */
  1426.   *next_out = eos;
  1427.   /* Set length of encoded descriptor. */
  1428.   *encoded_size_out = eos - desc;
  1429.   /* Check min allowed length of token list. */
  1430.   if (smartlist_len(tokens) < 7) {
  1431.     log_warn(LD_REND, "Impossibly short descriptor.");
  1432.     goto err;
  1433.   }
  1434.   /* Parse base32-encoded descriptor ID. */
  1435.   tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
  1436.   tor_assert(tok == smartlist_get(tokens, 0));
  1437.   tor_assert(tok->n_args == 1);
  1438.   if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
  1439.       strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
  1440.     log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
  1441.     goto err;
  1442.   }
  1443.   if (base32_decode(desc_id_out, DIGEST_LEN,
  1444.                     tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
  1445.     log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
  1446.              tok->args[0]);
  1447.     goto err;
  1448.   }
  1449.   /* Parse descriptor version. */
  1450.   tok = find_by_keyword(tokens, R_VERSION);
  1451.   tor_assert(tok->n_args == 1);
  1452.   result->version =
  1453.     (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
  1454.   if (result->version != 2 || !num_ok) {
  1455.     /* If it's <2, it shouldn't be under this format.  If the number
  1456.      * is greater than 2, we bumped it because we broke backward
  1457.      * compatibility.  See how version numbers in our other formats
  1458.      * work. */
  1459.     log_warn(LD_REND, "Unrecognized descriptor version: %s",
  1460.              escaped(tok->args[0]));
  1461.     goto err;
  1462.   }
  1463.   /* Parse public key. */
  1464.   tok = find_by_keyword(tokens, R_PERMANENT_KEY);
  1465.   result->pk = tok->key;
  1466.   tok->key = NULL; /* Prevent free */
  1467.   /* Parse secret ID part. */
  1468.   tok = find_by_keyword(tokens, R_SECRET_ID_PART);
  1469.   tor_assert(tok->n_args == 1);
  1470.   if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
  1471.       strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
  1472.     log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
  1473.     goto err;
  1474.   }
  1475.   if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
  1476.     log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
  1477.              tok->args[0]);
  1478.     goto err;
  1479.   }
  1480.   /* Parse publication time -- up-to-date check is done when storing the
  1481.    * descriptor. */
  1482.   tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
  1483.   tor_assert(tok->n_args == 1);
  1484.   if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
  1485.     log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
  1486.     goto err;
  1487.   }
  1488.   /* Parse protocol versions. */
  1489.   tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
  1490.   tor_assert(tok->n_args == 1);
  1491.   versions = smartlist_create();
  1492.   smartlist_split_string(versions, tok->args[0], ",",
  1493.                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
  1494.   for (i = 0; i < smartlist_len(versions); i++) {
  1495.     version = (int) tor_parse_long(smartlist_get(versions, i),
  1496.                                    10, 0, INT_MAX, &num_ok, NULL);
  1497.     if (!num_ok) /* It's a string; let's ignore it. */
  1498.       continue;
  1499.     result->protocols |= 1 << version;
  1500.   }
  1501.   SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
  1502.   smartlist_free(versions);
  1503.   /* Parse encrypted introduction points. Don't verify. */
  1504.   tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
  1505.   if (tok) {
  1506.     if (strcmp(tok->object_type, "MESSAGE")) {
  1507.       log_warn(LD_DIR, "Bad object type: introduction points should be of "
  1508.                "type MESSAGE");
  1509.       goto err;
  1510.     }
  1511.     *intro_points_encrypted_out = tor_memdup(tok->object_body,
  1512.                                              tok->object_size);
  1513.     *intro_points_encrypted_size_out = tok->object_size;
  1514.   } else {
  1515.     *intro_points_encrypted_out = NULL;
  1516.     *intro_points_encrypted_size_out = 0;
  1517.   }
  1518.   /* Parse and verify signature. */
  1519.   tok = find_by_keyword(tokens, R_SIGNATURE);
  1520.   note_crypto_pk_op(VERIFY_RTR);
  1521.   if (check_signature_token(desc_hash, tok, result->pk, 0,
  1522.                             "v2 rendezvous service descriptor") < 0)
  1523.     goto err;
  1524.   /* Verify that descriptor ID belongs to public key and secret ID part. */
  1525.   crypto_pk_get_digest(result->pk, public_key_hash);
  1526.   rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
  1527.                                secret_id_part);
  1528.   if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) {
  1529.     log_warn(LD_REND, "Parsed descriptor ID does not match "
  1530.              "computed descriptor ID.");
  1531.     goto err;
  1532.   }
  1533.   goto done;
  1534.  err:
  1535.   if (result)
  1536.     rend_service_descriptor_free(result);
  1537.   result = NULL;
  1538.  done:
  1539.   if (tokens) {
  1540.     SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  1541.     smartlist_free(tokens);
  1542.   }
  1543.   if (area)
  1544.     memarea_drop_all(area);
  1545.   *parsed_out = result;
  1546.   if (result)
  1547.     return 0;
  1548.   return -1;
  1549. }
  1550. /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
  1551.  * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
  1552.  * write the result to a newly allocated string that is pointed to by
  1553.  * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
  1554.  * Return 0 if decryption was successful and -1 otherwise. */
  1555. int
  1556. rend_decrypt_introduction_points(char **ipos_decrypted,
  1557.                                  size_t *ipos_decrypted_size,
  1558.                                  const char *descriptor_cookie,
  1559.                                  const char *ipos_encrypted,
  1560.                                  size_t ipos_encrypted_size)
  1561. {
  1562.   tor_assert(ipos_encrypted);
  1563.   tor_assert(descriptor_cookie);
  1564.   if (ipos_encrypted_size < 2) {
  1565.     log_warn(LD_REND, "Size of encrypted introduction points is too "
  1566.                       "small.");
  1567.     return -1;
  1568.   }
  1569.   if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
  1570.     char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
  1571.          session_key[CIPHER_KEY_LEN], *dec;
  1572.     int declen, client_blocks;
  1573.     size_t pos = 0, len, client_entries_len;
  1574.     crypto_digest_env_t *digest;
  1575.     crypto_cipher_env_t *cipher;
  1576.     client_blocks = (int) ipos_encrypted[1];
  1577.     client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
  1578.                          REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
  1579.     if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
  1580.       log_warn(LD_REND, "Size of encrypted introduction points is too "
  1581.                         "small.");
  1582.       return -1;
  1583.     }
  1584.     memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
  1585.     digest = crypto_new_digest_env();
  1586.     crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
  1587.     crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
  1588.     crypto_digest_get_digest(digest, client_id,
  1589.                              REND_BASIC_AUTH_CLIENT_ID_LEN);
  1590.     crypto_free_digest_env(digest);
  1591.     for (pos = 2; pos < 2 + client_entries_len;
  1592.          pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
  1593.       if (!memcmp(ipos_encrypted + pos, client_id,
  1594.                   REND_BASIC_AUTH_CLIENT_ID_LEN)) {
  1595.         /* Attempt to decrypt introduction points. */
  1596.         cipher = crypto_create_init_cipher(descriptor_cookie, 0);
  1597.         if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
  1598.                                   + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
  1599.                                   CIPHER_KEY_LEN) < 0) {
  1600.           log_warn(LD_REND, "Could not decrypt session key for client.");
  1601.           crypto_free_cipher_env(cipher);
  1602.           return -1;
  1603.         }
  1604.         crypto_free_cipher_env(cipher);
  1605.         cipher = crypto_create_init_cipher(session_key, 0);
  1606.         len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
  1607.         dec = tor_malloc(len);
  1608.         declen = crypto_cipher_decrypt_with_iv(cipher, dec, len,
  1609.             ipos_encrypted + 2 + client_entries_len,
  1610.             ipos_encrypted_size - 2 - client_entries_len);
  1611.         crypto_free_cipher_env(cipher);
  1612.         if (declen < 0) {
  1613.           log_warn(LD_REND, "Could not decrypt introduction point string.");
  1614.           tor_free(dec);
  1615.           return -1;
  1616.         }
  1617.         if (memcmpstart(dec, declen, "introduction-point ")) {
  1618.           log_warn(LD_REND, "Decrypted introduction points don't "
  1619.                             "look like we could parse them.");
  1620.           tor_free(dec);
  1621.           continue;
  1622.         }
  1623.         *ipos_decrypted = dec;
  1624.         *ipos_decrypted_size = declen;
  1625.         return 0;
  1626.       }
  1627.     }
  1628.     log_warn(LD_REND, "Could not decrypt introduction points. Please "
  1629.              "check your authorization for this service!");
  1630.     return -1;
  1631.   } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
  1632.     crypto_cipher_env_t *cipher;
  1633.     char *dec;
  1634.     int declen;
  1635.     dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
  1636.     cipher = crypto_create_init_cipher(descriptor_cookie, 0);
  1637.     declen = crypto_cipher_decrypt_with_iv(cipher, dec,
  1638.                                            ipos_encrypted_size -
  1639.                                                CIPHER_IV_LEN - 1,
  1640.                                            ipos_encrypted + 1,
  1641.                                            ipos_encrypted_size - 1);
  1642.     crypto_free_cipher_env(cipher);
  1643.     if (declen < 0) {
  1644.       log_warn(LD_REND, "Decrypting introduction points failed!");
  1645.       tor_free(dec);
  1646.       return -1;
  1647.     }
  1648.     *ipos_decrypted = dec;
  1649.     *ipos_decrypted_size = declen;
  1650.     return 0;
  1651.   } else {
  1652.     log_warn(LD_REND, "Unknown authorization type number: %d",
  1653.              ipos_encrypted[0]);
  1654.     return -1;
  1655.   }
  1656. }
  1657. /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
  1658.  * length <b>intro_points_encoded_size</b> and write the result to the
  1659.  * descriptor in <b>parsed</b>; return the number of successfully parsed
  1660.  * introduction points or -1 in case of a failure. */
  1661. int
  1662. rend_parse_introduction_points(rend_service_descriptor_t *parsed,
  1663.                                const char *intro_points_encoded,
  1664.                                size_t intro_points_encoded_size)
  1665. {
  1666.   const char *current_ipo, *end_of_intro_points;
  1667.   smartlist_t *tokens;
  1668.   directory_token_t *tok;
  1669.   rend_intro_point_t *intro;
  1670.   extend_info_t *info;
  1671.   int result, num_ok=1;
  1672.   memarea_t *area = NULL;
  1673.   tor_assert(parsed);
  1674.   /** Function may only be invoked once. */
  1675.   tor_assert(!parsed->intro_nodes);
  1676.   tor_assert(intro_points_encoded);
  1677.   tor_assert(intro_points_encoded_size > 0);
  1678.   /* Consider one intro point after the other. */
  1679.   current_ipo = intro_points_encoded;
  1680.   end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
  1681.   tokens = smartlist_create();
  1682.   parsed->intro_nodes = smartlist_create();
  1683.   area = memarea_new();
  1684.   while (!memcmpstart(current_ipo, end_of_intro_points-current_ipo,
  1685.                       "introduction-point ")) {
  1686.     /* Determine end of string. */
  1687.     const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
  1688.                                  "nintroduction-point ");
  1689.     if (!eos)
  1690.       eos = end_of_intro_points;
  1691.     else
  1692.       eos = eos+1;
  1693.     tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
  1694.     /* Free tokens and clear token list. */
  1695.     SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  1696.     smartlist_clear(tokens);
  1697.     memarea_clear(area);
  1698.     /* Tokenize string. */
  1699.     if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
  1700.       log_warn(LD_REND, "Error tokenizing introduction point");
  1701.       goto err;
  1702.     }
  1703.     /* Advance to next introduction point, if available. */
  1704.     current_ipo = eos;
  1705.     /* Check minimum allowed length of introduction point. */
  1706.     if (smartlist_len(tokens) < 5) {
  1707.       log_warn(LD_REND, "Impossibly short introduction point.");
  1708.       goto err;
  1709.     }
  1710.     /* Allocate new intro point and extend info. */
  1711.     intro = tor_malloc_zero(sizeof(rend_intro_point_t));
  1712.     info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
  1713.     /* Parse identifier. */
  1714.     tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
  1715.     if (base32_decode(info->identity_digest, DIGEST_LEN,
  1716.                       tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
  1717.       log_warn(LD_REND, "Identity digest contains illegal characters: %s",
  1718.                tok->args[0]);
  1719.       rend_intro_point_free(intro);
  1720.       goto err;
  1721.     }
  1722.     /* Write identifier to nickname. */
  1723.     info->nickname[0] = '$';
  1724.     base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
  1725.                   info->identity_digest, DIGEST_LEN);
  1726.     /* Parse IP address. */
  1727.     tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
  1728.     if (tor_addr_from_str(&info->addr, tok->args[0])<0) {
  1729.       log_warn(LD_REND, "Could not parse introduction point address.");
  1730.       rend_intro_point_free(intro);
  1731.       goto err;
  1732.     }
  1733.     if (tor_addr_family(&info->addr) != AF_INET) {
  1734.       log_warn(LD_REND, "Introduction point address was not ipv4.");
  1735.       rend_intro_point_free(intro);
  1736.       goto err;
  1737.     }
  1738.     /* Parse onion port. */
  1739.     tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
  1740.     info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
  1741.                                            &num_ok,NULL);
  1742.     if (!info->port || !num_ok) {
  1743.       log_warn(LD_REND, "Introduction point onion port %s is invalid",
  1744.                escaped(tok->args[0]));
  1745.       rend_intro_point_free(intro);
  1746.       goto err;
  1747.     }
  1748.     /* Parse onion key. */
  1749.     tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
  1750.     info->onion_key = tok->key;
  1751.     tok->key = NULL; /* Prevent free */
  1752.     /* Parse service key. */
  1753.     tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
  1754.     intro->intro_key = tok->key;
  1755.     tok->key = NULL; /* Prevent free */
  1756.     /* Add extend info to list of introduction points. */
  1757.     smartlist_add(parsed->intro_nodes, intro);
  1758.   }
  1759.   result = smartlist_len(parsed->intro_nodes);
  1760.   goto done;
  1761.  err:
  1762.   result = -1;
  1763.  done:
  1764.   /* Free tokens and clear token list. */
  1765.   SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  1766.   smartlist_free(tokens);
  1767.   if (area)
  1768.     memarea_drop_all(area);
  1769.   return result;
  1770. }
  1771. /** Parse the content of a client_key file in <b>ckstr</b> and add
  1772.  * rend_authorized_client_t's for each parsed client to
  1773.  * <b>parsed_clients</b>. Return the number of parsed clients as result
  1774.  * or -1 for failure. */
  1775. int
  1776. rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
  1777. {
  1778.   int result = -1;
  1779.   smartlist_t *tokens;
  1780.   directory_token_t *tok;
  1781.   const char *current_entry = NULL;
  1782.   memarea_t *area = NULL;
  1783.   if (!ckstr || strlen(ckstr) == 0)
  1784.     return -1;
  1785.   tokens = smartlist_create();
  1786.   /* Begin parsing with first entry, skipping comments or whitespace at the
  1787.    * beginning. */
  1788.   area = memarea_new();
  1789.   current_entry = eat_whitespace(ckstr);
  1790.   while (!strcmpstart(current_entry, "client-name ")) {
  1791.     rend_authorized_client_t *parsed_entry;
  1792.     size_t len;
  1793.     char descriptor_cookie_base64[REND_DESC_COOKIE_LEN_BASE64+2+1];
  1794.     char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
  1795.     /* Determine end of string. */
  1796.     const char *eos = strstr(current_entry, "nclient-name ");
  1797.     if (!eos)
  1798.       eos = current_entry + strlen(current_entry);
  1799.     else
  1800.       eos = eos + 1;
  1801.     /* Free tokens and clear token list. */
  1802.     SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  1803.     smartlist_clear(tokens);
  1804.     memarea_clear(area);
  1805.     /* Tokenize string. */
  1806.     if (tokenize_string(area, current_entry, eos, tokens,
  1807.                         client_keys_token_table, 0)) {
  1808.       log_warn(LD_REND, "Error tokenizing client keys file.");
  1809.       goto err;
  1810.     }
  1811.     /* Advance to next entry, if available. */
  1812.     current_entry = eos;
  1813.     /* Check minimum allowed length of token list. */
  1814.     if (smartlist_len(tokens) < 2) {
  1815.       log_warn(LD_REND, "Impossibly short client key entry.");
  1816.       goto err;
  1817.     }
  1818.     /* Parse client name. */
  1819.     tok = find_by_keyword(tokens, C_CLIENT_NAME);
  1820.     tor_assert(tok == smartlist_get(tokens, 0));
  1821.     tor_assert(tok->n_args == 1);
  1822.     len = strlen(tok->args[0]);
  1823.     if (len < 1 || len > 19 ||
  1824.       strspn(tok->args[0], REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
  1825.       log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
  1826.                "between 1 and 19, and valid characters are "
  1827.                "[A-Za-z0-9+-_].)", tok->args[0]);
  1828.       goto err;
  1829.     }
  1830.     /* Check if client name is duplicate. */
  1831.     if (strmap_get(parsed_clients, tok->args[0])) {
  1832.       log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
  1833.                "duplicate client name: '%s'. Ignoring.", tok->args[0]);
  1834.       goto err;
  1835.     }
  1836.     parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
  1837.     parsed_entry->client_name = tor_strdup(tok->args[0]);
  1838.     strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
  1839.     /* Parse client key. */
  1840.     tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
  1841.     if (tok) {
  1842.       parsed_entry->client_key = tok->key;
  1843.       tok->key = NULL; /* Prevent free */
  1844.     }
  1845.     /* Parse descriptor cookie. */
  1846.     tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
  1847.     tor_assert(tok->n_args == 1);
  1848.     if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
  1849.       log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
  1850.                escaped(tok->args[0]));
  1851.       goto err;
  1852.     }
  1853.     /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
  1854.      * because a base64 encoding of length 24 does not fit into 16 bytes in all
  1855.      * cases. */
  1856.     if ((base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
  1857.                        tok->args[0], REND_DESC_COOKIE_LEN_BASE64+2+1)
  1858.            != REND_DESC_COOKIE_LEN)) {
  1859.       log_warn(LD_REND, "Descriptor cookie contains illegal characters: "
  1860.                         "%s", descriptor_cookie_base64);
  1861.       goto err;
  1862.     }
  1863.     memcpy(parsed_entry->descriptor_cookie, descriptor_cookie_tmp,
  1864.            REND_DESC_COOKIE_LEN);
  1865.   }
  1866.   result = strmap_size(parsed_clients);
  1867.   goto done;
  1868.  err:
  1869.   result = -1;
  1870.  done:
  1871.   /* Free tokens and clear token list. */
  1872.   SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
  1873.   smartlist_free(tokens);
  1874.   if (area)
  1875.     memarea_drop_all(area);
  1876.   return result;
  1877. }