aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2014-02-15 15:06:06 -0500
committerNick Mathewson <nickm@torproject.org>2014-02-15 15:06:06 -0500
commit67749475f56532235602e0c8d1a9a59a68d816c3 (patch)
treec7775cfa8342016bef490144db5c1bb31da37474
parent9d0af78e3cffde924ec65247cd8ef97cf5319d28 (diff)
parentac5ae794bd58aafcf0dddfaa09abd2184b11bbde (diff)
downloadtor-67749475f56532235602e0c8d1a9a59a68d816c3.tar
tor-67749475f56532235602e0c8d1a9a59a68d816c3.tar.gz
Merge remote-tracking branch 'public/bug10841'
-rw-r--r--changes/bug108416
-rw-r--r--src/or/directory.c104
-rw-r--r--src/or/or.h15
-rw-r--r--src/or/rendclient.c3
-rw-r--r--src/or/rendcommon.c260
-rw-r--r--src/or/rendcommon.h18
6 files changed, 56 insertions, 350 deletions
diff --git a/changes/bug10841 b/changes/bug10841
new file mode 100644
index 000000000..5b065a8b2
--- /dev/null
+++ b/changes/bug10841
@@ -0,0 +1,6 @@
+ o Removed code
+ - Remove all code for hidden service authorities to accept and serve
+ version 0 descriptors and left-over code for hidden services and
+ hidden service clients to upload and fetch version 0 descriptors.
+ Version 0 descriptors are not in use anymore since 0.2.2.1-alpha.
+ Fixes the rest of bug 10841.
diff --git a/src/or/directory.c b/src/or/directory.c
index c102512c2..739885c76 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -170,12 +170,8 @@ dir_conn_purpose_to_string(int purpose)
{
switch (purpose)
{
- case DIR_PURPOSE_FETCH_RENDDESC:
- return "hidden-service descriptor fetch";
case DIR_PURPOSE_UPLOAD_DIR:
return "server descriptor upload";
- case DIR_PURPOSE_UPLOAD_RENDDESC:
- return "hidden-service descriptor upload";
case DIR_PURPOSE_UPLOAD_VOTE:
return "server vote upload";
case DIR_PURPOSE_UPLOAD_SIGNATURES:
@@ -247,13 +243,13 @@ directories_have_accepted_server_descriptor(void)
/** Start a connection to every suitable directory authority, using
* connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
* (of length <b>payload_len</b>). The dir_purpose should be one of
- * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
+ * 'DIR_PURPOSE_UPLOAD_{DIR|VOTE|SIGNATURES}'.
*
* <b>router_purpose</b> describes the type of descriptor we're
* publishing, if we're publishing a descriptor -- e.g. general or bridge.
*
* <b>type</b> specifies what sort of dir authorities (V1, V3,
- * HIDSERV, BRIDGE, etc) we should upload to.
+ * BRIDGE, etc) we should upload to.
*
* If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
* <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
@@ -410,9 +406,6 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
V3_DIRINFO);
break;
- case DIR_PURPOSE_FETCH_RENDDESC:
- type = HIDSERV_DIRINFO;
- break;
case DIR_PURPOSE_FETCH_STATUS_VOTE:
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
case DIR_PURPOSE_FETCH_CERTIFICATE:
@@ -452,7 +445,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
}
- if (!options->FetchServerDescriptors && type != HIDSERV_DIRINFO)
+ if (!options->FetchServerDescriptors)
return;
if (!get_via_tor) {
@@ -523,11 +516,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
} else { /* get_via_tor */
/* Never use fascistfirewall; we're going via Tor. */
- if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
- /* only ask hidserv authorities, any of them will do */
- pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
- rs = router_pick_trusteddirserver(HIDSERV_DIRINFO, pds_flags);
- } else {
+ if (1) {
/* anybody with a non-zero dirport will do. Disregard firewalls. */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
rs = router_pick_directory_server(type, pds_flags);
@@ -649,7 +638,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
* 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|RENDDESC_V2}. <b>router_purpose</b>
+ * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC_V2}. <b>router_purpose</b>
* specifies the descriptor purposes we have in mind (currently only
* used for FETCH_DIR).
*
@@ -900,9 +889,7 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr,
static int
is_sensitive_dir_purpose(uint8_t dir_purpose)
{
- return ((dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) ||
- (dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC) ||
- (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC) ||
+ return ((dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2) ||
(dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
(dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
}
@@ -1267,12 +1254,6 @@ directory_send_command(dir_connection_t *conn,
httpcommand = "GET";
tor_asprintf(&url, "/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);
@@ -1532,20 +1513,18 @@ body_is_plausible(const char *body, size_t len, int purpose)
if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
return (!strcmpstart(body,"onion-key"));
}
- if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
+ if (1) {
if (!strcmpstart(body,"router") ||
!strcmpstart(body,"signed-directory") ||
!strcmpstart(body,"network-status") ||
!strcmpstart(body,"running-routers"))
- return 1;
+ return 1;
for (i=0;i<32;++i) {
if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
return 0;
}
- return 1;
- } else {
- return 1;
}
+ return 1;
}
/** Called when we've just fetched a bunch of router descriptors in
@@ -2104,46 +2083,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
* dirservers down just because they don't like us. */
}
- if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
- tor_assert(conn->rend_data);
- 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(body, body_len, 0,
- conn->rend_data->onion_address) < -1) {
- log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
- /* Any pending rendezvous attempts will notice when
- * connection_about_to_close_connection()
- * cleans this dir conn up. */
- /* We could retry. But since v0 descriptors are going out of
- * style, it isn't worth the hassle. We'll do better in v2. */
- } else {
- /* Success, or at least there's a v2 descriptor already
- * present. Notify pending connections about this. */
- conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
- rend_client_desc_trynow(conn->rend_data->onion_address);
- }
- break;
- case 404:
- /* Not there. Pending connections will be notified when
- * connection_about_to_close_connection() cleans this conn up. */
- break;
- case 400:
- log_warn(LD_REND,
- "http status 400 (%s). Dirserver didn't like our "
- "rendezvous query?", escaped(reason));
- break;
- default:
- log_warn(LD_REND,"http status %d (%s) response unexpected while "
- "fetching hidden service descriptor (server '%s:%d').",
- status_code, escaped(reason), conn->base_.address,
- conn->base_.port);
- break;
- }
- }
-
if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
#define SEND_HS_DESC_FAILED_EVENT() ( \
control_event_hs_descriptor_failed(conn->rend_data, \
@@ -2155,27 +2094,22 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
switch (status_code) {
case 200:
switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) {
- case -2:
+ case RCS_BADDESC:
+ case RCS_NOTDIR: /* Impossible */
log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
"Retrying at another directory.");
/* We'll retry when connection_about_to_close_connection()
* cleans this dir conn up. */
SEND_HS_DESC_FAILED_EVENT();
break;
- case -1:
- /* We already have a v0 descriptor here. Ignoring this one
- * and _not_ performing another request. */
- log_info(LD_REND, "Successfully fetched v2 rendezvous "
- "descriptor, but we already have a v0 descriptor.");
- conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
- break;
+ case RCS_OKAY:
default:
/* success. notify pending connections about this. */
log_info(LD_REND, "Successfully fetched v2 rendezvous "
"descriptor.");
control_event_hs_descriptor_received(conn->rend_data,
conn->identity_digest);
- conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
+ conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
rend_client_desc_trynow(conn->rend_data->onion_address);
break;
}
@@ -2206,8 +2140,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
}
- if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
- conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
+ if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
"(%s))",
status_code, escaped(reason));
@@ -2311,7 +2244,7 @@ connection_dir_about_to_close(dir_connection_t *dir_conn)
}
/* If we were trying to fetch a v2 rend desc and did not succeed,
* retry as needed. (If a fetch is successful, the connection state
- * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
+ * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 to mark that
* refetching is unnecessary.) */
if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
dir_conn->rend_data &&
@@ -2452,9 +2385,7 @@ note_client_request(int purpose, int compressed, size_t bytes)
case DIR_PURPOSE_UPLOAD_DIR: kind = "dl/ul-dir"; break;
case DIR_PURPOSE_UPLOAD_VOTE: kind = "dl/ul-vote"; break;
case DIR_PURPOSE_UPLOAD_SIGNATURES: kind = "dl/ul-sig"; break;
- case DIR_PURPOSE_FETCH_RENDDESC: kind = "dl/rend"; break;
case DIR_PURPOSE_FETCH_RENDDESC_V2: kind = "dl/rend2"; break;
- case DIR_PURPOSE_UPLOAD_RENDDESC: kind = "dl/ul-rend"; break;
case DIR_PURPOSE_UPLOAD_RENDDESC_V2: kind = "dl/ul-rend2"; break;
}
if (kind) {
@@ -3312,19 +3243,20 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
connection_dir_is_encrypted(conn) &&
!strcmpstart(url,"/tor/rendezvous2/publish")) {
switch (rend_cache_store_v2_desc_as_dir(body)) {
- case -2:
+ case RCS_NOTDIR:
log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
"since we're not currently a hidden service directory.",
(int)body_len, conn->base_.address);
write_http_status_line(conn, 503, "Currently not acting as v2 "
"hidden service directory");
break;
- case -1:
+ case RCS_BADDESC:
log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
(int)body_len, conn->base_.address);
write_http_status_line(conn, 400,
"Invalid v2 service descriptor rejected");
break;
+ case RCS_OKAY:
default:
write_http_status_line(conn, 200, "Service descriptor (v2) stored");
log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");
diff --git a/src/or/or.h b/src/or/or.h
index cc4e5ed9d..c47ae23ed 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -400,13 +400,10 @@ typedef enum {
#define CONTROL_CONN_STATE_NEEDAUTH 2
#define CONTROL_CONN_STATE_MAX_ 2
-#define DIR_PURPOSE_MIN_ 3
-/** A connection to a directory server: download a rendezvous
- * descriptor. */
-#define DIR_PURPOSE_FETCH_RENDDESC 3
-/** A connection to a directory server: set after a rendezvous
+#define DIR_PURPOSE_MIN_ 4
+/** A connection to a directory server: set after a v2 rendezvous
* descriptor is downloaded. */
-#define DIR_PURPOSE_HAS_FETCHED_RENDDESC 4
+#define DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 4
/** A connection to a directory server: download one or more server
* descriptors. */
#define DIR_PURPOSE_FETCH_SERVERDESC 6
@@ -415,9 +412,6 @@ typedef enum {
#define DIR_PURPOSE_FETCH_EXTRAINFO 7
/** A connection to a directory server: upload a server descriptor. */
#define DIR_PURPOSE_UPLOAD_DIR 8
-/** A connection to a directory server: upload a rendezvous
- * descriptor. */
-#define DIR_PURPOSE_UPLOAD_RENDDESC 9
/** A connection to a directory server: upload a v3 networkstatus vote. */
#define DIR_PURPOSE_UPLOAD_VOTE 10
/** A connection to a directory server: upload a v3 consensus signature */
@@ -451,7 +445,6 @@ typedef enum {
* directory server. */
#define DIR_PURPOSE_IS_UPLOAD(p) \
((p)==DIR_PURPOSE_UPLOAD_DIR || \
- (p)==DIR_PURPOSE_UPLOAD_RENDDESC || \
(p)==DIR_PURPOSE_UPLOAD_VOTE || \
(p)==DIR_PURPOSE_UPLOAD_SIGNATURES)
@@ -2599,8 +2592,6 @@ typedef enum {
V1_DIRINFO = 1 << 0,
/** Serves/signs v3 directory information: votes, consensuses, certs */
V3_DIRINFO = 1 << 2,
- /** Serves hidden service descriptors. */
- HIDSERV_DIRINFO = 1 << 3,
/** Serves bridge descriptors. */
BRIDGE_DIRINFO = 1 << 4,
/** Serves extrainfo documents. */
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 2327a547c..24d720c91 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -796,8 +796,7 @@ rend_client_cancel_descriptor_fetches(void)
SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
if (conn->type == CONN_TYPE_DIR &&
- (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC ||
- conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)) {
+ conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
/* It's a rendezvous descriptor fetch in progress -- cancel it
* by marking the connection for close.
*
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index d1b49411c..a664b5d50 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -672,79 +672,6 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
return seconds_valid;
}
-/** Parse a service descriptor at <b>str</b> (<b>len</b> bytes). On
- * success, return a newly alloced service_descriptor_t. On failure,
- * return NULL.
- */
-rend_service_descriptor_t *
-rend_parse_service_descriptor(const char *str, size_t len)
-{
- rend_service_descriptor_t *result = NULL;
- int i, n_intro_points;
- size_t keylen, asn1len;
- const char *end, *cp, *eos;
- rend_intro_point_t *intro;
-
- result = tor_malloc_zero(sizeof(rend_service_descriptor_t));
- cp = str;
- end = str+len;
- if (end-cp<2) goto truncated;
- result->version = 0;
- if (end-cp < 2) goto truncated;
- asn1len = ntohs(get_uint16(cp));
- cp += 2;
- if ((size_t)(end-cp) < asn1len) goto truncated;
- result->pk = crypto_pk_asn1_decode(cp, asn1len);
- if (!result->pk) goto truncated;
- cp += asn1len;
- if (end-cp < 4) goto truncated;
- result->timestamp = (time_t) ntohl(get_uint32(cp));
- cp += 4;
- result->protocols = 1<<2; /* always use intro format 2 */
- if (end-cp < 2) goto truncated;
- n_intro_points = ntohs(get_uint16(cp));
- cp += 2;
-
- result->intro_nodes = smartlist_new();
- for (i=0;i<n_intro_points;++i) {
- if (end-cp < 2) goto truncated;
- eos = (const char *)memchr(cp,'\0',end-cp);
- if (!eos) goto truncated;
- /* Write nickname to extend info, but postpone the lookup whether
- * we know that router. It's not part of the parsing process. */
- intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
- strlcpy(intro->extend_info->nickname, cp,
- sizeof(intro->extend_info->nickname));
- smartlist_add(result->intro_nodes, intro);
- cp = eos+1;
- }
- keylen = crypto_pk_keysize(result->pk);
- tor_assert(end-cp >= 0);
- if ((size_t)(end-cp) < keylen) goto truncated;
- if ((size_t)(end-cp) > keylen) {
- log_warn(LD_PROTOCOL,
- "Signature is %d bytes too long on service descriptor.",
- (int)((size_t)(end-cp) - keylen));
- goto error;
- }
- note_crypto_pk_op(REND_CLIENT);
- if (crypto_pk_public_checksig_digest(result->pk,
- (char*)str,cp-str, /* data */
- (char*)cp,end-cp /* signature*/
- )<0) {
- log_warn(LD_PROTOCOL, "Bad signature on service descriptor.");
- goto error;
- }
-
- return result;
- truncated:
- log_warn(LD_PROTOCOL, "Truncated service descriptor.");
- error:
- rend_service_descriptor_free(result);
- return NULL;
-}
-
/** Sets <b>out</b> to the first 10 bytes of the digest of <b>pk</b>,
* base32 encoded. NUL-terminates out. (We use this string to
* identify services in directory requests and .onion URLs.)
@@ -843,7 +770,7 @@ void
rend_cache_purge(void)
{
if (rend_cache) {
- log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache");
+ log_info(LD_REND, "Purging HS descriptor cache");
strmap_free(rend_cache, rend_cache_entry_free_);
}
rend_cache = strmap_new();
@@ -954,27 +881,6 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
return 1;
}
-/** <b>query</b> is a base32'ed service id. If it's malformed, return -1.
- * Else look it up.
- * - If it is found, point *desc to it, and write its length into
- * *desc_len, and return 1.
- * - If it is not found, return 0.
- * Note: calls to rend_cache_clean or rend_cache_store may invalidate
- * *desc.
- */
-int
-rend_cache_lookup_desc(const char *query, int version, const char **desc,
- size_t *desc_len)
-{
- rend_cache_entry_t *e;
- int r;
- r = rend_cache_lookup_entry(query,version,&e);
- if (r <= 0) return r;
- *desc = e->desc;
- *desc_len = e->len;
- return 1;
-}
-
/** Lookup the v2 service descriptor with base32-encoded <b>desc_id</b> and
* copy the pointer to it to *<b>desc</b>. Return 1 on success, 0 on
* well-formed-but-not-found, and -1 on failure.
@@ -1006,130 +912,16 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
* descriptor */
#define MAX_INTRO_POINTS 10
-/** Parse *desc, calculate its service id, and store it in the cache.
- * If we have a newer v0 descriptor with the same ID, ignore this one.
- * If we have an older descriptor with the same ID, replace it.
- * If we are acting as client due to the published flag and have any v2
- * descriptor with the same ID, reject this one in order to not get
- * confused with having both versions for the same service.
- *
- * Return -2 if it's malformed or otherwise rejected; return -1 if we
- * already have a v2 descriptor here; return 0 if it's the same or older
- * than one we've already got; return 1 if it's novel.
- *
- * The published flag tells us if we store the descriptor
- * in our role as directory (1) or if we cache it as client (0).
- *
- * If <b>service_id</b> is non-NULL and the descriptor is not for that
- * service ID, reject it. <b>service_id</b> must be specified if and
- * only if <b>published</b> is 0 (we fetched this descriptor).
- */
-int
-rend_cache_store(const char *desc, size_t desc_len, int published,
- const char *service_id)
-{
- rend_cache_entry_t *e;
- rend_service_descriptor_t *parsed;
- char query[REND_SERVICE_ID_LEN_BASE32+1];
- char key[REND_SERVICE_ID_LEN_BASE32+2]; /* 0<query>\0 */
- time_t now;
- tor_assert(rend_cache);
- parsed = rend_parse_service_descriptor(desc,desc_len);
- if (!parsed) {
- log_warn(LD_PROTOCOL,"Couldn't parse service descriptor.");
- return -2;
- }
- if (rend_get_service_id(parsed->pk, query)<0) {
- log_warn(LD_BUG,"Couldn't compute service ID.");
- rend_service_descriptor_free(parsed);
- return -2;
- }
- if ((service_id != NULL) && strcmp(query, service_id)) {
- log_warn(LD_REND, "Received service descriptor for service ID %s; "
- "expected descriptor for service ID %s.",
- query, safe_str(service_id));
- rend_service_descriptor_free(parsed);
- return -2;
- }
- now = time(NULL);
- if (parsed->timestamp < now-REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
- log_fn(LOG_PROTOCOL_WARN, LD_REND,
- "Service descriptor %s is too old.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return -2;
- }
- if (parsed->timestamp > now+REND_CACHE_MAX_SKEW) {
- log_fn(LOG_PROTOCOL_WARN, LD_REND,
- "Service descriptor %s is too far in the future.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return -2;
- }
- /* Do we have a v2 descriptor and fetched this descriptor as a client? */
- tor_snprintf(key, sizeof(key), "2%s", query);
- if (!published && strmap_get_lc(rend_cache, key)) {
- log_info(LD_REND, "We already have a v2 descriptor for service %s.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return -1;
- }
- if (parsed->intro_nodes &&
- smartlist_len(parsed->intro_nodes) > MAX_INTRO_POINTS) {
- log_warn(LD_REND, "Found too many introduction points on a hidden "
- "service descriptor for %s. This is probably a (misguided) "
- "attempt to improve reliability, but it could also be an "
- "attempt to do a guard enumeration attack. Rejecting.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return -2;
- }
- tor_snprintf(key, sizeof(key), "0%s", query);
- e = (rend_cache_entry_t*) strmap_get_lc(rend_cache, key);
- if (e && e->parsed->timestamp > parsed->timestamp) {
- log_info(LD_REND,"We already have a newer service descriptor %s with the "
- "same ID and version.",
- safe_str_client(query));
- rend_service_descriptor_free(parsed);
- return 0;
- }
- if (e && e->len == desc_len && tor_memeq(desc,e->desc,desc_len)) {
- log_info(LD_REND,"We already have this service descriptor %s.",
- safe_str_client(query));
- e->received = time(NULL);
- rend_service_descriptor_free(parsed);
- return 0;
- }
- if (!e) {
- e = tor_malloc_zero(sizeof(rend_cache_entry_t));
- strmap_set_lc(rend_cache, key, e);
- } else {
- rend_service_descriptor_free(e->parsed);
- tor_free(e->desc);
- }
- e->received = time(NULL);
- e->parsed = parsed;
- e->len = desc_len;
- e->desc = tor_malloc(desc_len);
- memcpy(e->desc, desc, desc_len);
-
- log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
- safe_str_client(query), (int)desc_len);
- return 1;
-}
-
/** Parse the v2 service descriptor(s) in <b>desc</b> and store it/them to the
* local rend cache. Don't attempt to decrypt the included list of introduction
* points (as we don't have a descriptor cookie for it).
*
* If we have a newer descriptor with the same ID, ignore this one.
* If we have an older descriptor with the same ID, replace it.
- * Return -2 if we are not acting as hidden service directory;
- * return -1 if the descriptor(s) were not parsable; return 0 if all
- * descriptors are the same or older than those we've already got;
- * return a positive number for the number of novel stored descriptors.
+ *
+ * Return an appropriate rend_cache_store_status_t.
*/
-int
+rend_cache_store_status_t
rend_cache_store_v2_desc_as_dir(const char *desc)
{
rend_service_descriptor_t *parsed;
@@ -1149,7 +941,7 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
/* Cannot store descs, because we are (currently) not acting as
* hidden service directory. */
log_info(LD_REND, "Cannot store descs: Not acting as hs dir");
- return -2;
+ return RCS_NOTDIR;
}
while (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
&intro_size, &encoded_size,
@@ -1225,11 +1017,11 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
}
if (!number_parsed) {
log_info(LD_REND, "Could not parse any descriptor.");
- return -1;
+ return RCS_BADDESC;
}
log_info(LD_REND, "Parsed %d and added %d descriptor%s.",
number_parsed, number_stored, number_stored != 1 ? "s" : "");
- return number_stored;
+ return RCS_OKAY;
}
/** Parse the v2 service descriptor in <b>desc</b>, decrypt the included list
@@ -1239,15 +1031,12 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
*
* If we have a newer v2 descriptor with the same ID, ignore this one.
* If we have an older descriptor with the same ID, replace it.
- * If we have any v0 descriptor with the same ID, reject this one in order
- * to not get confused with having both versions for the same service.
* If the descriptor's service ID does not match
* <b>rend_query</b>-\>onion_address, reject it.
- * Return -2 if it's malformed or otherwise rejected; return -1 if we
- * already have a v0 descriptor here; return 0 if it's the same or older
- * than one we've already got; return 1 if it's novel.
+ *
+ * Return an appropriate rend_cache_store_status_t.
*/
-int
+rend_cache_store_status_t
rend_cache_store_v2_desc_as_client(const char *desc,
const rend_data_t *rend_query)
{
@@ -1276,7 +1065,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
char key[REND_SERVICE_ID_LEN_BASE32+2];
char service_id[REND_SERVICE_ID_LEN_BASE32+1];
rend_cache_entry_t *e;
- int retval;
+ rend_cache_store_status_t retval = RCS_BADDESC;
tor_assert(rend_cache);
tor_assert(desc);
/* Parse the descriptor. */
@@ -1284,20 +1073,17 @@ rend_cache_store_v2_desc_as_client(const char *desc,
&intro_size, &encoded_size,
&next_desc, desc) < 0) {
log_warn(LD_REND, "Could not parse descriptor.");
- retval = -2;
goto err;
}
/* Compute service ID from public key. */
if (rend_get_service_id(parsed->pk, service_id)<0) {
log_warn(LD_REND, "Couldn't compute service ID.");
- retval = -2;
goto err;
}
if (strcmp(rend_query->onion_address, service_id)) {
log_warn(LD_REND, "Received service descriptor for service ID %s; "
"expected descriptor for service ID %s.",
service_id, safe_str(rend_query->onion_address));
- retval = -2;
goto err;
}
/* Decode/decrypt introduction points. */
@@ -1329,7 +1115,6 @@ rend_cache_store_v2_desc_as_client(const char *desc,
log_warn(LD_REND, "Failed to parse introduction points. Either the "
"service has published a corrupt descriptor or you have "
"provided invalid authorization data.");
- retval = -2;
goto err;
} else if (n_intro_points > MAX_INTRO_POINTS) {
log_warn(LD_REND, "Found too many introduction points on a hidden "
@@ -1337,7 +1122,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
"attempt to improve reliability, but it could also be an "
"attempt to do a guard enumeration attack. Rejecting.",
safe_str_client(rend_query->onion_address));
- retval = -2;
+
goto err;
}
} else {
@@ -1350,22 +1135,12 @@ rend_cache_store_v2_desc_as_client(const char *desc,
if (parsed->timestamp < now - REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
log_warn(LD_REND, "Service descriptor with service ID %s is too old.",
safe_str_client(service_id));
- retval = -2;
goto err;
}
/* Is descriptor too far in the future? */
if (parsed->timestamp > now + REND_CACHE_MAX_SKEW) {
log_warn(LD_REND, "Service descriptor with service ID %s is too far in "
"the future.", safe_str_client(service_id));
- retval = -2;
- goto err;
- }
- /* Do we have a v0 descriptor? */
- tor_snprintf(key, sizeof(key), "0%s", service_id);
- if (strmap_get_lc(rend_cache, key)) {
- log_info(LD_REND, "We already have a v0 descriptor for service ID %s.",
- safe_str_client(service_id));
- retval = -1;
goto err;
}
/* Do we already have a newer descriptor? */
@@ -1375,16 +1150,14 @@ rend_cache_store_v2_desc_as_client(const char *desc,
log_info(LD_REND, "We already have a newer service descriptor for "
"service ID %s with the same desc ID and version.",
safe_str_client(service_id));
- retval = 0;
- goto err;
+ goto okay;
}
/* Do we already have this descriptor? */
if (e && !strcmp(desc, e->desc)) {
log_info(LD_REND,"We already have this service descriptor %s.",
safe_str_client(service_id));
e->received = time(NULL);
- retval = 0;
- goto err;
+ goto okay;
}
if (!e) {
e = tor_malloc_zero(sizeof(rend_cache_entry_t));
@@ -1400,7 +1173,10 @@ rend_cache_store_v2_desc_as_client(const char *desc,
e->len = encoded_size;
log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
safe_str_client(service_id), (int)encoded_size);
- return 1;
+ return RCS_OKAY;
+
+ okay:
+ retval = RCS_OKAY;
err:
rend_service_descriptor_free(parsed);
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index f476593d2..07a47accf 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -26,8 +26,6 @@ void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
const uint8_t *payload);
void rend_service_descriptor_free(rend_service_descriptor_t *desc);
-rend_service_descriptor_t *rend_parse_service_descriptor(const char *str,
- size_t len);
int rend_get_service_id(crypto_pk_t *pk, char *out);
void rend_encoded_v2_service_descriptor_free(
rend_encoded_v2_service_descriptor_t *desc);
@@ -39,16 +37,20 @@ void rend_cache_clean_v2_descs_as_dir(time_t now);
void rend_cache_purge(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_desc_as_dir(const char *query, const char **desc);
-int rend_cache_store(const char *desc, size_t desc_len, int published,
- const char *service_id);
-int rend_cache_store_v2_desc_as_client(const char *desc,
+/** Return value from rend_cache_store_v2_desc_as_{dir,client}. */
+typedef enum {
+ RCS_NOTDIR = -2, /**< We're not a directory */
+ RCS_BADDESC = -1, /**< This descriptor is no good. */
+ RCS_OKAY = 0 /**< All worked as expected */
+} rend_cache_store_status_t;
+
+rend_cache_store_status_t rend_cache_store_v2_desc_as_dir(const char *desc);
+rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc,
const rend_data_t *rend_query);
-int rend_cache_store_v2_desc_as_dir(const char *desc);
+
int rend_encode_v2_descriptors(smartlist_t *descs_out,
rend_service_descriptor_t *desc, time_t now,
uint8_t period, rend_auth_type_t auth_type,