aboutsummaryrefslogtreecommitdiff
path: root/src/or/rendcommon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/rendcommon.c')
-rw-r--r--src/or/rendcommon.c162
1 files changed, 62 insertions, 100 deletions
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index 8727a70c2..4d4a90f61 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -9,6 +9,15 @@
**/
#include "or.h"
+#include "circuitbuild.h"
+#include "config.h"
+#include "rendclient.h"
+#include "rendcommon.h"
+#include "rendmid.h"
+#include "rendservice.h"
+#include "rephist.h"
+#include "routerlist.h"
+#include "routerparse.h"
/** Return 0 if one and two are the same service ids, else -1 or 1 */
int
@@ -22,6 +31,8 @@ rend_cmp_service_ids(const char *one, const char *two)
void
rend_service_descriptor_free(rend_service_descriptor_t *desc)
{
+ if (!desc)
+ return;
if (desc->pk)
crypto_free_pk_env(desc->pk);
if (desc->intro_nodes) {
@@ -125,7 +136,8 @@ rend_compute_v2_desc_id(char *desc_id_out, const char *service_id,
if (!service_id ||
strlen(service_id) != REND_SERVICE_ID_LEN_BASE32) {
log_warn(LD_REND, "Could not compute v2 descriptor ID: "
- "Illegal service ID: %s", safe_str(service_id));
+ "Illegal service ID: %s",
+ safe_str(service_id));
return -1;
}
if (replica >= REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS) {
@@ -138,7 +150,7 @@ rend_compute_v2_desc_id(char *desc_id_out, const char *service_id,
service_id, REND_SERVICE_ID_LEN_BASE32) < 0) {
log_warn(LD_REND, "Could not compute v2 descriptor ID: "
"Illegal characters in service ID: %s",
- safe_str(service_id));
+ safe_str_client(service_id));
return -1;
}
/* Calculate current time-period. */
@@ -403,8 +415,7 @@ rend_desc_v2_is_parsable(rend_encoded_v2_service_descriptor_t *desc)
&test_intro_size,
&test_encoded_size,
&test_next, desc->desc_str);
- if (test_parsed)
- rend_service_descriptor_free(test_parsed);
+ rend_service_descriptor_free(test_parsed);
tor_free(test_intro_content);
return (res >= 0);
}
@@ -414,6 +425,8 @@ void
rend_encoded_v2_service_descriptor_free(
rend_encoded_v2_service_descriptor_t *desc)
{
+ if (!desc)
+ return;
tor_free(desc->desc_str);
tor_free(desc);
}
@@ -422,10 +435,11 @@ rend_encoded_v2_service_descriptor_free(
void
rend_intro_point_free(rend_intro_point_t *intro)
{
- if (intro->extend_info)
- extend_info_free(intro->extend_info);
- if (intro->intro_key)
- crypto_free_pk_env(intro->intro_key);
+ if (!intro)
+ return;
+
+ extend_info_free(intro->extend_info);
+ crypto_free_pk_env(intro->intro_key);
tor_free(intro);
}
@@ -618,7 +632,8 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
}
if (router_append_dirobj_signature(desc_str + written,
desc_len - written,
- desc_digest, service_key) < 0) {
+ desc_digest, DIGEST_LEN,
+ service_key) < 0) {
log_warn(LD_BUG, "Couldn't sign desc.");
rend_encoded_v2_service_descriptor_free(enc);
goto err;
@@ -655,63 +670,6 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
return seconds_valid;
}
-/** Encode a service descriptor for <b>desc</b>, and sign it with
- * <b>key</b>. Store the descriptor in *<b>str_out</b>, and set
- * *<b>len_out</b> to its length.
- */
-int
-rend_encode_service_descriptor(rend_service_descriptor_t *desc,
- crypto_pk_env_t *key,
- char **str_out, size_t *len_out)
-{
- char *cp;
- char *end;
- int i, r;
- size_t asn1len;
- size_t buflen =
- PK_BYTES*2*(smartlist_len(desc->intro_nodes)+2);/*Too long, but ok*/
- cp = *str_out = tor_malloc(buflen);
- end = cp + PK_BYTES*2*(smartlist_len(desc->intro_nodes)+1);
- r = crypto_pk_asn1_encode(desc->pk, cp+2, end-(cp+2));
- if (r < 0) {
- tor_free(*str_out);
- return -1;
- }
- asn1len = r;
- set_uint16(cp, htons((uint16_t)asn1len));
- cp += 2+asn1len;
- set_uint32(cp, htonl((uint32_t)desc->timestamp));
- cp += 4;
- set_uint16(cp, htons((uint16_t)smartlist_len(desc->intro_nodes)));
- cp += 2;
- for (i=0; i < smartlist_len(desc->intro_nodes); ++i) {
- rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i);
- char ipoint[HEX_DIGEST_LEN+2];
- const size_t ipoint_len = HEX_DIGEST_LEN+1;
- ipoint[0] = '$';
- base16_encode(ipoint+1, HEX_DIGEST_LEN+1,
- intro->extend_info->identity_digest,
- DIGEST_LEN);
- tor_assert(strlen(ipoint) == ipoint_len);
- /* Assert that appending ipoint and its NUL won't over overrun the
- * buffer. */
- tor_assert(cp + ipoint_len+1 < *str_out + buflen);
- memcpy(cp, ipoint, ipoint_len+1);
- cp += ipoint_len+1;
- }
- note_crypto_pk_op(REND_SERVER);
- r = crypto_pk_private_sign_digest(key,
- cp, buflen - (cp - *str_out),
- *str_out, cp-*str_out);
- if (r<0) {
- tor_free(*str_out);
- return -1;
- }
- cp += r;
- *len_out = (size_t)(cp-*str_out);
- return 0;
-}
-
/** 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.
@@ -828,22 +786,27 @@ rend_cache_init(void)
/** Helper: free storage held by a single service descriptor cache entry. */
static void
-_rend_cache_entry_free(void *p)
+rend_cache_entry_free(rend_cache_entry_t *e)
{
- rend_cache_entry_t *e = p;
+ if (!e)
+ return;
rend_service_descriptor_free(e->parsed);
tor_free(e->desc);
tor_free(e);
}
+static void
+_rend_cache_entry_free(void *p)
+{
+ rend_cache_entry_free(p);
+}
+
/** Free all storage held by the service descriptor cache. */
void
rend_cache_free_all(void)
{
- if (rend_cache)
- strmap_free(rend_cache, _rend_cache_entry_free);
- if (rend_cache_v2_dir)
- digestmap_free(rend_cache_v2_dir, _rend_cache_entry_free);
+ strmap_free(rend_cache, _rend_cache_entry_free);
+ digestmap_free(rend_cache_v2_dir, _rend_cache_entry_free);
rend_cache = NULL;
rend_cache_v2_dir = NULL;
}
@@ -864,7 +827,7 @@ rend_cache_clean(void)
ent = (rend_cache_entry_t*)val;
if (ent->parsed->timestamp < cutoff) {
iter = strmap_iter_next_rmv(rend_cache, iter);
- _rend_cache_entry_free(ent);
+ rend_cache_entry_free(ent);
} else {
iter = strmap_iter_next(rend_cache, iter);
}
@@ -900,9 +863,9 @@ rend_cache_clean_v2_descs_as_dir(void)
char key_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
base32_encode(key_base32, sizeof(key_base32), key, DIGEST_LEN);
log_info(LD_REND, "Removing descriptor with ID '%s' from cache",
- safe_str(key_base32));
+ safe_str_client(key_base32));
iter = digestmap_iter_next_rmv(rend_cache_v2_dir, iter);
- _rend_cache_entry_free(ent);
+ rend_cache_entry_free(ent);
} else {
iter = digestmap_iter_next(rend_cache_v2_dir, iter);
}
@@ -978,6 +941,11 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
}
if (!*e)
return 0;
+ tor_assert((*e)->parsed && (*e)->parsed->intro_nodes);
+ /* XXX023 hack for now, to return "not found" if there are no intro
+ * points remaining. See bug 997. */
+ if (! rend_client_any_intro_points_usable(*e))
+ return 0;
return 1;
}
@@ -1061,7 +1029,6 @@ rend_cache_store(const char *desc, size_t desc_len, int published,
char query[REND_SERVICE_ID_LEN_BASE32+1];
char key[REND_SERVICE_ID_LEN_BASE32+2]; /* 0<query>\0 */
time_t now;
- or_options_t *options = get_options();
tor_assert(rend_cache);
parsed = rend_parse_service_descriptor(desc,desc_len);
if (!parsed) {
@@ -1082,13 +1049,15 @@ rend_cache_store(const char *desc, size_t desc_len, int published,
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(query));
+ "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(query));
+ "Service descriptor %s is too far in the future.",
+ safe_str_client(query));
rend_service_descriptor_free(parsed);
return -2;
}
@@ -1096,25 +1065,22 @@ rend_cache_store(const char *desc, size_t desc_len, int published,
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(query));
+ safe_str_client(query));
rend_service_descriptor_free(parsed);
return -1;
}
- /* report novel publication to statistics */
- if (published && options->HSAuthorityRecordStats) {
- hs_usage_note_publish_total(query, now);
- }
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(query));
+ "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(query));
+ safe_str_client(query));
e->received = time(NULL);
rend_service_descriptor_free(parsed);
return 0;
@@ -1122,10 +1088,6 @@ rend_cache_store(const char *desc, size_t desc_len, int published,
if (!e) {
e = tor_malloc_zero(sizeof(rend_cache_entry_t));
strmap_set_lc(rend_cache, key, e);
- /* report novel publication to statistics */
- if (published && options->HSAuthorityRecordStats) {
- hs_usage_note_publish_novel(query, now);
- }
} else {
rend_service_descriptor_free(e->parsed);
tor_free(e->desc);
@@ -1137,7 +1099,7 @@ rend_cache_store(const char *desc, size_t desc_len, int published,
memcpy(e->desc, desc, desc_len);
log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
- safe_str(query), (int)desc_len);
+ safe_str_client(query), (int)desc_len);
return 1;
}
@@ -1188,7 +1150,7 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
if (!hid_serv_responsible_for_desc_id(desc_id)) {
log_info(LD_REND, "Service descriptor with desc ID %s is not in "
"interval that we are responsible for.",
- safe_str(desc_id_base32));
+ safe_str_client(desc_id_base32));
goto skip;
}
/* Is descriptor too old? */
@@ -1326,7 +1288,8 @@ rend_cache_store_v2_desc_as_client(const char *desc,
/* Decode/decrypt introduction points. */
if (intro_content) {
if (rend_query->auth_type != REND_NO_AUTH &&
- rend_query->descriptor_cookie) {
+ !tor_mem_is_zero(rend_query->descriptor_cookie,
+ sizeof(rend_query->descriptor_cookie))) {
char *ipos_decrypted = NULL;
size_t ipos_decrypted_size;
if (rend_decrypt_introduction_points(&ipos_decrypted,
@@ -1361,14 +1324,14 @@ rend_cache_store_v2_desc_as_client(const char *desc,
/* Is descriptor too old? */
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(service_id));
+ 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(service_id));
+ "the future.", safe_str_client(service_id));
retval = -2;
goto err;
}
@@ -1376,7 +1339,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
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(service_id));
+ safe_str_client(service_id));
retval = -1;
goto err;
}
@@ -1386,14 +1349,14 @@ rend_cache_store_v2_desc_as_client(const char *desc,
if (e && e->parsed->timestamp > parsed->timestamp) {
log_info(LD_REND, "We already have a newer service descriptor for "
"service ID %s with the same desc ID and version.",
- safe_str(service_id));
+ safe_str_client(service_id));
retval = 0;
goto err;
}
/* 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(service_id));
+ safe_str_client(service_id));
e->received = time(NULL);
retval = 0;
goto err;
@@ -1411,12 +1374,11 @@ rend_cache_store_v2_desc_as_client(const char *desc,
strlcpy(e->desc, desc, encoded_size + 1);
e->len = encoded_size;
log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
- safe_str(service_id), (int)encoded_size);
+ safe_str_client(service_id), (int)encoded_size);
return 1;
err:
- if (parsed)
- rend_service_descriptor_free(parsed);
+ rend_service_descriptor_free(parsed);
tor_free(intro_content);
return retval;
}