Loading src/or/config.c +14 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,7 @@ static config_var_t _option_vars[] = { V(Group, STRING, NULL), V(HardwareAccel, BOOL, "0"), V(HashedControlPassword, STRING, NULL), V(HidServDirectoryV2, BOOL, "0"), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNodes", LINELIST_S, RendConfigLines, NULL), Loading Loading @@ -286,8 +287,12 @@ static config_var_t _option_vars[] = { VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"), V(VirtualAddrNetwork, STRING, "127.192.0.0/10"), VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"), VAR("__ConsiderAllRoutersAsHidServDirectories", BOOL, __ConsiderAllRoutersAsHidServDirectories, "0"), VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"), VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"), VAR("__MinUptimeHidServDirectoryV2", INTERVAL, __MinUptimeHidServDirectoryV2, "24 hours"), { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; Loading Loading @@ -2688,6 +2693,9 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("HSAuthorityRecordStats is set but we're not running as " "a hidden service authority."); if (options->HidServDirectoryV2 && !options->DirPort) REJECT("Running as hidden service directory, but no DirPort set."); if (options->ConnLimit <= 0) { r = tor_snprintf(buf, sizeof(buf), "ConnLimit must be greater than 0, but was set to %d", Loading Loading @@ -2820,6 +2828,12 @@ options_validate(or_options_t *old_options, or_options_t *options, return -1; } if (options->__MinUptimeHidServDirectoryV2 < 0) { log_warn(LD_CONFIG, "__MinUptimeHidServDirectoryV2 option must be at " "least 0 seconds. Changing to 0."); options->__MinUptimeHidServDirectoryV2 = 0; } if (options->RendPostPeriod < MIN_REND_POST_PERIOD) { log(LOG_WARN,LD_CONFIG,"RendPostPeriod option must be at least %d seconds." " Clipping.", MIN_REND_POST_PERIOD); Loading src/or/directory.c +209 −9 Original line number Diff line number Diff line Loading @@ -157,6 +157,10 @@ dir_conn_purpose_to_string(int purpose) return "status vote fetch"; case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: return "consensus signature fetch"; case DIR_PURPOSE_FETCH_RENDDESC_V2: return "hidden-service v2 descriptor fetch"; case DIR_PURPOSE_UPLOAD_RENDDESC_V2: return "hidden-service v2 descriptor upload"; } log_warn(LD_BUG, "Called with unknown purpose %d", purpose); Loading Loading @@ -422,7 +426,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose, * upload or download a server or rendezvous * descriptor. <b>dir_purpose</b> determines what * kind of directory connection we're launching, and must be one of * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}. <b>router_purpose</b> * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b> * specifies the descriptor purposes we have in mind (currently only * used for FETCH_DIR). * Loading Loading @@ -867,12 +871,27 @@ directory_send_command(dir_connection_t *conn, url = tor_malloc(len); tor_snprintf(url, len, "/tor/rendezvous/%s", resource); break; case DIR_PURPOSE_FETCH_RENDDESC_V2: tor_assert(resource); tor_assert(!payload); tor_assert(strlen(resource) <= REND_DESC_ID_V2_BASE32); httpcommand = "GET"; len = strlen(resource) + 32; url = tor_malloc(len); tor_snprintf(url, len, "/tor/rendezvous2/%s", resource); break; case DIR_PURPOSE_UPLOAD_RENDDESC: tor_assert(!resource); tor_assert(payload); httpcommand = "POST"; url = tor_strdup("/tor/rendezvous/publish"); break; case DIR_PURPOSE_UPLOAD_RENDDESC_V2: tor_assert(!resource); tor_assert(payload); httpcommand = "POST"; url = tor_strdup("/tor/rendezvous2/publish"); break; default: tor_assert(0); return; Loading Loading @@ -1721,8 +1740,46 @@ connection_dir_client_reached_eof(dir_connection_t *conn) } } if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) { log_info(LD_REND,"Uploaded rendezvous descriptor (status %d (%s))", if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) { log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d " "(%s))", (int)body_len, status_code, escaped(reason)); switch (status_code) { case 200: if (rend_cache_store_v2_client(body, NULL) < 0) { log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed."); /* alice's ap_stream will notice when connection_mark_for_close * cleans it up */ } else { /* success. notify pending connections about this. */ log_info(LD_REND, "Successfully fetched rendezvous descriptor."); conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; rend_client_desc_here(conn->rend_query); } break; case 404: /* not there. pending connections will be notified when * connection_mark_for_close cleans it up. */ break; case 400: log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: " "http status 400 (%s). Dirserver didn't like our " "v2 rendezvous query?", escaped(reason)); break; default: log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: " "http status %d (%s) response unexpected while " "fetching v2 hidden service descriptor (server '%s:%d').", status_code, escaped(reason), conn->_base.address, conn->_base.port); break; } } if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC || conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) { log_info(LD_REND,"Uploaded rendezvous descriptor (status %d " "(%s))", status_code, escaped(reason)); switch (status_code) { case 200: Loading Loading @@ -2428,6 +2485,32 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, goto done; } if (options->HidServDirectoryV2 && !strcmpstart(url,"/tor/rendezvous2/")) { /* Handle v2 rendezvous descriptor fetch request. */ char *descp; const char *query = url + strlen("/tor/rendezvous2/"); if (strlen(query) == REND_DESC_ID_V2_BASE32) { log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'", query); switch (rend_cache_lookup_v2_dir(query, &descp)) { case 1: /* valid */ write_http_response_header(conn, strlen(descp), 0, 0); connection_write_to_buf(descp, strlen(descp), TO_CONN(conn)); break; case 0: /* well-formed but not present */ write_http_status_line(conn, 404, "Not found"); break; case -1: /* not well-formed */ write_http_status_line(conn, 400, "Bad request"); break; } } else { /* not well-formed */ write_http_status_line(conn, 400, "Bad request"); } goto done; } if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) { /* rendezvous descriptor fetch */ const char *descp; Loading Loading @@ -2546,6 +2629,27 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, conn->_base.state = DIR_CONN_STATE_SERVER_WRITING; if (parse_http_url(headers, &url) < 0) { write_http_status_line(conn, 400, "Bad request"); return 0; } log_debug(LD_DIRSERV,"rewritten url as '%s'.", url); /* Handle v2 rendezvous service publish request. */ if (options->HidServDirectoryV2 && !strcmpstart(url,"/tor/rendezvous2/publish")) { if (rend_cache_store_v2_dir(body) < 0) { log_warn(LD_REND, "Rejected rend descriptor (length %d) from %s.", (int)body_len, conn->_base.address); write_http_status_line(conn, 400, "Invalid service descriptor rejected"); log_info(LD_REND, "Handled v2 rendezvous descriptor post: rejected"); } else { write_http_status_line(conn, 200, "Service descriptor stored"); log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted"); } goto done; } if (!authdir_mode(options)) { /* we just provide cached directories; we don't want to * receive anything. */ Loading @@ -2554,12 +2658,6 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, return 0; } if (parse_http_url(headers, &url) < 0) { write_http_status_line(conn, 400, "Bad request"); return 0; } log_debug(LD_DIRSERV,"rewritten url as '%s'.", url); if (authdir_mode_handles_descs(options) && !strcmp(url,"/tor/")) { /* server descriptor post */ const char *msg = NULL; Loading Loading @@ -2948,3 +3046,105 @@ dir_split_resource_into_fingerprints(const char *resource, return 0; } /** Determine the responsible hidden service directories for * <b>desc_ids</b> and upload the appropriate descriptor from * <b>desc_strs</b> to them; each smartlist must contain * REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS entries; <b>service_id</b> and * <b>seconds_valid</b> are only passed for logging purposes.*/ /* XXXX020 enable tunneling when available!! */ void directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *desc_strs, const char *service_id, int seconds_valid, smartlist_t *hs_dirs_) { int i, j; smartlist_t *responsible_dirs; routerinfo_t *hs_dir; if (smartlist_len(desc_ids) != REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS || smartlist_len(desc_strs) != REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS) { log_warn(LD_REND, "Could not post descriptors to hidden service " "directories: Illegal number of descriptor " "IDs/strings"); return; } responsible_dirs = smartlist_create(); for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) { const char *desc_id = smartlist_get(desc_ids, i); const char *desc_str = smartlist_get(desc_strs, i); /* Determine responsible dirs. */ if (hid_serv_get_responsible_directories(responsible_dirs, desc_id, hs_dirs_) < 0) { log_warn(LD_REND, "Could not determine the responsible hidden service " "directories to post descriptors to."); smartlist_free(responsible_dirs); return; } for (j = 0; j < REND_NUMBER_OF_CONSECUTIVE_REPLICAS; j++) { char desc_id_base32[REND_DESC_ID_V2_BASE32 + 1]; hs_dir = smartlist_get(responsible_dirs, j); /* Send publish request. */ directory_initiate_command(hs_dir->address, hs_dir->addr, hs_dir->or_port, hs_dir->dir_port, 0, hs_dir->cache_info.identity_digest, DIR_PURPOSE_UPLOAD_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, 1, NULL, desc_str, strlen(desc_str), 0); base32_encode(desc_id_base32, REND_DESC_ID_V2_BASE32 + 1, desc_id, DIGEST_LEN); log_info(LD_REND, "Sending publish request for v2 descriptor for " "service '%s' with descriptor ID '%s' with validity " "of %d seconds to hidden service directory '%s' on " "port %d.", service_id, desc_id_base32, seconds_valid, hs_dir->nickname, hs_dir->dir_port); } smartlist_clear(responsible_dirs); } smartlist_free(responsible_dirs); } /** Determine the responsible hidden service directories for <b>desc_id</b> * and fetch the descriptor belonging to this ID from one of them; * <b>query</b> is only passed for pretty log statements. * XXXX020 enable tunneling when available!! */ void directory_get_from_hs_dir(const char *desc_id, const char *query, smartlist_t *hs_dirs_) { smartlist_t *responsible_dirs = smartlist_create(); routerinfo_t *hs_dir; char desc_id_base32[REND_DESC_ID_V2_BASE32 + 1]; int replica; tor_assert(desc_id); tor_assert(query); tor_assert(strlen(query) == REND_SERVICE_ID_LEN); /* Determine responsible dirs. */ if (hid_serv_get_responsible_directories(responsible_dirs, desc_id, hs_dirs_) < 0) { log_warn(LD_REND, "Could not determine the responsible hidden service " "directories to fetch descriptors."); smartlist_free(responsible_dirs); return; } replica = crypto_rand_int(REND_NUMBER_OF_CONSECUTIVE_REPLICAS); hs_dir = smartlist_get(responsible_dirs, replica); /* XXXX020 if hsdir fails, use another one... */ base32_encode(desc_id_base32, REND_DESC_ID_V2_BASE32 + 1, desc_id, DIGEST_LEN); /* Send fetch request. */ directory_initiate_command(hs_dir->address, hs_dir->addr, hs_dir->or_port, hs_dir->dir_port, 0, hs_dir->cache_info.identity_digest, DIR_PURPOSE_FETCH_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, 1, desc_id_base32, NULL, 0, 0); log_info(LD_REND, "Sending fetch request for v2 descriptor for " "service '%s' with descriptor ID '%s' to hidden " "service directory '%s' on port %d.", query, desc_id_base32, hs_dir->nickname, hs_dir->dir_port); smartlist_free(responsible_dirs); } src/or/dirserv.c +22 −2 Original line number Diff line number Diff line Loading @@ -1526,6 +1526,21 @@ dirserv_thinks_router_is_unreliable(time_t now, return 0; } /** Return true if <b>router</b> has an uptime of at least * <b>__MinUptimeHidServDirectoryV2</b> and is reachable in the last * REND_HS_DIR_REACHABLE_TIMEOUT seconds, else false. */ static int dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now) { int uptime = real_uptime(router, now); return (router->wants_to_be_hs_dir && uptime > get_options()->__MinUptimeHidServDirectoryV2 && ((router_is_me(router) && !we_are_hibernating()) || (now < router->last_reachable + REND_HS_DIR_REACHABLE_TIMEOUT))); } /** Look through the routerlist, and assign the median uptime of running valid * servers to stable_uptime, and the relative bandwidth capacities to * fast_bandwidth and guard_bandwidth. Set total_bandwidth to the total Loading Loading @@ -1674,13 +1689,14 @@ routerstatus_format_entry(char *buf, size_t buf_len, return 0; cp = buf + strlen(buf); r = tor_snprintf(cp, buf_len - (cp-buf), "s%s%s%s%s%s%s%s%s%s%s%s\n", "s%s%s%s%s%s%s%s%s%s%s%s%s\n", /* These must stay in alphabetical order. */ rs->is_authority?" Authority":"", rs->is_bad_exit?" BadExit":"", rs->is_exit?" Exit":"", rs->is_fast?" Fast":"", rs->is_possible_guard?" Guard":"", rs->is_hs_dir?" HSDir":"", rs->is_named?" Named":"", rs->is_running?" Running":"", rs->is_stable?" Stable":"", Loading Loading @@ -1843,6 +1859,10 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, rs->is_possible_guard = 0; } rs->is_bad_exit = listbadexits && ri->is_bad_exit; ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now); if (get_options()->__ConsiderAllRoutersAsHidServDirectories) ri->is_hs_dir = 1; /* Override real value. */ rs->is_hs_dir = ri->is_hs_dir; /* 0.1.1.9-alpha is the first version to support fetch by descriptor * hash. */ rs->is_v2_dir = ri->dir_port && Loading Loading @@ -1992,7 +2012,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, v3_out->server_versions = server_versions; v3_out->known_flags = smartlist_create(); smartlist_split_string(v3_out->known_flags, "Authority Exit Fast Guard Running Stable V2Dir Valid", "Authority Exit Fast Guard HSDir Running Stable V2Dir Valid", 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); if (listbadexits) smartlist_add(v3_out->known_flags, tor_strdup("BadExit")); Loading src/or/networkstatus.c +1 −0 Original line number Diff line number Diff line Loading @@ -1576,6 +1576,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, router->is_possible_guard = rs->is_possible_guard; router->is_exit = rs->is_exit; router->is_bad_exit = rs->is_bad_exit; router->is_hs_dir = rs->is_hs_dir; } if (router->is_running && ds) { download_status_reset(&ds->v2_ns_dl_status); Loading src/or/or.h +50 −1 Original line number Diff line number Diff line Loading @@ -351,7 +351,13 @@ typedef enum { /** Purpose for connection at a directory server. */ #define DIR_PURPOSE_SERVER 16 #define _DIR_PURPOSE_MAX 16 /** A connection to a hidden service directory server: upload a v2 rendezvous * descriptor. */ #define DIR_PURPOSE_UPLOAD_RENDDESC_V2 17 /** A connection to a hidden service directory server: download a v2 rendezvous * descriptor. */ #define DIR_PURPOSE_FETCH_RENDDESC_V2 18 #define _DIR_PURPOSE_MAX 18 #define _EXIT_PURPOSE_MIN 1 /** This exit stream wants to do an ordinary connect. */ Loading Loading @@ -608,6 +614,14 @@ typedef enum { /** Length of v2 descriptor ID (32 base32 chars = 160 bits). */ #define REND_DESC_ID_V2_BASE32 32 /** Length of the base32-encoded secret ID part of versioned hidden service * descriptors. */ #define REND_SECRET_ID_PART_LEN_BASE32 32 /** Length of the base32-encoded hash of an introduction point's * identity key. */ #define REND_INTRO_POINT_ID_LEN_BASE32 32 #define CELL_DIRECTION_IN 1 #define CELL_DIRECTION_OUT 2 Loading Loading @@ -1197,6 +1211,11 @@ typedef struct { unsigned int is_exit:1; /**< Do we think this is an OK exit? */ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked, * or otherwise nasty? */ unsigned int wants_to_be_hs_dir:1; /**< True iff this router has set a flag to possibly act as hidden service directory. */ unsigned int is_hs_dir:1; /**< True iff this router is a hidden service * directory. */ /** Tor can use this router for general positions in circuits. */ #define ROUTER_PURPOSE_GENERAL 0 Loading Loading @@ -1269,6 +1288,8 @@ typedef struct routerstatus_t { * an exit node. */ unsigned int is_bad_directory:1; /**< Do we think this directory is junky, * underpowered, or otherwise useless? */ unsigned int is_hs_dir:1; /** True iff this router is a hidden service * directory. */ /** True iff we know version info for this router. (i.e., a "v" entry was * included.) We'll replace all these with a big tor_version_t or a char[] * if the number of traits we care about ever becomes incredibly big. */ Loading Loading @@ -1998,6 +2019,10 @@ typedef struct { int PublishHidServDescriptors; int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */ int FetchHidServDescriptors; /** and hidden service descriptors? */ int HidServDirectoryV2; /**< Do we act as hs dir? */ int __MinUptimeHidServDirectoryV2; /**< Accept hs dirs after what time? */ int __ConsiderAllRoutersAsHidServDirectories; /**< Consider all routers as * hidden service dirs? */ int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */ int AllDirActionsPrivate; /**< Should every directory action be sent * through a Tor circuit? */ Loading Loading @@ -2849,6 +2874,12 @@ int dir_split_resource_into_fingerprints(const char *resource, char *directory_dump_request_log(void); int router_supports_extrainfo(const char *identity_digest, int is_authority); void directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *descs, const char *service_id, int seconds_valid, smartlist_t *hs_dirs); void directory_get_from_hs_dir(const char *desc_id, const char *query, smartlist_t *hs_dirs); time_t download_status_increment_failure(download_status_t *dls, int status_code, const char *item, int server, time_t now); Loading Loading @@ -3422,13 +3453,19 @@ typedef struct rend_cache_entry_t { void rend_cache_init(void); void rend_cache_clean(void); void rend_cache_clean_up(void); void rend_cache_clean_v2_dir(void); void rend_cache_free_all(void); int rend_valid_service_id(const char *query); int rend_cache_lookup_desc(const char *query, int version, const char **desc, size_t *desc_len); int rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **entry_out); int rend_cache_lookup_v2_dir(const char *query, char **desc); int rend_cache_store(const char *desc, size_t desc_len, int published); int rend_cache_store_v2_client(const char *desc, const char *descriptor_cookie); int rend_cache_store_v2_dir(const char *desc); int rend_cache_size(void); int rend_encode_v2_descriptors(smartlist_t *desc_strs_out, smartlist_t *desc_ids_out, Loading Loading @@ -3702,6 +3739,18 @@ void routerlist_assert_ok(routerlist_t *rl); const char *esc_router_info(routerinfo_t *router); void routers_sort_by_identity(smartlist_t *routers); smartlist_t *hid_serv_create_routing_table(void); int hid_serv_have_enough_directories(smartlist_t *hs_dirs); int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs, const char *id, smartlist_t *hs_dirs); routerinfo_t *hid_serv_next_directory(const char *id, smartlist_t *hs_dirs); routerinfo_t *hid_serv_previous_directory(const char *id, smartlist_t *hs_dirs); int hid_serv_acting_as_directory(smartlist_t *hs_dirs); int hid_serv_responsible_for_desc_id(const char *id, smartlist_t *hs_dirs); /********************************* routerparse.c ************************/ #define MAX_STATUS_TAG_LEN 32 Loading Loading
src/or/config.c +14 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,7 @@ static config_var_t _option_vars[] = { V(Group, STRING, NULL), V(HardwareAccel, BOOL, "0"), V(HashedControlPassword, STRING, NULL), V(HidServDirectoryV2, BOOL, "0"), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNodes", LINELIST_S, RendConfigLines, NULL), Loading Loading @@ -286,8 +287,12 @@ static config_var_t _option_vars[] = { VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"), V(VirtualAddrNetwork, STRING, "127.192.0.0/10"), VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"), VAR("__ConsiderAllRoutersAsHidServDirectories", BOOL, __ConsiderAllRoutersAsHidServDirectories, "0"), VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"), VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"), VAR("__MinUptimeHidServDirectoryV2", INTERVAL, __MinUptimeHidServDirectoryV2, "24 hours"), { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; Loading Loading @@ -2688,6 +2693,9 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("HSAuthorityRecordStats is set but we're not running as " "a hidden service authority."); if (options->HidServDirectoryV2 && !options->DirPort) REJECT("Running as hidden service directory, but no DirPort set."); if (options->ConnLimit <= 0) { r = tor_snprintf(buf, sizeof(buf), "ConnLimit must be greater than 0, but was set to %d", Loading Loading @@ -2820,6 +2828,12 @@ options_validate(or_options_t *old_options, or_options_t *options, return -1; } if (options->__MinUptimeHidServDirectoryV2 < 0) { log_warn(LD_CONFIG, "__MinUptimeHidServDirectoryV2 option must be at " "least 0 seconds. Changing to 0."); options->__MinUptimeHidServDirectoryV2 = 0; } if (options->RendPostPeriod < MIN_REND_POST_PERIOD) { log(LOG_WARN,LD_CONFIG,"RendPostPeriod option must be at least %d seconds." " Clipping.", MIN_REND_POST_PERIOD); Loading
src/or/directory.c +209 −9 Original line number Diff line number Diff line Loading @@ -157,6 +157,10 @@ dir_conn_purpose_to_string(int purpose) return "status vote fetch"; case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: return "consensus signature fetch"; case DIR_PURPOSE_FETCH_RENDDESC_V2: return "hidden-service v2 descriptor fetch"; case DIR_PURPOSE_UPLOAD_RENDDESC_V2: return "hidden-service v2 descriptor upload"; } log_warn(LD_BUG, "Called with unknown purpose %d", purpose); Loading Loading @@ -422,7 +426,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose, * upload or download a server or rendezvous * descriptor. <b>dir_purpose</b> determines what * kind of directory connection we're launching, and must be one of * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}. <b>router_purpose</b> * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b> * specifies the descriptor purposes we have in mind (currently only * used for FETCH_DIR). * Loading Loading @@ -867,12 +871,27 @@ directory_send_command(dir_connection_t *conn, url = tor_malloc(len); tor_snprintf(url, len, "/tor/rendezvous/%s", resource); break; case DIR_PURPOSE_FETCH_RENDDESC_V2: tor_assert(resource); tor_assert(!payload); tor_assert(strlen(resource) <= REND_DESC_ID_V2_BASE32); httpcommand = "GET"; len = strlen(resource) + 32; url = tor_malloc(len); tor_snprintf(url, len, "/tor/rendezvous2/%s", resource); break; case DIR_PURPOSE_UPLOAD_RENDDESC: tor_assert(!resource); tor_assert(payload); httpcommand = "POST"; url = tor_strdup("/tor/rendezvous/publish"); break; case DIR_PURPOSE_UPLOAD_RENDDESC_V2: tor_assert(!resource); tor_assert(payload); httpcommand = "POST"; url = tor_strdup("/tor/rendezvous2/publish"); break; default: tor_assert(0); return; Loading Loading @@ -1721,8 +1740,46 @@ connection_dir_client_reached_eof(dir_connection_t *conn) } } if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC) { log_info(LD_REND,"Uploaded rendezvous descriptor (status %d (%s))", if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) { log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d " "(%s))", (int)body_len, status_code, escaped(reason)); switch (status_code) { case 200: if (rend_cache_store_v2_client(body, NULL) < 0) { log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed."); /* alice's ap_stream will notice when connection_mark_for_close * cleans it up */ } else { /* success. notify pending connections about this. */ log_info(LD_REND, "Successfully fetched rendezvous descriptor."); conn->_base.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC; rend_client_desc_here(conn->rend_query); } break; case 404: /* not there. pending connections will be notified when * connection_mark_for_close cleans it up. */ break; case 400: log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: " "http status 400 (%s). Dirserver didn't like our " "v2 rendezvous query?", escaped(reason)); break; default: log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: " "http status %d (%s) response unexpected while " "fetching v2 hidden service descriptor (server '%s:%d').", status_code, escaped(reason), conn->_base.address, conn->_base.port); break; } } if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC || conn->_base.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) { log_info(LD_REND,"Uploaded rendezvous descriptor (status %d " "(%s))", status_code, escaped(reason)); switch (status_code) { case 200: Loading Loading @@ -2428,6 +2485,32 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, goto done; } if (options->HidServDirectoryV2 && !strcmpstart(url,"/tor/rendezvous2/")) { /* Handle v2 rendezvous descriptor fetch request. */ char *descp; const char *query = url + strlen("/tor/rendezvous2/"); if (strlen(query) == REND_DESC_ID_V2_BASE32) { log_info(LD_REND, "Got a v2 rendezvous descriptor request for ID '%s'", query); switch (rend_cache_lookup_v2_dir(query, &descp)) { case 1: /* valid */ write_http_response_header(conn, strlen(descp), 0, 0); connection_write_to_buf(descp, strlen(descp), TO_CONN(conn)); break; case 0: /* well-formed but not present */ write_http_status_line(conn, 404, "Not found"); break; case -1: /* not well-formed */ write_http_status_line(conn, 400, "Bad request"); break; } } else { /* not well-formed */ write_http_status_line(conn, 400, "Bad request"); } goto done; } if (options->HSAuthoritativeDir && !strcmpstart(url,"/tor/rendezvous/")) { /* rendezvous descriptor fetch */ const char *descp; Loading Loading @@ -2546,6 +2629,27 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, conn->_base.state = DIR_CONN_STATE_SERVER_WRITING; if (parse_http_url(headers, &url) < 0) { write_http_status_line(conn, 400, "Bad request"); return 0; } log_debug(LD_DIRSERV,"rewritten url as '%s'.", url); /* Handle v2 rendezvous service publish request. */ if (options->HidServDirectoryV2 && !strcmpstart(url,"/tor/rendezvous2/publish")) { if (rend_cache_store_v2_dir(body) < 0) { log_warn(LD_REND, "Rejected rend descriptor (length %d) from %s.", (int)body_len, conn->_base.address); write_http_status_line(conn, 400, "Invalid service descriptor rejected"); log_info(LD_REND, "Handled v2 rendezvous descriptor post: rejected"); } else { write_http_status_line(conn, 200, "Service descriptor stored"); log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted"); } goto done; } if (!authdir_mode(options)) { /* we just provide cached directories; we don't want to * receive anything. */ Loading @@ -2554,12 +2658,6 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, return 0; } if (parse_http_url(headers, &url) < 0) { write_http_status_line(conn, 400, "Bad request"); return 0; } log_debug(LD_DIRSERV,"rewritten url as '%s'.", url); if (authdir_mode_handles_descs(options) && !strcmp(url,"/tor/")) { /* server descriptor post */ const char *msg = NULL; Loading Loading @@ -2948,3 +3046,105 @@ dir_split_resource_into_fingerprints(const char *resource, return 0; } /** Determine the responsible hidden service directories for * <b>desc_ids</b> and upload the appropriate descriptor from * <b>desc_strs</b> to them; each smartlist must contain * REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS entries; <b>service_id</b> and * <b>seconds_valid</b> are only passed for logging purposes.*/ /* XXXX020 enable tunneling when available!! */ void directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *desc_strs, const char *service_id, int seconds_valid, smartlist_t *hs_dirs_) { int i, j; smartlist_t *responsible_dirs; routerinfo_t *hs_dir; if (smartlist_len(desc_ids) != REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS || smartlist_len(desc_strs) != REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS) { log_warn(LD_REND, "Could not post descriptors to hidden service " "directories: Illegal number of descriptor " "IDs/strings"); return; } responsible_dirs = smartlist_create(); for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) { const char *desc_id = smartlist_get(desc_ids, i); const char *desc_str = smartlist_get(desc_strs, i); /* Determine responsible dirs. */ if (hid_serv_get_responsible_directories(responsible_dirs, desc_id, hs_dirs_) < 0) { log_warn(LD_REND, "Could not determine the responsible hidden service " "directories to post descriptors to."); smartlist_free(responsible_dirs); return; } for (j = 0; j < REND_NUMBER_OF_CONSECUTIVE_REPLICAS; j++) { char desc_id_base32[REND_DESC_ID_V2_BASE32 + 1]; hs_dir = smartlist_get(responsible_dirs, j); /* Send publish request. */ directory_initiate_command(hs_dir->address, hs_dir->addr, hs_dir->or_port, hs_dir->dir_port, 0, hs_dir->cache_info.identity_digest, DIR_PURPOSE_UPLOAD_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, 1, NULL, desc_str, strlen(desc_str), 0); base32_encode(desc_id_base32, REND_DESC_ID_V2_BASE32 + 1, desc_id, DIGEST_LEN); log_info(LD_REND, "Sending publish request for v2 descriptor for " "service '%s' with descriptor ID '%s' with validity " "of %d seconds to hidden service directory '%s' on " "port %d.", service_id, desc_id_base32, seconds_valid, hs_dir->nickname, hs_dir->dir_port); } smartlist_clear(responsible_dirs); } smartlist_free(responsible_dirs); } /** Determine the responsible hidden service directories for <b>desc_id</b> * and fetch the descriptor belonging to this ID from one of them; * <b>query</b> is only passed for pretty log statements. * XXXX020 enable tunneling when available!! */ void directory_get_from_hs_dir(const char *desc_id, const char *query, smartlist_t *hs_dirs_) { smartlist_t *responsible_dirs = smartlist_create(); routerinfo_t *hs_dir; char desc_id_base32[REND_DESC_ID_V2_BASE32 + 1]; int replica; tor_assert(desc_id); tor_assert(query); tor_assert(strlen(query) == REND_SERVICE_ID_LEN); /* Determine responsible dirs. */ if (hid_serv_get_responsible_directories(responsible_dirs, desc_id, hs_dirs_) < 0) { log_warn(LD_REND, "Could not determine the responsible hidden service " "directories to fetch descriptors."); smartlist_free(responsible_dirs); return; } replica = crypto_rand_int(REND_NUMBER_OF_CONSECUTIVE_REPLICAS); hs_dir = smartlist_get(responsible_dirs, replica); /* XXXX020 if hsdir fails, use another one... */ base32_encode(desc_id_base32, REND_DESC_ID_V2_BASE32 + 1, desc_id, DIGEST_LEN); /* Send fetch request. */ directory_initiate_command(hs_dir->address, hs_dir->addr, hs_dir->or_port, hs_dir->dir_port, 0, hs_dir->cache_info.identity_digest, DIR_PURPOSE_FETCH_RENDDESC_V2, ROUTER_PURPOSE_GENERAL, 1, desc_id_base32, NULL, 0, 0); log_info(LD_REND, "Sending fetch request for v2 descriptor for " "service '%s' with descriptor ID '%s' to hidden " "service directory '%s' on port %d.", query, desc_id_base32, hs_dir->nickname, hs_dir->dir_port); smartlist_free(responsible_dirs); }
src/or/dirserv.c +22 −2 Original line number Diff line number Diff line Loading @@ -1526,6 +1526,21 @@ dirserv_thinks_router_is_unreliable(time_t now, return 0; } /** Return true if <b>router</b> has an uptime of at least * <b>__MinUptimeHidServDirectoryV2</b> and is reachable in the last * REND_HS_DIR_REACHABLE_TIMEOUT seconds, else false. */ static int dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now) { int uptime = real_uptime(router, now); return (router->wants_to_be_hs_dir && uptime > get_options()->__MinUptimeHidServDirectoryV2 && ((router_is_me(router) && !we_are_hibernating()) || (now < router->last_reachable + REND_HS_DIR_REACHABLE_TIMEOUT))); } /** Look through the routerlist, and assign the median uptime of running valid * servers to stable_uptime, and the relative bandwidth capacities to * fast_bandwidth and guard_bandwidth. Set total_bandwidth to the total Loading Loading @@ -1674,13 +1689,14 @@ routerstatus_format_entry(char *buf, size_t buf_len, return 0; cp = buf + strlen(buf); r = tor_snprintf(cp, buf_len - (cp-buf), "s%s%s%s%s%s%s%s%s%s%s%s\n", "s%s%s%s%s%s%s%s%s%s%s%s%s\n", /* These must stay in alphabetical order. */ rs->is_authority?" Authority":"", rs->is_bad_exit?" BadExit":"", rs->is_exit?" Exit":"", rs->is_fast?" Fast":"", rs->is_possible_guard?" Guard":"", rs->is_hs_dir?" HSDir":"", rs->is_named?" Named":"", rs->is_running?" Running":"", rs->is_stable?" Stable":"", Loading Loading @@ -1843,6 +1859,10 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, rs->is_possible_guard = 0; } rs->is_bad_exit = listbadexits && ri->is_bad_exit; ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now); if (get_options()->__ConsiderAllRoutersAsHidServDirectories) ri->is_hs_dir = 1; /* Override real value. */ rs->is_hs_dir = ri->is_hs_dir; /* 0.1.1.9-alpha is the first version to support fetch by descriptor * hash. */ rs->is_v2_dir = ri->dir_port && Loading Loading @@ -1992,7 +2012,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, v3_out->server_versions = server_versions; v3_out->known_flags = smartlist_create(); smartlist_split_string(v3_out->known_flags, "Authority Exit Fast Guard Running Stable V2Dir Valid", "Authority Exit Fast Guard HSDir Running Stable V2Dir Valid", 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); if (listbadexits) smartlist_add(v3_out->known_flags, tor_strdup("BadExit")); Loading
src/or/networkstatus.c +1 −0 Original line number Diff line number Diff line Loading @@ -1576,6 +1576,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, router->is_possible_guard = rs->is_possible_guard; router->is_exit = rs->is_exit; router->is_bad_exit = rs->is_bad_exit; router->is_hs_dir = rs->is_hs_dir; } if (router->is_running && ds) { download_status_reset(&ds->v2_ns_dl_status); Loading
src/or/or.h +50 −1 Original line number Diff line number Diff line Loading @@ -351,7 +351,13 @@ typedef enum { /** Purpose for connection at a directory server. */ #define DIR_PURPOSE_SERVER 16 #define _DIR_PURPOSE_MAX 16 /** A connection to a hidden service directory server: upload a v2 rendezvous * descriptor. */ #define DIR_PURPOSE_UPLOAD_RENDDESC_V2 17 /** A connection to a hidden service directory server: download a v2 rendezvous * descriptor. */ #define DIR_PURPOSE_FETCH_RENDDESC_V2 18 #define _DIR_PURPOSE_MAX 18 #define _EXIT_PURPOSE_MIN 1 /** This exit stream wants to do an ordinary connect. */ Loading Loading @@ -608,6 +614,14 @@ typedef enum { /** Length of v2 descriptor ID (32 base32 chars = 160 bits). */ #define REND_DESC_ID_V2_BASE32 32 /** Length of the base32-encoded secret ID part of versioned hidden service * descriptors. */ #define REND_SECRET_ID_PART_LEN_BASE32 32 /** Length of the base32-encoded hash of an introduction point's * identity key. */ #define REND_INTRO_POINT_ID_LEN_BASE32 32 #define CELL_DIRECTION_IN 1 #define CELL_DIRECTION_OUT 2 Loading Loading @@ -1197,6 +1211,11 @@ typedef struct { unsigned int is_exit:1; /**< Do we think this is an OK exit? */ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked, * or otherwise nasty? */ unsigned int wants_to_be_hs_dir:1; /**< True iff this router has set a flag to possibly act as hidden service directory. */ unsigned int is_hs_dir:1; /**< True iff this router is a hidden service * directory. */ /** Tor can use this router for general positions in circuits. */ #define ROUTER_PURPOSE_GENERAL 0 Loading Loading @@ -1269,6 +1288,8 @@ typedef struct routerstatus_t { * an exit node. */ unsigned int is_bad_directory:1; /**< Do we think this directory is junky, * underpowered, or otherwise useless? */ unsigned int is_hs_dir:1; /** True iff this router is a hidden service * directory. */ /** True iff we know version info for this router. (i.e., a "v" entry was * included.) We'll replace all these with a big tor_version_t or a char[] * if the number of traits we care about ever becomes incredibly big. */ Loading Loading @@ -1998,6 +2019,10 @@ typedef struct { int PublishHidServDescriptors; int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */ int FetchHidServDescriptors; /** and hidden service descriptors? */ int HidServDirectoryV2; /**< Do we act as hs dir? */ int __MinUptimeHidServDirectoryV2; /**< Accept hs dirs after what time? */ int __ConsiderAllRoutersAsHidServDirectories; /**< Consider all routers as * hidden service dirs? */ int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */ int AllDirActionsPrivate; /**< Should every directory action be sent * through a Tor circuit? */ Loading Loading @@ -2849,6 +2874,12 @@ int dir_split_resource_into_fingerprints(const char *resource, char *directory_dump_request_log(void); int router_supports_extrainfo(const char *identity_digest, int is_authority); void directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *descs, const char *service_id, int seconds_valid, smartlist_t *hs_dirs); void directory_get_from_hs_dir(const char *desc_id, const char *query, smartlist_t *hs_dirs); time_t download_status_increment_failure(download_status_t *dls, int status_code, const char *item, int server, time_t now); Loading Loading @@ -3422,13 +3453,19 @@ typedef struct rend_cache_entry_t { void rend_cache_init(void); void rend_cache_clean(void); void rend_cache_clean_up(void); void rend_cache_clean_v2_dir(void); void rend_cache_free_all(void); int rend_valid_service_id(const char *query); int rend_cache_lookup_desc(const char *query, int version, const char **desc, size_t *desc_len); int rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **entry_out); int rend_cache_lookup_v2_dir(const char *query, char **desc); int rend_cache_store(const char *desc, size_t desc_len, int published); int rend_cache_store_v2_client(const char *desc, const char *descriptor_cookie); int rend_cache_store_v2_dir(const char *desc); int rend_cache_size(void); int rend_encode_v2_descriptors(smartlist_t *desc_strs_out, smartlist_t *desc_ids_out, Loading Loading @@ -3702,6 +3739,18 @@ void routerlist_assert_ok(routerlist_t *rl); const char *esc_router_info(routerinfo_t *router); void routers_sort_by_identity(smartlist_t *routers); smartlist_t *hid_serv_create_routing_table(void); int hid_serv_have_enough_directories(smartlist_t *hs_dirs); int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs, const char *id, smartlist_t *hs_dirs); routerinfo_t *hid_serv_next_directory(const char *id, smartlist_t *hs_dirs); routerinfo_t *hid_serv_previous_directory(const char *id, smartlist_t *hs_dirs); int hid_serv_acting_as_directory(smartlist_t *hs_dirs); int hid_serv_responsible_for_desc_id(const char *id, smartlist_t *hs_dirs); /********************************* routerparse.c ************************/ #define MAX_STATUS_TAG_LEN 32 Loading