|  | @@ -47,8 +47,16 @@ DECLARE_TYPED_DIGESTMAP_FNS(eimap_, digest_ei_map_t, extrainfo_t)
 | 
	
		
			
				|  |  |  /** Global list of a trusted_dir_server_t object for each trusted directory
 | 
	
		
			
				|  |  |   * server. */
 | 
	
		
			
				|  |  |  static smartlist_t *trusted_dir_servers = NULL;
 | 
	
		
			
				|  |  | -/** True iff the key certificate in at least one member of
 | 
	
		
			
				|  |  | - * <b>trusted_dir_server_t</b> has changed since we last flushed the
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** DOCDOC */
 | 
	
		
			
				|  |  | +typedef struct cert_list_t {
 | 
	
		
			
				|  |  | +  download_status_t dl_status;
 | 
	
		
			
				|  |  | +  smartlist_t *certs;
 | 
	
		
			
				|  |  | +} cert_list_t;
 | 
	
		
			
				|  |  | +/** Map from v3 identity key digest to cert_list_t. */
 | 
	
		
			
				|  |  | +static digestmap_t *trusted_dir_certs = NULL;
 | 
	
		
			
				|  |  | +/** True iff any key certificate in at least one member of
 | 
	
		
			
				|  |  | + * <b>trusted_dir_certs</b> has changed since we last flushed the
 | 
	
		
			
				|  |  |   * certificates to disk. */
 | 
	
		
			
				|  |  |  static int trusted_dir_servers_certs_changed = 0;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -80,6 +88,22 @@ get_n_authorities(authority_type_t type)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #define get_n_v2_authorities() get_n_authorities(V2_AUTHORITY)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/** DOCDOC */
 | 
	
		
			
				|  |  | +static cert_list_t *
 | 
	
		
			
				|  |  | +get_cert_list(const char *id_digest)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  cert_list_t *cl;
 | 
	
		
			
				|  |  | +  if (!trusted_dir_certs)
 | 
	
		
			
				|  |  | +    trusted_dir_certs = digestmap_new();
 | 
	
		
			
				|  |  | +  cl = digestmap_get(trusted_dir_certs, id_digest);
 | 
	
		
			
				|  |  | +  if (!cl) {
 | 
	
		
			
				|  |  | +    cl = tor_malloc_zero(sizeof(cert_list_t));
 | 
	
		
			
				|  |  | +    cl->certs = smartlist_create();
 | 
	
		
			
				|  |  | +    digestmap_set(trusted_dir_certs, id_digest, cl);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return cl;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /** Reload the cached v3 key certificates from the cached-certs file in
 | 
	
		
			
				|  |  |   * the data directory. Return 0 on success, -1 on failure. */
 | 
	
		
			
				|  |  |  int
 | 
	
	
		
			
				|  | @@ -108,6 +132,7 @@ int
 | 
	
		
			
				|  |  |  trusted_dirs_load_certs_from_string(const char *contents, int from_store)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    trusted_dir_server_t *ds;
 | 
	
		
			
				|  |  | +  cert_list_t *cl;
 | 
	
		
			
				|  |  |    const char *s, *eos;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    for (s = contents; *s; s = eos) {
 | 
	
	
		
			
				|  | @@ -117,17 +142,20 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store)
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      ds = trusteddirserver_get_by_v3_auth_digest(
 | 
	
		
			
				|  |  |                                         cert->cache_info.identity_digest);
 | 
	
		
			
				|  |  | -    if (!ds) {
 | 
	
		
			
				|  |  | -      log_info(LD_DIR, "Found %s certificate whose key didn't match "
 | 
	
		
			
				|  |  | -               "any v3 authority we recognized; skipping.",
 | 
	
		
			
				|  |  | -               from_store ? "cached" : "downloaded");
 | 
	
		
			
				|  |  | -      authority_cert_free(cert);
 | 
	
		
			
				|  |  | -      continue;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#if 0
 | 
	
		
			
				|  |  | +    if (drop_unknown && !ds) {
 | 
	
		
			
				|  |  | +        log_info(LD_DIR, "Found %s certificate whose key didn't match "
 | 
	
		
			
				|  |  | +                 "any v3 authority we recognized; skipping.",
 | 
	
		
			
				|  |  | +                 from_store ? "cached" : "downloaded");
 | 
	
		
			
				|  |  | +        authority_cert_free(cert);
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    if (!ds->v3_certs)
 | 
	
		
			
				|  |  | -      ds->v3_certs = smartlist_create();
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +    cl = get_cert_list(cert->cache_info.identity_digest);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, c,
 | 
	
		
			
				|  |  | +    SMARTLIST_FOREACH(cl->certs, authority_cert_t *, c,
 | 
	
		
			
				|  |  |        {
 | 
	
		
			
				|  |  |          if (!memcmp(c->cache_info.signed_descriptor_digest,
 | 
	
		
			
				|  |  |                      cert->cache_info.signed_descriptor_digest,
 | 
	
	
		
			
				|  | @@ -145,12 +173,19 @@ trusted_dirs_load_certs_from_string(const char *contents, int from_store)
 | 
	
		
			
				|  |  |      if (found)
 | 
	
		
			
				|  |  |        continue;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    log_info(LD_DIR, "Adding %s certificate for directory authority %s with "
 | 
	
		
			
				|  |  | -             "signing key %s", from_store ? "cached" : "downloaded",
 | 
	
		
			
				|  |  | -             ds->nickname, hex_str(cert->signing_key_digest,DIGEST_LEN));
 | 
	
		
			
				|  |  | +    if (ds) {
 | 
	
		
			
				|  |  | +      log_info(LD_DIR, "Adding %s certificate for directory authority %s with "
 | 
	
		
			
				|  |  | +               "signing key %s", from_store ? "cached" : "downloaded",
 | 
	
		
			
				|  |  | +               ds->nickname, hex_str(cert->signing_key_digest,DIGEST_LEN));
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      log_info(LD_DIR, "Adding %s certificate for unrecognized directory "
 | 
	
		
			
				|  |  | +               "authority with signing key %s",
 | 
	
		
			
				|  |  | +               from_store ? "cached" : "downloaded",
 | 
	
		
			
				|  |  | +               hex_str(cert->signing_key_digest,DIGEST_LEN));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    smartlist_add(ds->v3_certs, cert);
 | 
	
		
			
				|  |  | -    if (cert->cache_info.published_on > ds->addr_current_at) {
 | 
	
		
			
				|  |  | +    smartlist_add(cl->certs, cert);
 | 
	
		
			
				|  |  | +    if (ds && cert->cache_info.published_on > ds->addr_current_at) {
 | 
	
		
			
				|  |  |        /* Check to see whether we should update our view of the authority's
 | 
	
		
			
				|  |  |         * address. */
 | 
	
		
			
				|  |  |        if (cert->addr && cert->dir_port &&
 | 
	
	
		
			
				|  | @@ -185,23 +220,20 @@ trusted_dirs_flush_certs_to_disk(void)
 | 
	
		
			
				|  |  |    char *filename;
 | 
	
		
			
				|  |  |    smartlist_t *chunks;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (!trusted_dir_servers_certs_changed)
 | 
	
		
			
				|  |  | +  if (!trusted_dir_servers_certs_changed || !trusted_dir_certs)
 | 
	
		
			
				|  |  |      return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    chunks = smartlist_create();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
 | 
	
		
			
				|  |  | -  {
 | 
	
		
			
				|  |  | -      if (ds->v3_certs) {
 | 
	
		
			
				|  |  | -        SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  | +  DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
 | 
	
		
			
				|  |  | +    SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  |            {
 | 
	
		
			
				|  |  |              sized_chunk_t *c = tor_malloc(sizeof(sized_chunk_t));
 | 
	
		
			
				|  |  |              c->bytes = cert->cache_info.signed_descriptor_body;
 | 
	
		
			
				|  |  |              c->len = cert->cache_info.signed_descriptor_len;
 | 
	
		
			
				|  |  |              smartlist_add(chunks, c);
 | 
	
		
			
				|  |  |            });
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | +  } DIGESTMAP_FOREACH_END
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    filename = get_datadir_fname("cached-certs");
 | 
	
		
			
				|  |  |    if (write_chunks_to_file(filename, chunks, 0)) {
 | 
	
		
			
				|  |  |      log_warn(LD_FS, "Error writing certificates to disk.");
 | 
	
	
		
			
				|  | @@ -221,23 +253,23 @@ static void
 | 
	
		
			
				|  |  |  trusted_dirs_remove_old_certs(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  #define OLD_CERT_LIFETIME (48*60*60)
 | 
	
		
			
				|  |  | -  SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
 | 
	
		
			
				|  |  | -    {
 | 
	
		
			
				|  |  | -      authority_cert_t *newest = NULL;
 | 
	
		
			
				|  |  | -      if (!ds->v3_certs)
 | 
	
		
			
				|  |  | -        continue;
 | 
	
		
			
				|  |  | -      SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  | +  if (!trusted_dir_certs)
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
 | 
	
		
			
				|  |  | +    authority_cert_t *newest = NULL;
 | 
	
		
			
				|  |  | +    SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  |            if (!newest || (cert->cache_info.published_on >
 | 
	
		
			
				|  |  |                            newest->cache_info.published_on))
 | 
	
		
			
				|  |  |              newest = cert);
 | 
	
		
			
				|  |  | -      SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  | +    SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  |            if (newest && (newest->cache_info.published_on >
 | 
	
		
			
				|  |  |                           cert->cache_info.published_on + OLD_CERT_LIFETIME)) {
 | 
	
		
			
				|  |  | -            SMARTLIST_DEL_CURRENT(ds->v3_certs, cert);
 | 
	
		
			
				|  |  | +            SMARTLIST_DEL_CURRENT(cl->certs, cert);
 | 
	
		
			
				|  |  |              authority_cert_free(cert);
 | 
	
		
			
				|  |  |              trusted_dir_servers_certs_changed = 1;
 | 
	
		
			
				|  |  |            });
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | +  } DIGESTMAP_FOREACH_END
 | 
	
		
			
				|  |  |  #undef OLD_CERT_LIFETIME
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    trusted_dirs_flush_certs_to_disk();
 | 
	
	
		
			
				|  | @@ -249,11 +281,11 @@ trusted_dirs_remove_old_certs(void)
 | 
	
		
			
				|  |  |  authority_cert_t *
 | 
	
		
			
				|  |  |  authority_cert_get_newest_by_id(const char *id_digest)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  trusted_dir_server_t *ds = trusteddirserver_get_by_v3_auth_digest(id_digest);
 | 
	
		
			
				|  |  | +  cert_list_t *cl;
 | 
	
		
			
				|  |  |    authority_cert_t *best = NULL;
 | 
	
		
			
				|  |  | -  if (!ds || !ds->v3_certs)
 | 
	
		
			
				|  |  | +  if (!trusted_dir_certs || !(cl = digestmap_get(trusted_dir_certs, id_digest)))
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  | -  SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  | +  SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  |    {
 | 
	
		
			
				|  |  |      if (!best || cert->cache_info.published_on > best->cache_info.published_on)
 | 
	
		
			
				|  |  |        best = cert;
 | 
	
	
		
			
				|  | @@ -267,18 +299,16 @@ authority_cert_get_newest_by_id(const char *id_digest)
 | 
	
		
			
				|  |  |  authority_cert_t *
 | 
	
		
			
				|  |  |  authority_cert_get_by_sk_digest(const char *sk_digest)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  if (!trusted_dir_servers)
 | 
	
		
			
				|  |  | +  if (!trusted_dir_certs)
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  | -  SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
 | 
	
		
			
				|  |  | -  {
 | 
	
		
			
				|  |  | -    if (!ds->v3_certs)
 | 
	
		
			
				|  |  | -      continue;
 | 
	
		
			
				|  |  | -    SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
 | 
	
		
			
				|  |  | +    SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN))
 | 
	
		
			
				|  |  |          return cert;
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | +  } DIGESTMAP_FOREACH_END
 | 
	
		
			
				|  |  |    return NULL;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -289,17 +319,40 @@ authority_cert_t *
 | 
	
		
			
				|  |  |  authority_cert_get_by_digests(const char *id_digest,
 | 
	
		
			
				|  |  |                                const char *sk_digest)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  trusted_dir_server_t *ds = trusteddirserver_get_by_v3_auth_digest(id_digest);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (!ds || !ds->v3_certs)
 | 
	
		
			
				|  |  | +  cert_list_t *cl;
 | 
	
		
			
				|  |  | +  if (!trusted_dir_certs || !(cl = digestmap_get(trusted_dir_certs, id_digest)))
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  | -  SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  | +  SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  |      if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN))
 | 
	
		
			
				|  |  |        return cert; );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return NULL;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/** DOCDOC */
 | 
	
		
			
				|  |  | +void
 | 
	
		
			
				|  |  | +authority_cert_get_all(smartlist_t *certs_out)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  if (!trusted_dir_certs)
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  DIGESTMAP_FOREACH(trusted_dir_certs, key, cert_list_t *, cl) {
 | 
	
		
			
				|  |  | +    SMARTLIST_FOREACH(cl->certs, authority_cert_t *, c,
 | 
	
		
			
				|  |  | +                      smartlist_add(certs_out, c));
 | 
	
		
			
				|  |  | +  } DIGESTMAP_FOREACH_END
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** DOCDOC */
 | 
	
		
			
				|  |  | +void
 | 
	
		
			
				|  |  | +authority_cert_dl_failed(const char *id_digest, int status)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  cert_list_t *cl;
 | 
	
		
			
				|  |  | +  if (!trusted_dir_certs || !(cl = digestmap_get(trusted_dir_certs, id_digest)))
 | 
	
		
			
				|  |  | +    return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  download_status_failed(&cl->dl_status, status);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /** How many times will we try to fetch a certificate before giving up? */
 | 
	
		
			
				|  |  |  #define MAX_CERT_DL_FAILURES 8
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -315,6 +368,8 @@ authority_certs_fetch_missing(networkstatus_vote_t *status, time_t now)
 | 
	
		
			
				|  |  |    digestmap_t *pending;
 | 
	
		
			
				|  |  |    smartlist_t *missing_digests;
 | 
	
		
			
				|  |  |    char *resource = NULL;
 | 
	
		
			
				|  |  | +  cert_list_t *cl;
 | 
	
		
			
				|  |  | +  const int cache = directory_caches_dir_info(get_options());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (should_delay_dir_fetches(get_options()))
 | 
	
		
			
				|  |  |      return;
 | 
	
	
		
			
				|  | @@ -326,24 +381,22 @@ authority_certs_fetch_missing(networkstatus_vote_t *status, time_t now)
 | 
	
		
			
				|  |  |    if (status) {
 | 
	
		
			
				|  |  |      SMARTLIST_FOREACH(status->voters, networkstatus_voter_info_t *, voter,
 | 
	
		
			
				|  |  |        {
 | 
	
		
			
				|  |  | -        trusted_dir_server_t *ds
 | 
	
		
			
				|  |  | -          = trusteddirserver_get_by_v3_auth_digest(voter->identity_digest);
 | 
	
		
			
				|  |  | -        if (!ds) /* XXXX020 This is wrong!!  If we're a cache, we should
 | 
	
		
			
				|  |  | -                  * download unrecognized signing keys so we can serve
 | 
	
		
			
				|  |  | -                  * them. */
 | 
	
		
			
				|  |  | -          continue;
 | 
	
		
			
				|  |  |          if (tor_digest_is_zero(voter->signing_key_digest))
 | 
	
		
			
				|  |  |            continue; /* This authority never signed this consensus, so don't
 | 
	
		
			
				|  |  |                       * go looking for a cert with key digest 0000000000. */
 | 
	
		
			
				|  |  | +        if (!cache &&
 | 
	
		
			
				|  |  | +            !trusteddirserver_get_by_v3_auth_digest(voter->identity_digest))
 | 
	
		
			
				|  |  | +          continue; /* We are not a cache, and we don't know this authority.*/
 | 
	
		
			
				|  |  | +        cl = get_cert_list(voter->identity_digest);
 | 
	
		
			
				|  |  |          if (authority_cert_get_by_digests(voter->identity_digest,
 | 
	
		
			
				|  |  |                                            voter->signing_key_digest)) {
 | 
	
		
			
				|  |  | -          download_status_reset(&ds->cert_dl_status);
 | 
	
		
			
				|  |  | +          download_status_reset(&cl->dl_status);
 | 
	
		
			
				|  |  |            continue;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        if (download_status_is_ready(&ds->cert_dl_status, now,
 | 
	
		
			
				|  |  | +        if (download_status_is_ready(&cl->dl_status, now,
 | 
	
		
			
				|  |  |                                       MAX_CERT_DL_FAILURES)) {
 | 
	
		
			
				|  |  | -          log_notice(LD_DIR, "We're missing a certificate from authority %s "
 | 
	
		
			
				|  |  | -                     "with signing key %s: launching request.", ds->nickname,
 | 
	
		
			
				|  |  | +          log_notice(LD_DIR, "We're missing a certificate from authority "
 | 
	
		
			
				|  |  | +                     "with signing key %s: launching request.",
 | 
	
		
			
				|  |  |                       hex_str(voter->signing_key_digest, DIGEST_LEN));
 | 
	
		
			
				|  |  |            smartlist_add(missing_digests, voter->identity_digest);
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -356,19 +409,18 @@ authority_certs_fetch_missing(networkstatus_vote_t *status, time_t now)
 | 
	
		
			
				|  |  |          continue;
 | 
	
		
			
				|  |  |        if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest))
 | 
	
		
			
				|  |  |          continue;
 | 
	
		
			
				|  |  | -      if (!ds->v3_certs)
 | 
	
		
			
				|  |  | -        ds->v3_certs = smartlist_create();
 | 
	
		
			
				|  |  | -      SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  | +      cl = get_cert_list(ds->v3_identity_digest);
 | 
	
		
			
				|  |  | +      SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |            if (!ftime_definitely_after(now, cert->expires)) {
 | 
	
		
			
				|  |  |              /* It's not expired, and we weren't looking for something to
 | 
	
		
			
				|  |  |               * verify a consensus with.  Call it done. */
 | 
	
		
			
				|  |  | -            download_status_reset(&ds->cert_dl_status);
 | 
	
		
			
				|  |  | +            download_status_reset(&cl->dl_status);
 | 
	
		
			
				|  |  |              found = 1;
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  | -      if (!found && download_status_is_ready(&ds->cert_dl_status, now,
 | 
	
		
			
				|  |  | +      if (!found && download_status_is_ready(&cl->dl_status, now,
 | 
	
		
			
				|  |  |                                               MAX_CERT_DL_FAILURES)) {
 | 
	
		
			
				|  |  |          log_notice(LD_DIR, "No current certificate known for authority %s; "
 | 
	
		
			
				|  |  |                     "launching request.", ds->nickname);
 | 
	
	
		
			
				|  | @@ -3403,11 +3455,6 @@ authority_cert_free(authority_cert_t *cert)
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  trusted_dir_server_free(trusted_dir_server_t *ds)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  if (ds->v3_certs) {
 | 
	
		
			
				|  |  | -    SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
 | 
	
		
			
				|  |  | -                      authority_cert_free(cert));
 | 
	
		
			
				|  |  | -    smartlist_free(ds->v3_certs);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  |    tor_free(ds->nickname);
 | 
	
		
			
				|  |  |    tor_free(ds->description);
 | 
	
		
			
				|  |  |    tor_free(ds->address);
 |