Drop version 0 hidserv support on service side.

This commit is contained in:
Karsten Loesing
2009-05-02 23:31:58 +02:00
committed by Nick Mathewson
parent 4ebcc4da34
commit 0d68da2381
3 changed files with 39 additions and 258 deletions
-55
View File
@@ -655,61 +655,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, *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.
+27 -128
View File
@@ -42,8 +42,6 @@ typedef struct rend_service_t {
/* Fields specified in config file */
char *directory; /**< where in the filesystem it stores it */
smartlist_t *ports; /**< List of rend_service_port_config_t */
int descriptor_version; /**< Rendezvous descriptor version that will be
* published. */
rend_auth_type_t auth_type; /**< Client authorization type or 0 if no client
* authorization is performed. */
smartlist_t *clients; /**< List of rend_authorized_client_t's of
@@ -156,36 +154,6 @@ rend_add_service(rend_service_t *service)
service->intro_nodes = smartlist_create();
/* If the service is configured to publish unversioned (v0) and versioned
* descriptors (v2 or higher), split it up into two separate services
* (unless it is configured to perform client authorization). */
if (service->descriptor_version == -1) {
if (service->auth_type == REND_NO_AUTH) {
rend_service_t *v0_service = tor_malloc_zero(sizeof(rend_service_t));
v0_service->directory = tor_strdup(service->directory);
v0_service->ports = smartlist_create();
SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p, {
rend_service_port_config_t *copy =
tor_malloc_zero(sizeof(rend_service_port_config_t));
memcpy(copy, p, sizeof(rend_service_port_config_t));
smartlist_add(v0_service->ports, copy);
});
v0_service->intro_period_started = service->intro_period_started;
v0_service->descriptor_version = 0; /* Unversioned descriptor. */
v0_service->auth_type = REND_NO_AUTH;
rend_add_service(v0_service);
}
service->descriptor_version = 2; /* Versioned descriptor. */
}
if (service->auth_type != REND_NO_AUTH && !service->descriptor_version) {
log_warn(LD_CONFIG, "Hidden service with client authorization and "
"version 0 descriptors configured; ignoring.");
rend_service_free(service);
return;
}
if (service->auth_type != REND_NO_AUTH &&
smartlist_len(service->clients) == 0) {
log_warn(LD_CONFIG, "Hidden service with client authorization but no "
@@ -307,7 +275,6 @@ rend_config_services(or_options_t *options, int validate_only)
service->directory = tor_strdup(line->value);
service->ports = smartlist_create();
service->intro_period_started = time(NULL);
service->descriptor_version = -1; /**< All descriptor versions. */
continue;
}
if (!service) {
@@ -433,35 +400,13 @@ rend_config_services(or_options_t *options, int validate_only)
return -1;
}
} else {
smartlist_t *versions;
char *version_str;
int i, version, ver_ok=1, versions_bitmask = 0;
tor_assert(!strcasecmp(line->key, "HiddenServiceVersion"));
versions = smartlist_create();
smartlist_split_string(versions, line->value, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
for (i = 0; i < smartlist_len(versions); i++) {
version_str = smartlist_get(versions, i);
if (strlen(version_str) != 1 || strspn(version_str, "02") != 1) {
log_warn(LD_CONFIG,
"HiddenServiceVersion can only be 0 and/or 2.");
SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
smartlist_free(versions);
rend_service_free(service);
return -1;
}
version = (int)tor_parse_long(version_str, 10, 0, INT_MAX, &ver_ok,
NULL);
if (!ver_ok)
continue;
versions_bitmask |= 1 << version;
if (strcmp(line->value, "2")) {
log_warn(LD_CONFIG,
"The only supported HiddenServiceVersion is 2.");
rend_service_free(service);
return -1;
}
/* If exactly one version is set, change descriptor_version to that
* value; otherwise leave it at -1. */
if (versions_bitmask == 1 << 0) service->descriptor_version = 0;
if (versions_bitmask == 1 << 2) service->descriptor_version = 2;
SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
smartlist_free(versions);
}
}
if (service) {
@@ -483,8 +428,7 @@ rend_config_services(or_options_t *options, int validate_only)
* probably ok? */
SMARTLIST_FOREACH(rend_service_list, rend_service_t *, new, {
SMARTLIST_FOREACH(old_service_list, rend_service_t *, old, {
if (!strcmp(old->directory, new->directory) &&
old->descriptor_version == new->descriptor_version) {
if (!strcmp(old->directory, new->directory)) {
smartlist_add_all(new->intro_nodes, old->intro_nodes);
smartlist_clear(old->intro_nodes);
smartlist_add(surviving_services, old);
@@ -507,8 +451,7 @@ rend_config_services(or_options_t *options, int validate_only)
tor_assert(oc->rend_data);
SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
if (!memcmp(ptr->pk_digest, oc->rend_data->rend_pk_digest,
DIGEST_LEN) &&
ptr->descriptor_version == oc->rend_data->rend_desc_version) {
DIGEST_LEN)) {
keep_it = 1;
break;
}
@@ -548,7 +491,6 @@ rend_service_update_descriptor(rend_service_t *service)
d = service->desc = tor_malloc_zero(sizeof(rend_service_descriptor_t));
d->pk = crypto_pk_dup_key(service->private_key);
d->timestamp = time(NULL);
d->version = service->descriptor_version;
d->intro_nodes = smartlist_create();
/* Support intro protocols 2 and 3. */
d->protocols = (1 << 2) + (1 << 3);
@@ -798,16 +740,18 @@ rend_service_load_keys(void)
}
/** Return the service whose public key has a digest of <b>digest</b> and
* which publishes the given descriptor <b>version</b>. Return NULL if no
* such service exists.
* which publishes the given descriptor <b>version</b>. (There is no other
* version than 2, so version is ignored.) Return NULL if no such service
* exists.
*/
static rend_service_t *
rend_service_get_by_pk_digest_and_version(const char* digest,
uint8_t version)
{
(void) version;
SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
if (!memcmp(s->pk_digest,digest,DIGEST_LEN) &&
s->descriptor_version == version) return s);
if (!memcmp(s->pk_digest,digest,DIGEST_LEN))
return s);
return NULL;
}
@@ -953,12 +897,8 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
return -1;
}
/* if descriptor version is 2, use intro key instead of service key. */
if (circuit->rend_data->rend_desc_version == 0) {
intro_key = service->private_key;
} else {
intro_key = circuit->intro_key;
}
/* use intro key instead of service key. */
intro_key = circuit->intro_key;
/* first DIGEST_LEN bytes of request is intro or service pk digest */
crypto_pk_get_digest(intro_key, intro_key_digest);
@@ -1201,7 +1141,6 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
memcpy(launched->rend_data->rend_cookie, r_cookie, REND_COOKIE_LEN);
strlcpy(launched->rend_data->onion_address, service->service_id,
sizeof(launched->rend_data->onion_address));
launched->rend_data->rend_desc_version = service->descriptor_version;
launched->build_state->pending_final_cpath = cpath =
tor_malloc_zero(sizeof(crypt_path_t));
cpath->magic = CRYPT_PATH_MAGIC;
@@ -1323,9 +1262,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
strlcpy(launched->rend_data->onion_address, service->service_id,
sizeof(launched->rend_data->onion_address));
memcpy(launched->rend_data->rend_pk_digest, service->pk_digest, DIGEST_LEN);
launched->rend_data->rend_desc_version = service->descriptor_version;
if (service->descriptor_version == 2)
launched->intro_key = crypto_pk_dup_key(intro->intro_key);
launched->intro_key = crypto_pk_dup_key(intro->intro_key);
if (launched->_base.state == CIRCUIT_STATE_OPEN)
rend_service_intro_has_opened(launched);
return 0;
@@ -1401,13 +1338,8 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
"Established circuit %d as introduction point for service %s",
circuit->_base.n_circ_id, serviceid);
/* If the introduction point will not be used in an unversioned
* descriptor, use the intro key instead of the service key in
* ESTABLISH_INTRO. */
if (service->descriptor_version == 0)
intro_key = service->private_key;
else
intro_key = circuit->intro_key;
/* Use the intro key instead of the service key in ESTABLISH_INTRO. */
intro_key = circuit->intro_key;
/* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
r = crypto_pk_asn1_encode(intro_key, buf+2,
RELAY_PAYLOAD_SIZE-2);
@@ -1695,9 +1627,8 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
smartlist_free(successful_uploads);
}
/** Encode and sign up-to-date v0 and/or v2 service descriptors for
* <b>service</b>, and upload it/them to all the dirservers/to the
* responsible hidden service directories.
/** Encode and sign an up-to-date service descriptor for <b>service</b>,
* and upload it/them to the responsible hidden service directories.
*/
static void
upload_service_descriptor(rend_service_t *service)
@@ -1709,35 +1640,8 @@ upload_service_descriptor(rend_service_t *service)
rendpostperiod = get_options()->RendPostPeriod;
/* Upload unversioned (v0) descriptor? */
if (service->descriptor_version == 0 &&
get_options()->PublishHidServDescriptors) {
char *desc;
size_t desc_len;
/* Encode the descriptor. */
if (rend_encode_service_descriptor(service->desc,
service->private_key,
&desc, &desc_len)<0) {
log_warn(LD_BUG, "Internal error: couldn't encode service descriptor; "
"not uploading.");
return;
}
/* Post it to the dirservers */
rend_get_service_id(service->desc->pk, serviceid);
log_info(LD_REND, "Sending publish request for hidden service %s",
serviceid);
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC,
ROUTER_PURPOSE_GENERAL,
HIDSERV_AUTHORITY, desc, desc_len, 0);
tor_free(desc);
service->next_upload_time = now + rendpostperiod;
uploaded = 1;
}
/* Upload v2 descriptor? */
if (service->descriptor_version == 2 &&
get_options()->PublishHidServDescriptors) {
/* Upload descriptor? */
if (get_options()->PublishHidServDescriptors) {
networkstatus_t *c = networkstatus_get_latest_consensus();
if (c && smartlist_len(c->routerstatus_list) > 0) {
int seconds_valid, i, j, num_descs;
@@ -1876,8 +1780,7 @@ rend_services_introduce(void)
for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
intro = smartlist_get(service->intro_nodes, j);
router = router_get_by_digest(intro->extend_info->identity_digest);
if (!router || !find_intro_circuit(intro, service->pk_digest,
service->descriptor_version)) {
if (!router || !find_intro_circuit(intro, service->pk_digest, -1)) {
log_info(LD_REND,"Giving up on %s as intro point for %s.",
intro->extend_info->nickname, service->service_id);
if (service->desc) {
@@ -1941,10 +1844,8 @@ rend_services_introduce(void)
smartlist_add(intro_routers, router);
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
intro->extend_info = extend_info_from_router(router);
if (service->descriptor_version == 2) {
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
}
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
smartlist_add(service->intro_nodes, intro);
log_info(LD_REND, "Picked router %s as an intro point for %s.",
router->nickname, service->service_id);
@@ -2037,8 +1938,7 @@ rend_consider_descriptor_republication(void)
for (i=0; i < smartlist_len(rend_service_list); ++i) {
service = smartlist_get(rend_service_list, i);
if (service->descriptor_version && service->desc &&
!service->desc->all_uploads_performed) {
if (service->desc && !service->desc->all_uploads_performed) {
/* If we failed in uploading a descriptor last time, try again *without*
* updating the descriptor's contents. */
upload_service_descriptor(service);
@@ -2066,8 +1966,7 @@ rend_service_dump_stats(int severity)
intro = smartlist_get(service->intro_nodes, j);
safe_name = safe_str(intro->extend_info->nickname);
circ = find_intro_circuit(intro, service->pk_digest,
service->descriptor_version);
circ = find_intro_circuit(intro, service->pk_digest, -1);
if (!circ) {
log(severity, LD_GENERAL, " Intro point %d at %s: no circuit",
j, safe_name);
+12 -75
View File
@@ -4000,78 +4000,6 @@ test_policies(void)
}
}
/** Run unit tests for basic rendezvous functions. */
static void
test_rend_fns(void)
{
char address1[] = "fooaddress.onion";
char address2[] = "aaaaaaaaaaaaaaaa.onion";
char address3[] = "fooaddress.exit";
char address4[] = "www.torproject.org";
rend_service_descriptor_t *d1 =
tor_malloc_zero(sizeof(rend_service_descriptor_t));
rend_service_descriptor_t *d2 = NULL;
char *encoded = NULL;
size_t len;
time_t now;
int i;
crypto_pk_env_t *pk1 = pk_generate(0), *pk2 = pk_generate(1);
/* Test unversioned (v0) descriptor */
d1->pk = crypto_pk_dup_key(pk1);
now = time(NULL);
d1->timestamp = now;
d1->version = 0;
d1->intro_nodes = smartlist_create();
for (i = 0; i < 3; i++) {
rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t));
intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
crypto_rand(intro->extend_info->identity_digest, DIGEST_LEN);
intro->extend_info->nickname[0] = '$';
base16_encode(intro->extend_info->nickname+1, HEX_DIGEST_LEN+1,
intro->extend_info->identity_digest, DIGEST_LEN);
smartlist_add(d1->intro_nodes, intro);
}
test_assert(! rend_encode_service_descriptor(d1, pk1, &encoded, &len));
d2 = rend_parse_service_descriptor(encoded, len);
test_assert(d2);
test_assert(!crypto_pk_cmp_keys(d1->pk, d2->pk));
test_eq(d2->timestamp, now);
test_eq(d2->version, 0);
test_eq(d2->protocols, 1<<2);
test_eq(smartlist_len(d2->intro_nodes), 3);
for (i = 0; i < 3; i++) {
rend_intro_point_t *intro1 = smartlist_get(d1->intro_nodes, i);
rend_intro_point_t *intro2 = smartlist_get(d2->intro_nodes, i);
test_streq(intro1->extend_info->nickname,
intro2->extend_info->nickname);
}
test_assert(BAD_HOSTNAME == parse_extended_hostname(address1));
test_assert(ONION_HOSTNAME == parse_extended_hostname(address2));
test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3));
test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4));
crypto_free_pk_env(pk1);
crypto_free_pk_env(pk2);
pk1 = pk2 = NULL;
rend_service_descriptor_free(d1);
rend_service_descriptor_free(d2);
d1 = d2 = NULL;
done:
if (pk1)
crypto_free_pk_env(pk1);
if (pk2)
crypto_free_pk_env(pk2);
if (d1)
rend_service_descriptor_free(d1);
if (d2)
rend_service_descriptor_free(d2);
tor_free(encoded);
}
/** Run AES performance benchmarks. */
static void
bench_aes(void)
@@ -4539,9 +4467,9 @@ test_crypto_base32_decode(void)
;
}
/** Test encoding and parsing of v2 rendezvous service descriptors. */
/** Test encoding and parsing of rendezvous service descriptors. */
static void
test_rend_fns_v2(void)
test_rend_fns(void)
{
rend_service_descriptor_t *generated = NULL, *parsed = NULL;
char service_id[DIGEST_LEN];
@@ -4556,6 +4484,16 @@ test_rend_fns_v2(void)
size_t intro_points_size;
size_t encoded_size;
int i;
char address1[] = "fooaddress.onion";
char address2[] = "aaaaaaaaaaaaaaaa.onion";
char address3[] = "fooaddress.exit";
char address4[] = "www.torproject.org";
test_assert(BAD_HOSTNAME == parse_extended_hostname(address1));
test_assert(ONION_HOSTNAME == parse_extended_hostname(address2));
test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3));
test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4));
pk1 = pk_generate(0);
pk2 = pk_generate(1);
generated = tor_malloc_zero(sizeof(rend_service_descriptor_t));
@@ -4760,7 +4698,6 @@ static struct {
ENT(v3_networkstatus),
ENT(policies),
ENT(rend_fns),
SUBENT(rend_fns, v2),
ENT(geoip),
DISABLED(bench_aes),