From ceac39aa8aa498a39b2e83f87a776bd7c225846b Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 9 May 2007 04:15:46 +0000 Subject: [PATCH] r12697@catbus: nickm | 2007-05-09 00:15:40 -0400 Change authority_type_t to a set of flags; use it more consistently. svn:r10144 --- src/or/circuitbuild.c | 3 +- src/or/config.c | 78 +++++++++++++++++++++++-------------------- src/or/directory.c | 44 +++++++++++++----------- src/or/dirserv.c | 2 +- src/or/or.h | 32 ++++++++---------- src/or/router.c | 11 +++--- src/or/routerlist.c | 38 +++++++++------------ 7 files changed, 105 insertions(+), 103 deletions(-) diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index bdce36caa6..24a8f0c729 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1740,7 +1740,8 @@ extend_info_from_router(routerinfo_t *r) * It's a general purpose router unless it's on our bridges list. */ static uint8_t -get_router_purpose_from_digest(char *digest) { +get_router_purpose_from_digest(char *digest) +{ (void)digest; return ROUTER_PURPOSE_GENERAL; /* XXX020 */ } diff --git a/src/or/config.c b/src/or/config.c index 9fedfa600b..a0385bb324 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -211,7 +211,7 @@ static config_var_t _option_vars[] = { VAR("PidFile", STRING, PidFile, NULL), VAR("PreferTunneledDirConns", BOOL, PreferTunneledDirConns, "0"), VAR("ProtocolWarnings", BOOL, ProtocolWarnings, "0"), - VAR("PublishServerDescriptor",STRING,PublishServerDescriptor,"v2"), + VAR("PublishServerDescriptor", CSV, PublishServerDescriptor,"v1,v2"), VAR("PublishHidServDescriptors",BOOL,PublishHidServDescriptors, "1"), VAR("ReachableAddresses", LINELIST, ReachableAddresses, NULL), VAR("ReachableDirAddresses",LINELIST,ReachableDirAddresses,NULL), @@ -1929,7 +1929,7 @@ resolve_my_address(int warn_severity, or_options_t *options, tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf)); if (is_internal_IP(ntohl(in.s_addr), 0) && - options->_PublishServerDescriptor != NO_AUTHORITY) { + options->_PublishServerDescriptor) { /* make sure we're ok with publishing an internal IP */ if (!options->DirServers) { /* if they are using the default dirservers, disallow internal IPs @@ -2308,27 +2308,33 @@ ensure_bandwidth_cap(uint64_t value, const char *desc, char **msg) return 0; } -/** Parse an authority type from string and write it to *auth. - * If compatible is non-zero, treat "1" as "v2" and treat "0" as "". - * Return 0 on success or -1 if not a recognized authority type. +/** Parse an authority type from list and write it to *auth. If + * compatible is non-zero, treat "1" as "v1,v2" and treat "0" as "". + * Return 0 on success or -(idx of first bad member) if not a recognized + * authority type. */ static int -parse_authority_type_from_string(const char *string, authority_type_t *auth, - int compatible) +parse_authority_type_from_list(smartlist_t *list, authority_type_t *auth, + int compatible) { tor_assert(auth); - if (!strcasecmp(string, "v1")) - *auth = V1_AUTHORITY; - else if (!strcasecmp(string, "v2") || (compatible && !strcmp(string, "1"))) - *auth = V2_AUTHORITY; - else if (!strcasecmp(string, "bridge")) - *auth = BRIDGE_AUTHORITY; - else if (!strcasecmp(string, "hidserv")) - *auth = HIDSERV_AUTHORITY; - else if (!strcasecmp(string, "") || (compatible && !strcmp(string, "0"))) - *auth = NO_AUTHORITY; - else - return -1; + *auth = 0; + SMARTLIST_FOREACH(list, const char *, string, { + if (!strcasecmp(string, "v1")) + *auth |= V1_AUTHORITY; + else if (compatible && !strcmp(string, "1")) + *auth |= V1_AUTHORITY | V2_AUTHORITY; + else if (!strcasecmp(string, "v2")) + *auth |= V2_AUTHORITY; + else if (!strcasecmp(string, "bridge")) + *auth |= BRIDGE_AUTHORITY; + else if (!strcasecmp(string, "hidserv")) + *auth |= HIDSERV_AUTHORITY; + else if (!strcasecmp(string, "") || (compatible && !strcmp(string, "0"))) + /* no authority */; + else + return - string_sl_idx; + }); return 0; } @@ -2473,8 +2479,9 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->NoPublish) { log(LOG_WARN, LD_CONFIG, "NoPublish is obsolete. Use PublishServerDescriptor instead."); - tor_free(options->PublishServerDescriptor); - options->PublishServerDescriptor = tor_strdup(""); + SMARTLIST_FOREACH(options->PublishServerDescriptor, char *, s, + tor_free(s)); + smartlist_clear(options->PublishServerDescriptor); } if (authdir_mode(options)) { @@ -2681,11 +2688,11 @@ options_validate(or_options_t *old_options, or_options_t *options, }); } - if (parse_authority_type_from_string(options->PublishServerDescriptor, - &options->_PublishServerDescriptor, 1) < 0) { + if ((i = parse_authority_type_from_list(options->PublishServerDescriptor, + &options->_PublishServerDescriptor, 1) < 0)) { r = tor_snprintf(buf, sizeof(buf), "Unrecognized value '%s' for PublishServerDescriptor", - options->PublishServerDescriptor); + (char*)smartlist_get(options->PublishServerDescriptor, -i)); *msg = tor_strdup(r >= 0 ? buf : "internal error"); return -1; } @@ -3564,9 +3571,8 @@ parse_dir_server_line(const char *line, int validate_only) char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL; uint16_t dir_port = 0, or_port = 0; char digest[DIGEST_LEN]; - int is_v1_authority = 0, is_hidserv_authority = 0, - is_not_hidserv_authority = 0, is_v2_authority = 1, - is_bridge_authority = 0; + authority_type_t type = V2_AUTHORITY; + int is_not_hidserv_authority = 0, is_not_v2_authority = 0; items = smartlist_create(); smartlist_split_string(items, line, NULL, @@ -3586,15 +3592,15 @@ parse_dir_server_line(const char *line, int validate_only) if (TOR_ISDIGIT(flag[0])) break; if (!strcasecmp(flag, "v1")) { - is_v1_authority = is_hidserv_authority = 1; + type |= (V1_AUTHORITY | HIDSERV_AUTHORITY); } else if (!strcasecmp(flag, "hs")) { - is_hidserv_authority = 1; + type |= HIDSERV_AUTHORITY; } else if (!strcasecmp(flag, "no-hs")) { is_not_hidserv_authority = 1; } else if (!strcasecmp(flag, "bridge")) { - is_bridge_authority = 1; + type |= BRIDGE_AUTHORITY; } else if (!strcasecmp(flag, "no-v2")) { - is_v2_authority = 0; + is_not_v2_authority = 1; } else if (!strcasecmpstart(flag, "orport=")) { int ok; char *portstring = flag + strlen("orport="); @@ -3609,9 +3615,10 @@ parse_dir_server_line(const char *line, int validate_only) tor_free(flag); smartlist_del_keeporder(items, 0); } - if (is_not_hidserv_authority) - is_hidserv_authority = 0; + type &= ~HIDSERV_AUTHORITY; + if (is_not_v2_authority) + type &= ~V2_AUTHORITY; if (smartlist_len(items) < 2) { log_warn(LD_CONFIG, "Too few arguments to DirServer line."); @@ -3642,10 +3649,7 @@ parse_dir_server_line(const char *line, int validate_only) log_debug(LD_DIR, "Trusted dirserver at %s:%d (%s)", address, (int)dir_port, (char*)smartlist_get(items,0)); - add_trusted_dir_server(nickname, address, dir_port, or_port, digest, - is_v1_authority, is_v2_authority, - is_bridge_authority, is_hidserv_authority); - + add_trusted_dir_server(nickname, address, dir_port, or_port, digest, type); } r = 0; diff --git a/src/or/directory.c b/src/or/directory.c index 24b3b1c66a..f782feca2e 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -83,17 +83,27 @@ purpose_is_private(uint8_t purpose) return 1; } -/** Return a static string describing auth. */ -const char * +/** Return a newly allocated string describing auth. */ +char * authority_type_to_string(authority_type_t auth) { - switch(auth) { - case V1_AUTHORITY: return "V1"; - case V2_AUTHORITY: return "V2"; - case BRIDGE_AUTHORITY: return "Bridge"; - case HIDSERV_AUTHORITY: return "Hidden service"; - case NO_AUTHORITY: default: return "[Unexpected authority type]"; + char *result; + smartlist_t *lst = smartlist_create(); + if (auth & V1_AUTHORITY) + smartlist_add(lst, (void*)"V1"); + if (auth & V2_AUTHORITY) + smartlist_add(lst, (void*)"V2"); + if (auth & BRIDGE_AUTHORITY) + smartlist_add(lst, (void*)"Bridge"); + if (auth & HIDSERV_AUTHORITY) + smartlist_add(lst, (void*)"Hidden service"); + if (smartlist_len(lst)) { + result = smartlist_join_strings(lst, ", ", 0, NULL); + } else { + result = tor_strdup("[Not an authority]"); } + smartlist_free(lst); + return result; } /** Start a connection to every suitable directory server, using @@ -124,16 +134,11 @@ directory_post_to_dirservers(uint8_t purpose, authority_type_t type, local_routerstatus_t *lrs = router_get_combined_status_by_digest( ds->digest); int new_enough; - size_t upload_len = payload_len; - if (type == HIDSERV_AUTHORITY && !ds->is_hidserv_authority) - continue; - if (type == BRIDGE_AUTHORITY && !ds->is_bridge_authority) - continue; - if (type == V1_AUTHORITY && !ds->is_v1_authority) - continue; - if (type == V2_AUTHORITY && !ds->is_v2_authority) + + if ((type & ds->type) == 0) continue; + found = 1; /* at least one authority of this type was listed */ if (purpose == DIR_PURPOSE_UPLOAD_DIR) ds->has_accepted_serverdesc = 0; @@ -152,9 +157,10 @@ directory_post_to_dirservers(uint8_t purpose, authority_type_t type, NULL, payload, upload_len); }); if (!found) { + char *s = authority_type_to_string(type); log_warn(LD_DIR, "Publishing server descriptor to directory authorities " - "of type '%s', but no authorities of that type listed!", - authority_type_to_string(type)); + "of type '%s', but no authorities of that type listed!", s); + tor_free(s); } } @@ -1234,7 +1240,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) ds->has_accepted_serverdesc = 1; servers = router_get_trusted_dir_servers(); SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, { - if ((d->is_v1_authority || d->is_v2_authority) && + if ((d->type & (V1_AUTHORITY|V2_AUTHORITY)) && !d->has_accepted_serverdesc) { all_done = 0; break; diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 6addaba849..2ca3be2666 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1840,7 +1840,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result, } else { SMARTLIST_FOREACH(router_get_trusted_dir_servers(), trusted_dir_server_t *, ds, - if (ds->is_v2_authority) + if (ds->type & V2_AUTHORITY) smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN))); } smartlist_sort_digests(result); diff --git a/src/or/or.h b/src/or/or.h index a881f89f97..f07865d82d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1311,9 +1311,13 @@ typedef struct authority_cert_t { time_t expires; } authority_cert_t; +/** DOCDOC */ typedef enum { - NO_AUTHORITY=0, V1_AUTHORITY, V2_AUTHORITY, - HIDSERV_AUTHORITY, BRIDGE_AUTHORITY + NO_AUTHORITY = 0, + V1_AUTHORITY = 1 << 0, + V2_AUTHORITY = 1 << 1, + HIDSERV_AUTHORITY = 1 << 2, + BRIDGE_AUTHORITY = 1 << 3, } authority_type_t; #define CRYPT_PATH_MAGIC 0x70127012u @@ -1757,7 +1761,7 @@ typedef struct { int NoPublish; /** To what authority types do we publish our descriptor? Choices are * "v1", "v2", "bridge", or "". */ - char *PublishServerDescriptor; + smartlist_t *PublishServerDescriptor; /** An authority type, derived from PublishServerDescriptor. */ authority_type_t _PublishServerDescriptor; /** Boolean: do we publish hidden service descriptors to the HS auths? */ @@ -2519,7 +2523,7 @@ int assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type, /********************************* directory.c ***************************/ -const char *authority_type_to_string(authority_type_t auth); +char *authority_type_to_string(authority_type_t auth); void directory_post_to_dirservers(uint8_t purpose, authority_type_t type, const char *payload, size_t payload_len, size_t extrainfo_len); @@ -3029,20 +3033,14 @@ typedef struct trusted_dir_server_t { uint16_t or_port; /**< OR port: Used for tunneling connections. */ char digest[DIGEST_LEN]; /**< Digest of identity key. */ unsigned int is_running:1; /**< True iff we think this server is running. */ - /** True iff this server is an authority for the older ("v1") directory - * protocol. */ - unsigned int is_v1_authority:1; - /** True iff this server is an authority for the newer ("v2") directory - * protocol. */ - unsigned int is_v2_authority:1; - /** True iff this server is an authority for bridge relays. */ - unsigned int is_bridge_authority:1; - /** True iff this server is an authority for hidden services. */ - unsigned int is_hidserv_authority:1; + /** True iff this server has accepted the most recent server descriptor * we tried to upload to it. */ unsigned int has_accepted_serverdesc:1; + /** DOCDOC */ + authority_type_t type; + int n_networkstatus_failures; /**< How many times have we asked for this * server's network-status unsuccessfully? */ local_routerstatus_t fake_status; /**< Used when we need to pass this trusted @@ -3137,9 +3135,7 @@ int router_exit_policy_rejects_all(routerinfo_t *router); void add_trusted_dir_server(const char *nickname, const char *address, uint16_t dir_port, uint16_t or_port, - const char *digest, int is_v1_authority, - int is_v2_authority, int is_bridge_authority, - int is_hidserv_authority); + const char *digest, authority_type_t type); void clear_trusted_dir_servers(void); int any_trusted_dir_is_v1_authority(void); networkstatus_t *networkstatus_get_by_digest(const char *digest); @@ -3237,7 +3233,5 @@ void authority_cert_free(authority_cert_t *cert); authority_cert_t *authority_cert_parse_from_string(const char *s, char **end_of_string); - - #endif diff --git a/src/or/router.c b/src/or/router.c index b6c4ca69cb..17470cc5f9 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -242,6 +242,7 @@ init_keys(void) char *cp; or_options_t *options = get_options(); or_state_t *state = get_or_state(); + authority_type_t type; if (!key_lock) key_lock = tor_mutex_new(); @@ -371,15 +372,17 @@ init_keys(void) } /* 6b. [authdirserver only] add own key to approved directories. */ crypto_pk_get_digest(get_identity_key(), digest); + type = ((options->V1AuthoritativeDir ? V1_AUTHORITY : 0) | + (options->V2AuthoritativeDir ? V2_AUTHORITY : 0) | + (options->BridgeAuthoritativeDir ? BRIDGE_AUTHORITY : 0) | + (options->HSAuthoritativeDir ? HIDSERV_AUTHORITY : 0)); + if (!router_digest_is_trusted_dir(digest)) { add_trusted_dir_server(options->Nickname, NULL, (uint16_t)options->DirPort, (uint16_t)options->ORPort, digest, - options->V1AuthoritativeDir, /* v1 authority */ - options->V2AuthoritativeDir, /* v2 authority */ - options->BridgeAuthoritativeDir, /* bridge auth */ - options->HSAuthoritativeDir /*hidserv authority*/); + type); } return 0; /* success */ } diff --git a/src/or/routerlist.c b/src/or/routerlist.c index af113dec9e..dfe6cd83eb 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -100,19 +100,22 @@ static int have_warned_about_old_version = 0; * listed by the authorities */ static int have_warned_about_new_version = 0; -/** Return the number of v2 directory authorities */ +/** Return the number of directory authorities whose type matches some bit set + * in type */ static INLINE int -get_n_v2_authorities(void) +get_n_authorities(authority_type_t type) { int n = 0; if (!trusted_dir_servers) return 0; SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, - if (ds->is_v2_authority) + if (ds->type & type) ++n); return n; } +#define get_n_v2_authorities() get_n_authorities(V2_AUTHORITY) + /** Repopulate our list of network_status_t objects from the list cached on * disk. Return 0 on success, -1 on failure. */ int @@ -709,11 +712,7 @@ router_pick_trusteddirserver_impl(authority_type_t type, int is_overloaded = d->fake_status.last_dir_503_at + DIR_503_TIMEOUT > now; if (!d->is_running) continue; - if (type == V1_AUTHORITY && !d->is_v1_authority) - continue; - if (type == V2_AUTHORITY && !d->is_v2_authority) - continue; - if (type == HIDSERV_AUTHORITY && !d->is_hidserv_authority) + if ((type & d->type) == 0) continue; if (requireother && me && router_digest_is_me(d->digest)) continue; @@ -2713,7 +2712,7 @@ router_set_networkstatus(const char *s, time_t arrived_at, base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN); if (!(trusted_dir = router_get_trusteddirserver_by_digest(ns->identity_digest)) || - !trusted_dir->is_v2_authority) { + !(trusted_dir->type & V2_AUTHORITY)) { log_info(LD_DIR, "Network status was signed, but not by an authoritative " "directory we recognize."); if (!get_options()->DirPort) { @@ -3066,7 +3065,7 @@ update_networkstatus_cache_downloads(time_t now) SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, { char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */ - if (!ds->is_v2_authority) + if (!(ds->type & V2_AUTHORITY)) continue; if (router_digest_is_me(ds->digest)) continue; @@ -3133,7 +3132,7 @@ update_networkstatus_client_downloads(time_t now) SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, { networkstatus_t *ns = networkstatus_get_by_digest(ds->digest); - if (!ds->is_v2_authority) + if (!(ds->type & V2_AUTHORITY)) continue; ++n_dirservers; if (ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES) @@ -3183,7 +3182,7 @@ update_networkstatus_client_downloads(time_t now) if (i >= n_dirservers) i = 0; ds = smartlist_get(trusted_dir_servers, i); - if (! ds->is_v2_authority) + if (!(ds->type & V2_AUTHORITY)) continue; if (n_failed < n_dirservers && ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES) { @@ -3263,9 +3262,7 @@ router_exit_policy_rejects_all(routerinfo_t *router) void add_trusted_dir_server(const char *nickname, const char *address, uint16_t dir_port, uint16_t or_port, - const char *digest, int is_v1_authority, - int is_v2_authority, int is_bridge_authority, - int is_hidserv_authority) + const char *digest, authority_type_t type) { trusted_dir_server_t *ent; uint32_t a; @@ -3299,10 +3296,7 @@ add_trusted_dir_server(const char *nickname, const char *address, ent->dir_port = dir_port; ent->or_port = or_port; ent->is_running = 1; - ent->is_v1_authority = is_v1_authority; - ent->is_v2_authority = is_v2_authority; - ent->is_bridge_authority = is_bridge_authority; - ent->is_hidserv_authority = is_hidserv_authority; + ent->type = type; memcpy(ent->digest, digest, DIGEST_LEN); dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0); @@ -3361,8 +3355,8 @@ int any_trusted_dir_is_v1_authority(void) { if (trusted_dir_servers) - SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ent, - if (ent->is_v1_authority) return 1); + return get_n_authorities(V1_AUTHORITY) > 0; + return 0; } @@ -4545,7 +4539,7 @@ have_tried_downloading_all_statuses(int n_failures) SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, { - if (!ds->is_v2_authority) + if (!(ds->type & V2_AUTHORITY)) continue; /* If we don't have the status, and we haven't failed to get the status, * we haven't tried to get the status. */