endif
libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \
- memarea.c util_codedigest.c $(libor_extra_source)
- memarea.c di_ops.c $(libor_extra_source)
++ memarea.c di_ops.c util_codedigest.c $(libor_extra_source)
libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c
- noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h
+libor_event_a_SOURCES = compat_libevent.c
+
++noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h
+
+common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)
+ if test "@SHA1SUM@" != none; then \
+ @SHA1SUM@ $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) | @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > common_sha1.i; \
+ elif test "@OPENSSL@" != none; then \
+ @OPENSSL@ sha1 $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) | @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > common_sha1.i; \
+ else \
+ rm common_sha1.i; \
+ touch common_sha1.i; \
+ fi
-noinst_HEADERS = address.h log.h crypto.h test.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h di_ops.h ciphers.inc
+util_codedigest.o: common_sha1.i
+crypto.o: sha256.c
int
tor_digest_is_zero(const char *digest)
{
- return tor_mem_is_zero(digest, DIGEST_LEN);
+ static const uint8_t ZERO_DIGEST[] = {
+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
+ };
+ return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
}
+/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */
+int
+tor_digest256_is_zero(const char *digest)
+{
+ return tor_mem_is_zero(digest, DIGEST256_LEN);
+}
+
/* Helper: common code to check whether the result of a strtol or strtoul or
* strtoll is correct. */
#define CHECK_STRTOX_RESULT() \
SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
{
if (tor_digest_is_zero(bridge->identity) &&
- tor_addr_eq_ipv4h(&bridge->addr, ri->addr) &&
- bridge->port == ri->or_port)
+ !tor_addr_compare(&bridge->addr, addr, CMP_EXACT) &&
+ bridge->port == port)
return bridge;
- if (!memcmp(bridge->identity, digest, DIGEST_LEN))
- if (tor_memeq(bridge->identity, ri->cache_info.identity_digest,
- DIGEST_LEN))
++ if (tor_memeq(bridge->identity, digest, DIGEST_LEN))
return bridge;
}
SMARTLIST_FOREACH_END(bridge);
continue;
};
- SMARTLIST_FOREACH(v->voters, networkstatus_voter_info_t *, vi, {
- if (vi->signature &&
- fast_memeq(vi->identity_digest, want_digest, want_len)) {
+ SMARTLIST_FOREACH_BEGIN(v->voters, networkstatus_voter_info_t *, vi) {
+ if (smartlist_len(vi->sigs) &&
- !memcmp(vi->identity_digest, want_digest, want_len)) {
++ tor_memeq(vi->identity_digest, want_digest, want_len)) {
have++;
break;
};
tor_assert(address);
tor_assert(digest_rcvd);
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
+ /* XXX023 Doing a loop like this is stupid. We should just look up the
+ * router by digest_rcvd, and see if address, orport, and as_advertised
+ * match up. -NM */
+ SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
if (!strcasecmp(address, ri->address) && or_port == ri->or_port &&
as_advertised &&
- !memcmp(ri->cache_info.identity_digest, digest_rcvd, DIGEST_LEN)) {
+ fast_memeq(ri->cache_info.identity_digest, digest_rcvd, DIGEST_LEN)) {
/* correct digest. mark this router reachable! */
if (!bridge_auth || ri->purpose == ROUTER_PURPOSE_BRIDGE) {
- log_info(LD_DIRSERV, "Found router %s to be reachable. Yay.",
- ri->nickname);
- rep_hist_note_router_reachable(digest_rcvd, now);
+ tor_addr_t addr, *addrp=NULL;
+ log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.",
+ ri->nickname, address, ri->or_port );
+ if (tor_addr_from_str(&addr, ri->address) != -1)
+ addrp = &addr;
+ else
+ log_warn(LD_BUG, "Couldn't parse IP address \"%s\"", ri->address);
+ rep_hist_note_router_reachable(digest_rcvd, addrp, or_port, now);
ri->last_reachable = now;
}
}
/* Figure out the most popular opinion of what the most recent
* routerinfo and its contents are. */
- rs = compute_routerstatus_consensus(matching_descs);
+ memset(microdesc_digest, 0, sizeof(microdesc_digest));
+ rs = compute_routerstatus_consensus(matching_descs, consensus_method,
+ microdesc_digest);
/* Copy bits of that into rs_out. */
- tor_assert(!memcmp(lowest_id, rs->status.identity_digest, DIGEST_LEN));
+ tor_assert(fast_memeq(lowest_id, rs->status.identity_digest, DIGEST_LEN));
memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN);
memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
DIGEST_LEN);
goto err;
}
+ /* Fetch any new router descriptors we just learned about */
+ update_consensus_router_descriptor_downloads(time(NULL), 1, vote);
+
/* Now see whether we already have a vote from this authority. */
SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
- if (! memcmp(v->vote->cert->cache_info.identity_digest,
+ if (fast_memeq(v->vote->cert->cache_info.identity_digest,
vote->cert->cache_info.identity_digest,
DIGEST_LEN)) {
networkstatus_voter_info_t *vi_old = get_voter(v->vote);
- if (!memcmp(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) {
+ if (fast_memeq(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) {
/* Ah, it's the same vote. Not a problem. */
- log_info(LD_DIR, "Discarding a vote we already have.");
+ log_info(LD_DIR, "Discarding a vote we already have (from %s).",
+ vi->address);
if (*status_out < 200)
*status_out = 200;
goto discard;
} else {
if (pending_vote_list && include_pending) {
SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
- if (!memcmp(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
- if (fast_memeq(pv->vote->networkstatus_digest, fp, DIGEST_LEN))
++ if (fast_memeq(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
return pv->vote_body);
}
if (previous_vote_list && include_previous) {
SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
- if (!memcmp(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
- if (fast_memeq(pv->vote->networkstatus_digest, fp, DIGEST_LEN))
++ if (fast_memeq(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
return pv->vote_body);
}
}
return NULL;
}
-/** Check whether the signature on <b>voter</b> is correctly signed by
- * the signing key of <b>cert</b>. Return -1 if <b>cert</b> doesn't match the
+/** Check whether the signature <b>sig</b> is correctly signed with the
+ * signing key in <b>cert</b>. Return -1 if <b>cert</b> doesn't match the
* signing key; otherwise set the good_signature or bad_signature flag on
* <b>voter</b>, and return 0. */
-/* (private; exposed for testing.) */
int
-networkstatus_check_voter_signature(networkstatus_t *consensus,
- networkstatus_voter_info_t *voter,
- authority_cert_t *cert)
+networkstatus_check_document_signature(const networkstatus_t *consensus,
+ document_signature_t *sig,
+ const authority_cert_t *cert)
{
- char d[DIGEST_LEN];
+ char key_digest[DIGEST_LEN];
+ const int dlen = sig->alg == DIGEST_SHA1 ? DIGEST_LEN : DIGEST256_LEN;
char *signed_digest;
size_t signed_digest_len;
- if (crypto_pk_get_digest(cert->signing_key, d)<0)
+
+ if (crypto_pk_get_digest(cert->signing_key, key_digest)<0)
return -1;
- if (memcmp(sig->signing_key_digest, key_digest, DIGEST_LEN) ||
- memcmp(sig->identity_digest, cert->cache_info.identity_digest,
- DIGEST_LEN))
- if (tor_memneq(voter->signing_key_digest, d, DIGEST_LEN))
++ if (tor_memneq(sig->signing_key_digest, key_digest, DIGEST_LEN) ||
++ tor_memneq(sig->identity_digest, cert->cache_info.identity_digest,
++ DIGEST_LEN))
return -1;
+
signed_digest_len = crypto_pk_keysize(cert->signing_key);
signed_digest = tor_malloc(signed_digest_len);
if (crypto_pk_public_checksig(cert->signing_key,
signed_digest,
signed_digest_len,
- voter->signature,
- voter->signature_len) != DIGEST_LEN ||
- tor_memneq(signed_digest, consensus->networkstatus_digest, DIGEST_LEN)) {
+ sig->signature,
+ sig->signature_len) < dlen ||
- memcmp(signed_digest, consensus->digests.d[sig->alg], dlen)) {
++ tor_memneq(signed_digest, consensus->digests.d[sig->alg], dlen)) {
log_warn(LD_DIR, "Got a bad signature on a networkstatus vote");
- voter->bad_signature = 1;
+ sig->bad_signature = 1;
} else {
- voter->good_signature = 1;
+ sig->good_signature = 1;
}
tor_free(signed_digest);
return 0;
goto done;
}
- if (current_consensus &&
- tor_memeq(c->networkstatus_digest, current_consensus->networkstatus_digest,
- DIGEST_LEN)) {
+ if (!strcmp(flavor, "ns")) {
+ consensus_fname = get_datadir_fname("cached-consensus");
+ unverified_fname = get_datadir_fname("unverified-consensus");
+ if (current_consensus) {
+ current_digests = ¤t_consensus->digests;
+ current_valid_after = current_consensus->valid_after;
+ }
+ } else {
+ cached_dir_t *cur;
+ char buf[128];
+ tor_snprintf(buf, sizeof(buf), "cached-%s-consensus", flavor);
+ consensus_fname = get_datadir_fname(buf);
+ tor_snprintf(buf, sizeof(buf), "unverified-%s-consensus", flavor);
+ unverified_fname = get_datadir_fname(buf);
+ cur = dirserv_get_consensus(flavor);
+ if (cur) {
+ current_digests = &cur->digests;
+ current_valid_after = cur->published;
+ }
+ }
+
+ if (current_digests &&
- !memcmp(&c->digests, current_digests, sizeof(c->digests))) {
++ tor_memeq(&c->digests, current_digests, sizeof(c->digests))) {
/* We already have this one. That's a failure. */
- log_info(LD_DIR, "Got a consensus we already have");
+ log_info(LD_DIR, "Got a %s consensus we already have", flavor);
goto done;
}
}
/* first 20 bytes of payload are the hash of Bob's pk */
- if (entry->parsed->version == 0) { /* un-versioned descriptor */
- intro_key = entry->parsed->pk;
- } else { /* versioned descriptor */
- intro_key = NULL;
- SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
- intro, {
- if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest,
- intro->extend_info->identity_digest, DIGEST_LEN)) {
- intro_key = intro->intro_key;
- break;
- }
- });
- if (!intro_key) {
- /** XXX This case probably means that the intro point vanished while
- * we were building a circuit to it. In the future, we should find
- * out how that happened and whether we should kill the circuits to
- * removed intro points immediately. See task 1073. */
- int num_intro_points = smartlist_len(entry->parsed->intro_nodes);
- if (rend_cache_lookup_entry(introcirc->rend_data->onion_address,
- 0, &entry) > 0) {
- log_info(LD_REND, "We have both a v0 and a v2 rend desc for this "
- "service. The v2 desc doesn't contain the introduction "
- "point (and key) to send an INTRODUCE1/2 cell to this "
- "introduction point. Assuming the introduction point "
- "is for v0 rend clients and using the service key "
- "from the v0 desc instead. (This is probably a bug, "
- "because we shouldn't even have both a v0 and a v2 "
- "descriptor for the same service.)");
- /* See flyspray task 1024. */
- intro_key = entry->parsed->pk;
- } else {
- log_info(LD_REND, "Internal error: could not find intro key; we "
- "only have a v2 rend desc with %d intro points.",
- num_intro_points);
- goto perm_err;
- }
+ intro_key = NULL;
+ SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
+ intro, {
- if (!memcmp(introcirc->build_state->chosen_exit->identity_digest,
++ if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest,
+ intro->extend_info->identity_digest, DIGEST_LEN)) {
+ intro_key = intro->intro_key;
+ break;
+ }
+ });
+ if (!intro_key) {
+ log_info(LD_REND, "Could not find intro key for %s at %s; we "
+ "have a v2 rend desc with %d intro points. "
+ "Trying a different intro point...",
+ safe_str_client(introcirc->rend_data->onion_address),
+ introcirc->build_state->chosen_exit->nickname,
+ smartlist_len(entry->parsed->intro_nodes));
+
+ if (rend_client_reextend_intro_circuit(introcirc)) {
+ goto perm_err;
+ } else {
+ return -1;
}
}
if (crypto_pk_get_digest(intro_key, payload)<0) {
rend_service_descriptor_free(parsed);
return 0;
}
- if (e && e->len == desc_len && !memcmp(desc,e->desc,desc_len)) {
+ 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;
int keep_it = 0;
tor_assert(oc->rend_data);
SMARTLIST_FOREACH(surviving_services, rend_service_t *, ptr, {
- if (!memcmp(ptr->pk_digest, oc->rend_data->rend_pk_digest,
+ if (tor_memeq(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;
}
return r;
}
-/** 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.
+/** Return the service whose public key has a digest of <b>digest</b>, or
+ * NULL if no such service exists.
*/
static rend_service_t *
-rend_service_get_by_pk_digest_and_version(const char* digest,
- uint8_t version)
+rend_service_get_by_pk_digest(const char* digest)
{
SMARTLIST_FOREACH(rend_service_list, rend_service_t*, s,
- if (!memcmp(s->pk_digest,digest,DIGEST_LEN))
- if (tor_memeq(s->pk_digest,digest,DIGEST_LEN) &&
- s->descriptor_version == version) return s);
++ if (tor_memeq(s->pk_digest,digest,DIGEST_LEN))
+ return s);
return NULL;
}
tor_assert(intro);
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
CIRCUIT_PURPOSE_S_INTRO))) {
- if (!memcmp(circ->build_state->chosen_exit->identity_digest,
+ if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
intro->extend_info->identity_digest, DIGEST_LEN) &&
- circ->rend_data &&
- circ->rend_data->rend_desc_version == desc_version) {
+ circ->rend_data) {
return circ;
}
}
circ = NULL;
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
- if (!memcmp(circ->build_state->chosen_exit->identity_digest,
+ if (tor_memeq(circ->build_state->chosen_exit->identity_digest,
intro->extend_info->identity_digest, DIGEST_LEN) &&
- circ->rend_data &&
- circ->rend_data->rend_desc_version == desc_version) {
+ circ->rend_data) {
return circ;
}
}
int
router_digest_is_me(const char *digest)
{
- return identitykey && tor_memeq(identitykey_digest, digest, DIGEST_LEN);
+ return (server_identitykey &&
- !memcmp(server_identitykey_digest, digest, DIGEST_LEN));
++ tor_memeq(server_identitykey_digest, digest, DIGEST_LEN));
}
/** Return true iff I'm a server and <b>digest</b> is equal to
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
routerstatus_t *rs =
- networkstatus_v2_find_entry(ns, router->cache_info.identity_digest);
+ networkstatus_v2_find_entry(ns, id_digest);
- if (rs && !memcmp(rs->descriptor_digest,
+ if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN))
rs->need_to_mirror = 0;
});
if (consensus) {
- routerstatus_t *rs = networkstatus_vote_find_entry(consensus,
- router->cache_info.identity_digest);
+ routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest);
- if (rs && !memcmp(rs->descriptor_digest,
+ if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN)) {
in_consensus = 1;
}
// log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
// hex_str(signed_digest,4));
- if (memcmp(digest, signed_digest, digest_len)) {
- if (tor_memneq(digest, signed_digest, DIGEST_LEN)) {
++ if (tor_memneq(digest, signed_digest, digest_len)) {
log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
tor_free(signed_digest);
return -1;
}
/** Helper to sort a smartlist of pointers to routerstatus_t */
-static int
-_compare_routerstatus_entries(const void **_a, const void **_b)
+int
+compare_routerstatus_entries(const void **_a, const void **_b)
{
const routerstatus_t *a = *_a, *b = *_b;
- return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
+ return fast_memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
}
/** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */