mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
r13936@catbus: nickm | 2007-07-27 12:23:26 -0400
Code to implement detached signature documents. svn:r10944
This commit is contained in:
parent
35561a542c
commit
a65cea38d2
149
src/or/dirvote.c
149
src/or/dirvote.c
@ -754,32 +754,21 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus)
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
int
|
||||
networkstatus_add_consensus_signatures(networkstatus_vote_t *target,
|
||||
networkstatus_vote_t *src,
|
||||
char **new_signatures_out)
|
||||
static int
|
||||
networkstatus_add_signatures_impl(networkstatus_vote_t *target,
|
||||
smartlist_t *src_voter_list,
|
||||
char **new_signatures_out)
|
||||
{
|
||||
smartlist_t *added_signatures, *sigs;
|
||||
int r;
|
||||
tor_assert(target);
|
||||
tor_assert(src);
|
||||
tor_assert(! target->is_vote);
|
||||
tor_assert(! src->is_vote);
|
||||
tor_assert(!target->is_vote);
|
||||
tor_assert(new_signatures_out);
|
||||
|
||||
*new_signatures_out = NULL;
|
||||
|
||||
/* Are they the same consensus? */
|
||||
if (memcmp(target->networkstatus_digest, src->networkstatus_digest,
|
||||
DIGEST_LEN))
|
||||
return -1;
|
||||
if (target == src)
|
||||
return 0;
|
||||
|
||||
added_signatures = smartlist_create();
|
||||
|
||||
/* For each voter in src... */
|
||||
SMARTLIST_FOREACH(src->voters, networkstatus_voter_info_t *, src_voter,
|
||||
SMARTLIST_FOREACH(src_voter_list, networkstatus_voter_info_t *, src_voter,
|
||||
{
|
||||
networkstatus_voter_info_t *target_voter =
|
||||
networkstatus_get_voter_by_id(target, src_voter->identity_digest);
|
||||
@ -793,11 +782,13 @@ networkstatus_add_consensus_signatures(networkstatus_vote_t *target,
|
||||
if (target_voter->good_signature)
|
||||
continue;
|
||||
|
||||
/* If this signature is no good, then skip. */
|
||||
cert = authority_cert_get_by_digests(src_voter->identity_digest,
|
||||
src_voter->signing_key_digest);
|
||||
if (cert) {
|
||||
networkstatus_check_voter_signature(target, src_voter, cert);
|
||||
/* Try checking the signature if we haven't already. */
|
||||
if (!src_voter->good_signature && !src_voter->bad_signature) {
|
||||
cert = authority_cert_get_by_digests(src_voter->identity_digest,
|
||||
src_voter->signing_key_digest);
|
||||
if (cert) {
|
||||
networkstatus_check_voter_signature(target, src_voter, cert);
|
||||
}
|
||||
}
|
||||
/* If this signature is good, then replace and add. */
|
||||
if (src_voter->good_signature || !target_voter->signature) {
|
||||
@ -824,10 +815,10 @@ networkstatus_add_consensus_signatures(networkstatus_vote_t *target,
|
||||
base16_encode(sk, sizeof(sk), v->signing_key_digest, DIGEST_LEN);
|
||||
base16_encode(ik, sizeof(ik), v->identity_digest, DIGEST_LEN);
|
||||
tor_snprintf(buf, sizeof(buf), "directory-signature %s %s\n"
|
||||
"-----BEGIN SIGNATURE-----", ik, sk);
|
||||
"-----BEGIN SIGNATURE-----\n", ik, sk);
|
||||
smartlist_add(sigs, tor_strdup(buf));
|
||||
base64_encode(buf, sizeof(buf), v->signature, v->signature_len);
|
||||
strlcat(buf, "-----END SIGNATURE-----", sizeof(buf));
|
||||
strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf));
|
||||
smartlist_add(sigs, tor_strdup(buf));
|
||||
});
|
||||
|
||||
@ -839,6 +830,116 @@ networkstatus_add_consensus_signatures(networkstatus_vote_t *target,
|
||||
return r;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
int
|
||||
networkstatus_add_consensus_signatures(networkstatus_vote_t *target,
|
||||
networkstatus_vote_t *src,
|
||||
char **new_signatures_out)
|
||||
{
|
||||
tor_assert(src);
|
||||
tor_assert(! src->is_vote);
|
||||
|
||||
*new_signatures_out = NULL;
|
||||
|
||||
/* Are they the same consensus? */
|
||||
if (memcmp(target->networkstatus_digest, src->networkstatus_digest,
|
||||
DIGEST_LEN))
|
||||
return -1;
|
||||
if (target == src)
|
||||
return 0;
|
||||
|
||||
return networkstatus_add_signatures_impl(target, src->voters,
|
||||
new_signatures_out);
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
int
|
||||
networkstatus_add_detached_signatures(networkstatus_vote_t *target,
|
||||
ns_detached_signatures_t *sigs,
|
||||
char **new_signatures_out)
|
||||
{
|
||||
tor_assert(sigs);
|
||||
|
||||
*new_signatures_out = NULL;
|
||||
|
||||
/* Are they the same consensus? */
|
||||
if (memcmp(target->networkstatus_digest, sigs->networkstatus_digest,
|
||||
DIGEST_LEN))
|
||||
return -1;
|
||||
|
||||
return networkstatus_add_signatures_impl(target, sigs->signatures,
|
||||
new_signatures_out);
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
char *
|
||||
networkstatus_get_detached_signatures(networkstatus_vote_t *consensus)
|
||||
{
|
||||
smartlist_t *elements;
|
||||
char buf[4096];
|
||||
char *result = NULL;
|
||||
tor_assert(consensus);
|
||||
tor_assert(! consensus->is_vote);
|
||||
|
||||
elements = smartlist_create();
|
||||
|
||||
{
|
||||
char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
|
||||
vu_buf[ISO_TIME_LEN+1];
|
||||
char d[HEX_DIGEST_LEN+1];
|
||||
|
||||
base16_encode(d, sizeof(d), consensus->networkstatus_digest, DIGEST_LEN);
|
||||
format_iso_time(va_buf, consensus->valid_after);
|
||||
format_iso_time(fu_buf, consensus->fresh_until);
|
||||
format_iso_time(vu_buf, consensus->valid_until);
|
||||
|
||||
tor_snprintf(buf, sizeof(buf),
|
||||
"consensus-digest %s\n"
|
||||
"valid-after %s\n"
|
||||
"fresh-until %s\n"
|
||||
"valid-until %s\n", d, va_buf, fu_buf, vu_buf);
|
||||
smartlist_add(elements, tor_strdup(buf));
|
||||
}
|
||||
|
||||
SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, v,
|
||||
{
|
||||
char sk[HEX_DIGEST_LEN+1];
|
||||
char id[HEX_DIGEST_LEN+1];
|
||||
if (!v->signature || !v->good_signature)
|
||||
continue;
|
||||
base16_encode(sk, sizeof(sk), v->signing_key_digest, DIGEST_LEN);
|
||||
base16_encode(id, sizeof(id), v->identity_digest, DIGEST_LEN);
|
||||
tor_snprintf(buf, sizeof(buf),
|
||||
"directory-signature %s %s\n-----BEGIN SIGNATURE-----\n",
|
||||
id, sk);
|
||||
smartlist_add(elements, tor_strdup(buf));
|
||||
base64_encode(buf, sizeof(buf), v->signature, v->signature_len);
|
||||
strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf));
|
||||
smartlist_add(elements, tor_strdup(buf));
|
||||
});
|
||||
|
||||
result = smartlist_join_strings(elements, "", 0, NULL);
|
||||
|
||||
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
|
||||
smartlist_free(elements);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
void
|
||||
ns_detached_signatures_free(ns_detached_signatures_t *s)
|
||||
{
|
||||
if (s->signatures) {
|
||||
SMARTLIST_FOREACH(s->signatures, networkstatus_voter_info_t *, v,
|
||||
{
|
||||
tor_free(v->signature);
|
||||
tor_free(v);
|
||||
});
|
||||
smartlist_free(s->signatures);
|
||||
}
|
||||
tor_free(s);
|
||||
}
|
||||
|
||||
/* =====
|
||||
* Certificate functions
|
||||
* ===== */
|
||||
|
17
src/or/or.h
17
src/or/or.h
@ -1361,6 +1361,16 @@ typedef struct networkstatus_vote_t {
|
||||
* otherwise just routerstatus_t. */
|
||||
} networkstatus_vote_t;
|
||||
|
||||
/* XXXX020 merge with networkstatus_vote_t ?? */
|
||||
/** DOCDOC */
|
||||
typedef struct ns_detached_signatures_t {
|
||||
time_t valid_after;
|
||||
time_t fresh_until;
|
||||
time_t valid_until;
|
||||
char networkstatus_digest[DIGEST_LEN];
|
||||
smartlist_t *signatures; /* list of networkstatus_voter_info_t */
|
||||
} ns_detached_signatures_t;
|
||||
|
||||
/** Contents of a directory of onion routers. */
|
||||
typedef struct {
|
||||
/** Map from server identity digest to a member of routers. */
|
||||
@ -2796,6 +2806,11 @@ int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus);
|
||||
int networkstatus_add_consensus_signatures(networkstatus_vote_t *target,
|
||||
networkstatus_vote_t *src,
|
||||
char **new_signatures_out);
|
||||
int networkstatus_add_detached_signatures(networkstatus_vote_t *target,
|
||||
ns_detached_signatures_t *sigs,
|
||||
char **new_signatures_out);
|
||||
char *networkstatus_get_detached_signatures(networkstatus_vote_t *consensus);
|
||||
void ns_detached_signatures_free(ns_detached_signatures_t *s);
|
||||
|
||||
/* cert manipulation */
|
||||
void authority_cert_free(authority_cert_t *cert);
|
||||
@ -3505,6 +3520,8 @@ void dump_distinct_digest_count(int severity);
|
||||
networkstatus_t *networkstatus_parse_from_string(const char *s);
|
||||
networkstatus_vote_t *networkstatus_parse_vote_from_string(const char *s,
|
||||
int is_vote);
|
||||
ns_detached_signatures_t *networkstatus_parse_detached_signatures(
|
||||
const char *s, const char *eos);
|
||||
|
||||
authority_cert_t *authority_cert_parse_from_string(const char *s,
|
||||
const char **end_of_string);
|
||||
|
@ -340,6 +340,15 @@ static token_rule_t networkstatus_vote_footer_token_table[] = {
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
static token_rule_t networkstatus_detached_signature_token_table[] = {
|
||||
T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
|
||||
T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
|
||||
T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
|
||||
T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
|
||||
T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
|
||||
END_OF_TABLE
|
||||
};
|
||||
|
||||
#undef T
|
||||
|
||||
/* static function prototypes */
|
||||
@ -2058,8 +2067,7 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote)
|
||||
goto err;
|
||||
v->good_signature = 1;
|
||||
} else {
|
||||
v->signature = tor_memdup(tok->object_body,
|
||||
tok->object_size);
|
||||
v->signature = tor_memdup(tok->object_body, tok->object_size);
|
||||
v->signature_len = tok->object_size;
|
||||
}
|
||||
});
|
||||
@ -2095,6 +2103,97 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote)
|
||||
return ns;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
ns_detached_signatures_t *
|
||||
networkstatus_parse_detached_signatures(const char *s, const char *eos)
|
||||
{
|
||||
/* XXXX020 there is too much duplicate code here. */
|
||||
directory_token_t *tok;
|
||||
|
||||
smartlist_t *tokens = smartlist_create();
|
||||
ns_detached_signatures_t *sigs =
|
||||
tor_malloc_zero(sizeof(ns_detached_signatures_t));
|
||||
|
||||
if (!eos)
|
||||
eos = s + strlen(s);
|
||||
|
||||
if (tokenize_string(s, eos, tokens,
|
||||
networkstatus_detached_signature_token_table)) {
|
||||
log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
|
||||
goto err;
|
||||
}
|
||||
|
||||
tok = find_first_by_keyword(tokens, K_CONSENSUS_DIGEST);
|
||||
if (strlen(tok->args[0]) != HEX_DIGEST_LEN)
|
||||
goto err;
|
||||
if (base16_decode(sigs->networkstatus_digest, DIGEST_LEN,
|
||||
tok->args[0], strlen(tok->args[0])) < 0)
|
||||
goto err;
|
||||
|
||||
tok = find_first_by_keyword(tokens, K_VALID_AFTER);
|
||||
if (parse_iso_time(tok->args[0], &sigs->valid_after))
|
||||
goto err;
|
||||
|
||||
tok = find_first_by_keyword(tokens, K_FRESH_UNTIL);
|
||||
if (parse_iso_time(tok->args[0], &sigs->fresh_until))
|
||||
goto err;
|
||||
|
||||
tok = find_first_by_keyword(tokens, K_VALID_UNTIL);
|
||||
if (parse_iso_time(tok->args[0], &sigs->valid_until))
|
||||
goto err;
|
||||
|
||||
sigs->signatures = smartlist_create();
|
||||
SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
|
||||
{
|
||||
char id_digest[DIGEST_LEN];
|
||||
char sk_digest[DIGEST_LEN];
|
||||
networkstatus_voter_info_t *voter;
|
||||
|
||||
tok = _tok;
|
||||
if (tok->tp != K_DIRECTORY_SIGNATURE)
|
||||
continue;
|
||||
tor_assert(tok->n_args >= 2);
|
||||
|
||||
if (!tok->object_type ||
|
||||
strcmp(tok->object_type, "SIGNATURE") ||
|
||||
tok->object_size < 128 || tok->object_size > 512) {
|
||||
log_warn(LD_DIR, "Bad object type or length on directory-signature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
|
||||
base16_decode(id_digest, sizeof(id_digest),
|
||||
tok->args[0], HEX_DIGEST_LEN) < 0) {
|
||||
log_warn(LD_DIR, "Error decoding declared identity %s in "
|
||||
"network-status vote.", escaped(tok->args[0]));
|
||||
goto err;
|
||||
}
|
||||
if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
|
||||
base16_decode(sk_digest, sizeof(sk_digest),
|
||||
tok->args[1], HEX_DIGEST_LEN) < 0) {
|
||||
log_warn(LD_DIR, "Error decoding declared identity %s in "
|
||||
"network-status vote.", escaped(tok->args[1]));
|
||||
goto err;
|
||||
}
|
||||
|
||||
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
|
||||
memcpy(voter->identity_digest, id_digest, DIGEST_LEN);
|
||||
memcpy(voter->signing_key_digest, sk_digest, DIGEST_LEN);
|
||||
voter->signature = tor_memdup(tok->object_body, tok->object_size);
|
||||
voter->signature_len = tok->object_size;
|
||||
|
||||
smartlist_add(sigs->signatures, voter);
|
||||
});
|
||||
|
||||
goto done;
|
||||
err:
|
||||
ns_detached_signatures_free(sigs);
|
||||
sigs = NULL;
|
||||
done:
|
||||
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Parse the addr policy in the string <b>s</b> and return it. If
|
||||
* assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
|
||||
* ADDR_POLICY_REJECT) for items that specify no action.
|
||||
|
Loading…
Reference in New Issue
Block a user