|  | @@ -2954,6 +2954,7 @@ routerinfo_free(routerinfo_t *router)
 | 
	
		
			
				|  |  |    if (router->identity_pkey)
 | 
	
		
			
				|  |  |      crypto_pk_free(router->identity_pkey);
 | 
	
		
			
				|  |  |    tor_cert_free(router->signing_key_cert);
 | 
	
		
			
				|  |  | +  tor_cert_free(router->cache_info.signing_key_cert);
 | 
	
		
			
				|  |  |    if (router->declared_family) {
 | 
	
		
			
				|  |  |      SMARTLIST_FOREACH(router->declared_family, char *, s, tor_free(s));
 | 
	
		
			
				|  |  |      smartlist_free(router->declared_family);
 | 
	
	
		
			
				|  | @@ -2973,6 +2974,7 @@ extrainfo_free(extrainfo_t *extrainfo)
 | 
	
		
			
				|  |  |    if (!extrainfo)
 | 
	
		
			
				|  |  |      return;
 | 
	
		
			
				|  |  |    tor_cert_free(extrainfo->signing_key_cert);
 | 
	
		
			
				|  |  | +  tor_cert_free(extrainfo->cache_info.signing_key_cert);
 | 
	
		
			
				|  |  |    tor_free(extrainfo->cache_info.signed_descriptor_body);
 | 
	
		
			
				|  |  |    tor_free(extrainfo->pending_sig);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -3182,7 +3184,7 @@ extrainfo_insert,(routerlist_t *rl, extrainfo_t *ei, int warn_if_incompatible))
 | 
	
		
			
				|  |  |                       "Mismatch in digest in extrainfo map.");
 | 
	
		
			
				|  |  |      goto done;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (routerinfo_incompatible_with_extrainfo(ri, ei, sd,
 | 
	
		
			
				|  |  | +  if (routerinfo_incompatible_with_extrainfo(ri->identity_pkey, ei, sd,
 | 
	
		
			
				|  |  |                                               &compatibility_error_msg)) {
 | 
	
		
			
				|  |  |      char d1[HEX_DIGEST_LEN+1], d2[HEX_DIGEST_LEN+1];
 | 
	
		
			
				|  |  |      r = (ri->cache_info.extrainfo_is_bogus) ?
 | 
	
	
		
			
				|  | @@ -5221,25 +5223,32 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2)
 | 
	
		
			
				|  |  |    return 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/** Check whether <b>ri</b> (a.k.a. sd) is a router compatible with the
 | 
	
		
			
				|  |  | - * extrainfo document
 | 
	
		
			
				|  |  | - * <b>ei</b>.  If no router is compatible with <b>ei</b>, <b>ei</b> should be
 | 
	
		
			
				|  |  | +/** Check whether <b>sd</b> describes a router descriptor compatible with the
 | 
	
		
			
				|  |  | + * extrainfo document <b>ei</b>.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * <b>identity_pkey</b> (which must also be provided) is RSA1024 identity key
 | 
	
		
			
				|  |  | + * for the router. We use it to check the signature of the extrainfo document,
 | 
	
		
			
				|  |  | + * if it has not already been checked.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * If no router is compatible with <b>ei</b>, <b>ei</b> should be
 | 
	
		
			
				|  |  |   * dropped.  Return 0 for "compatible", return 1 for "reject, and inform
 | 
	
		
			
				|  |  |   * whoever uploaded <b>ei</b>, and return -1 for "reject silently.".  If
 | 
	
		
			
				|  |  |   * <b>msg</b> is present, set *<b>msg</b> to a description of the
 | 
	
		
			
				|  |  |   * incompatibility (if any).
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Set the extrainfo_is_bogus field in <b>sd</b> if the digests matched
 | 
	
		
			
				|  |  | + * but the extrainfo was nonetheless incompatible.
 | 
	
		
			
				|  |  |   **/
 | 
	
		
			
				|  |  |  int
 | 
	
		
			
				|  |  | -routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
 | 
	
		
			
				|  |  | +routerinfo_incompatible_with_extrainfo(const crypto_pk_t *identity_pkey,
 | 
	
		
			
				|  |  |                                         extrainfo_t *ei,
 | 
	
		
			
				|  |  |                                         signed_descriptor_t *sd,
 | 
	
		
			
				|  |  |                                         const char **msg)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    int digest_matches, digest256_matches, r=1;
 | 
	
		
			
				|  |  | -  tor_assert(ri);
 | 
	
		
			
				|  |  | +  tor_assert(identity_pkey);
 | 
	
		
			
				|  |  | +  tor_assert(sd);
 | 
	
		
			
				|  |  |    tor_assert(ei);
 | 
	
		
			
				|  |  | -  if (!sd)
 | 
	
		
			
				|  |  | -    sd = (signed_descriptor_t*)&ri->cache_info;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (ei->bad_sig) {
 | 
	
		
			
				|  |  |      if (msg) *msg = "Extrainfo signature was bad, or signed with wrong key.";
 | 
	
	
		
			
				|  | @@ -5251,27 +5260,27 @@ routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
 | 
	
		
			
				|  |  |    /* Set digest256_matches to 1 if the digest is correct, or if no
 | 
	
		
			
				|  |  |     * digest256 was in the ri. */
 | 
	
		
			
				|  |  |    digest256_matches = tor_memeq(ei->digest256,
 | 
	
		
			
				|  |  | -                                ri->extra_info_digest256, DIGEST256_LEN);
 | 
	
		
			
				|  |  | +                                sd->extra_info_digest256, DIGEST256_LEN);
 | 
	
		
			
				|  |  |    digest256_matches |=
 | 
	
		
			
				|  |  | -    tor_mem_is_zero(ri->extra_info_digest256, DIGEST256_LEN);
 | 
	
		
			
				|  |  | +    tor_mem_is_zero(sd->extra_info_digest256, DIGEST256_LEN);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* The identity must match exactly to have been generated at the same time
 | 
	
		
			
				|  |  |     * by the same router. */
 | 
	
		
			
				|  |  | -  if (tor_memneq(ri->cache_info.identity_digest,
 | 
	
		
			
				|  |  | +  if (tor_memneq(sd->identity_digest,
 | 
	
		
			
				|  |  |                   ei->cache_info.identity_digest,
 | 
	
		
			
				|  |  |                   DIGEST_LEN)) {
 | 
	
		
			
				|  |  |      if (msg) *msg = "Extrainfo nickname or identity did not match routerinfo";
 | 
	
		
			
				|  |  |      goto err; /* different servers */
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (! tor_cert_opt_eq(ri->signing_key_cert, ei->signing_key_cert)) {
 | 
	
		
			
				|  |  | +  if (! tor_cert_opt_eq(sd->signing_key_cert, ei->signing_key_cert)) {
 | 
	
		
			
				|  |  |      if (msg) *msg = "Extrainfo signing key cert didn't match routerinfo";
 | 
	
		
			
				|  |  |      goto err; /* different servers */
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (ei->pending_sig) {
 | 
	
		
			
				|  |  |      char signed_digest[128];
 | 
	
		
			
				|  |  | -    if (crypto_pk_public_checksig(ri->identity_pkey,
 | 
	
		
			
				|  |  | +    if (crypto_pk_public_checksig(identity_pkey,
 | 
	
		
			
				|  |  |                         signed_digest, sizeof(signed_digest),
 | 
	
		
			
				|  |  |                         ei->pending_sig, ei->pending_sig_len) != DIGEST_LEN ||
 | 
	
		
			
				|  |  |          tor_memneq(signed_digest, ei->cache_info.signed_descriptor_digest,
 | 
	
	
		
			
				|  | @@ -5282,7 +5291,7 @@ routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
 | 
	
		
			
				|  |  |        goto err; /* Bad signature, or no match. */
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    ei->cache_info.send_unencrypted = ri->cache_info.send_unencrypted;
 | 
	
		
			
				|  |  | +    ei->cache_info.send_unencrypted = sd->send_unencrypted;
 | 
	
		
			
				|  |  |      tor_free(ei->pending_sig);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 |