mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
r12898@catbus: nickm | 2007-05-22 13:11:04 -0400
More v3 directory code: have authorities load certificates; have everybody store certificates to disk and load them; provide a way to configure v3 authorities. svn:r10293
This commit is contained in:
parent
6975a093e9
commit
c9fa4e6583
19
doc/TODO
19
doc/TODO
@ -56,7 +56,7 @@ N . Document transport and natdport
|
||||
|
||||
Things we'd like to do in 0.2.0.x:
|
||||
- Proposals:
|
||||
. 101: Voting on the Tor Directory System
|
||||
. 101: Voting on the Tor Directory System (plus 103)
|
||||
o Prepare ASAP for new voting formats
|
||||
o Don't flip out with warnings when voting-related URLs are
|
||||
uploaded/downloaded.
|
||||
@ -68,16 +68,21 @@ Things we'd like to do in 0.2.0.x:
|
||||
o Parse key certificates
|
||||
- Parse votes and consensuses
|
||||
- Unit tests for above
|
||||
- Code to manage key certificates
|
||||
- Cache on disk
|
||||
- Download as needed
|
||||
. Code to manage key certificates
|
||||
o Generate certificates
|
||||
o Authorities load certificates
|
||||
o Clients cache certificates on disk
|
||||
- Download as needed.
|
||||
- Serve list as needed.
|
||||
- Avoid double-checking signatures every time we get a vote.
|
||||
o Avoid double-checking signatures every time we get a vote.
|
||||
- Warn about expired stuff.
|
||||
- Code to generate votes
|
||||
- Code to generate consensus from a list of votes
|
||||
- Add a signature to a consensus.
|
||||
- Code to check signatures on a consensus
|
||||
- Push/pull documents as appropriate.
|
||||
o Have clients know which authorities are v3 authorities, and what
|
||||
their keys are.
|
||||
- Start caching consensus documents once authorities make them
|
||||
- Start downloading and using consensus documents once caches serve them
|
||||
. 104: Long and Short Router Descriptors (by Jun 1)
|
||||
@ -98,8 +103,8 @@ Things we'd like to do in 0.2.0.x:
|
||||
- 105: Version negotiation for the Tor protocol (finalize by Jun 1)
|
||||
- 108: Base "Stable" Flag on Mean Time Between Failures
|
||||
- 109: No more than one server per IP address
|
||||
- 103: Splitting identity key from regularly used signing key
|
||||
- Merge with 101 into a new dir-spec.txt
|
||||
o 103: Splitting identity key from regularly used signing key
|
||||
o Merge with 101 into a new dir-spec.txt
|
||||
- 113: Simplifying directory authority administration
|
||||
- 110: prevent infinite-length circuits (phase one)
|
||||
- servers should recognize relay_extend cells and pass them
|
||||
|
@ -1381,8 +1381,8 @@ append_bytes_to_file(const char *fname, const char *str, size_t len,
|
||||
/** Read the contents of <b>filename</b> into a newly allocated
|
||||
* string; return the string on success or NULL on failure.
|
||||
*
|
||||
* If <b>size_out</b> is provided, store the length of the result in
|
||||
* <b>size_out</b>.
|
||||
* If <b>stat_out</b> is provided, store the result of stat()ing the
|
||||
* file into <b>stat_out</b>.
|
||||
*
|
||||
* If <b>flags</b> & RFTS_BIN, open the file in binary mode.
|
||||
* If <b>flags</b> & RFTS_IGNORE_MISSING, don't warn if the file
|
||||
|
@ -261,6 +261,7 @@ static config_var_t _option_vars[] = {
|
||||
VAR("User", STRING, User, NULL),
|
||||
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
|
||||
VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"),
|
||||
VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
|
||||
VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
|
||||
VAR("VirtualAddrNetwork", STRING, VirtualAddrNetwork, "127.192.0.0/10"),
|
||||
VAR("__AllDirActionsPrivate",BOOL, AllDirActionsPrivate, "0"),
|
||||
@ -1047,6 +1048,7 @@ options_act(or_options_t *old_options)
|
||||
if (dns_reset())
|
||||
return -1;
|
||||
}
|
||||
/* XXXX020 init_keys() again if v3authoritativedir is newly set. */
|
||||
}
|
||||
|
||||
/* Check if we need to parse and add the EntryNodes config option. */
|
||||
@ -2346,6 +2348,8 @@ parse_authority_type_from_list(smartlist_t *list, authority_type_t *auth,
|
||||
*auth |= V1_AUTHORITY | V2_AUTHORITY;
|
||||
else if (!strcasecmp(string, "v2"))
|
||||
*auth |= V2_AUTHORITY;
|
||||
else if (!strcasecmp(string, "v3"))
|
||||
*auth |= V3_AUTHORITY;
|
||||
else if (!strcasecmp(string, "bridge"))
|
||||
*auth |= BRIDGE_AUTHORITY;
|
||||
else if (!strcasecmp(string, "hidserv"))
|
||||
@ -2580,6 +2584,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
"extra-info documents. Setting DownloadExtraInfo.");
|
||||
options->DownloadExtraInfo = 1;
|
||||
}
|
||||
/* XXXX020 Check that at least one of Bridge/HS/V1/V2/V2{AoritativeDir}
|
||||
* is set. */
|
||||
}
|
||||
|
||||
if (options->AuthoritativeDir && !options->DirPort)
|
||||
@ -3588,6 +3594,7 @@ parse_dir_server_line(const char *line, int validate_only)
|
||||
char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
|
||||
uint16_t dir_port = 0, or_port = 0;
|
||||
char digest[DIGEST_LEN];
|
||||
char v3_digest[DIGEST_LEN];
|
||||
authority_type_t type = V2_AUTHORITY;
|
||||
int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
|
||||
|
||||
@ -3625,6 +3632,15 @@ parse_dir_server_line(const char *line, int validate_only)
|
||||
if (!ok)
|
||||
log_warn(LD_CONFIG, "Invalid orport '%s' on DirServer line.",
|
||||
portstring);
|
||||
} else if (!strcasecmpstart(flag, "v3ident=")) {
|
||||
char *idstr = flag + strlen("v3ident=");
|
||||
if (strlen(idstr) != HEX_DIGEST_LEN ||
|
||||
base16_decode(v3_digest, DIGEST_LEN, idstr, HEX_DIGEST_LEN)<0) {
|
||||
log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
|
||||
flag);
|
||||
} else {
|
||||
type |= V3_AUTHORITY;
|
||||
}
|
||||
} else {
|
||||
log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
|
||||
flag);
|
||||
|
22
src/or/or.h
22
src/or/or.h
@ -1334,9 +1334,10 @@ typedef enum {
|
||||
NO_AUTHORITY = 0,
|
||||
V1_AUTHORITY = 1 << 0,
|
||||
V2_AUTHORITY = 1 << 1,
|
||||
HIDSERV_AUTHORITY = 1 << 2,
|
||||
BRIDGE_AUTHORITY = 1 << 3,
|
||||
EXTRAINFO_CACHE = 1 << 4, /* not precisely an authority type. */
|
||||
V3_AUTHORITY = 1 << 2,
|
||||
HIDSERV_AUTHORITY = 1 << 3,
|
||||
BRIDGE_AUTHORITY = 1 << 4,
|
||||
EXTRAINFO_CACHE = 1 << 5, /* not precisely an authority type. */
|
||||
} authority_type_t;
|
||||
|
||||
#define CRYPT_PATH_MAGIC 0x70127012u
|
||||
@ -1758,6 +1759,8 @@ typedef struct {
|
||||
* for version 1 directories? */
|
||||
int V2AuthoritativeDir; /**< Boolean: is this an authoritative directory
|
||||
* for version 2 directories? */
|
||||
int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
|
||||
* for version 3 directories? */
|
||||
int HSAuthoritativeDir; /**< Boolean: does this an authoritative directory
|
||||
* handle hidden service requests? */
|
||||
int HSAuthorityRecordStats; /**< Boolean: does this HS authoritative
|
||||
@ -3057,6 +3060,9 @@ typedef struct trusted_dir_server_t {
|
||||
uint16_t dir_port; /**< Directory port. */
|
||||
uint16_t or_port; /**< OR port: Used for tunneling connections. */
|
||||
char digest[DIGEST_LEN]; /**< Digest of identity key. */
|
||||
char v3_identity_digest[DIGEST_LEN]; /**< Digest of v3 (authority only,
|
||||
* high-security) identity key. */
|
||||
|
||||
unsigned int is_running:1; /**< True iff we think this server is running. */
|
||||
|
||||
/** True iff this server has accepted the most recent server descriptor
|
||||
@ -3066,6 +3072,8 @@ typedef struct trusted_dir_server_t {
|
||||
/** DOCDOC */
|
||||
authority_type_t type;
|
||||
|
||||
authority_cert_t *v3_cert; /**< V3 key certificate for this authority */
|
||||
|
||||
int n_networkstatus_failures; /**< How many times have we asked for this
|
||||
* server's network-status unsuccessfully? */
|
||||
local_routerstatus_t fake_status; /**< Used when we need to pass this trusted
|
||||
@ -3088,6 +3096,8 @@ routerstatus_t *router_pick_trusteddirserver(authority_type_t type,
|
||||
int retry_if_no_servers);
|
||||
trusted_dir_server_t *router_get_trusteddirserver_by_digest(
|
||||
const char *digest);
|
||||
trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(
|
||||
const char *digest);
|
||||
void routerlist_add_family(smartlist_t *sl, routerinfo_t *router);
|
||||
void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
|
||||
int must_be_running);
|
||||
@ -3197,6 +3207,10 @@ int getinfo_helper_networkstatus(control_connection_t *conn,
|
||||
void routerlist_assert_ok(routerlist_t *rl);
|
||||
void routerlist_check_bug_417(void);
|
||||
|
||||
int trusted_dirs_reload_certs(void);
|
||||
int trusted_dirs_load_certs_from_string(const char *contents, int from_store);
|
||||
void trusted_dirs_flush_certs_to_disk(void);
|
||||
|
||||
/********************************* routerparse.c ************************/
|
||||
|
||||
#define MAX_STATUS_TAG_LEN 32
|
||||
@ -3278,7 +3292,7 @@ networkstatus_t *networkstatus_parse_from_string(const char *s);
|
||||
|
||||
void authority_cert_free(authority_cert_t *cert);
|
||||
authority_cert_t *authority_cert_parse_from_string(const char *s,
|
||||
char **end_of_string);
|
||||
const char **end_of_string);
|
||||
|
||||
#endif
|
||||
|
||||
|
127
src/or/router.c
127
src/or/router.c
@ -38,6 +38,11 @@ static crypto_pk_env_t *lastonionkey=NULL;
|
||||
static crypto_pk_env_t *identitykey=NULL;
|
||||
/** Digest of identitykey. */
|
||||
static char identitykey_digest[DIGEST_LEN];
|
||||
/** Signing key used for v3 directory material; only set for authorities. */
|
||||
static crypto_pk_env_t *authority_signing_key = NULL;
|
||||
/** Key certificate to authenticate v3 directory material; only set for
|
||||
* authorities. */
|
||||
static authority_cert_t *authority_key_certificate = NULL;
|
||||
|
||||
/** Replace the current onion key with <b>k</b>. Does not affect lastonionkey;
|
||||
* to update onionkey correctly, call rotate_onion_key().
|
||||
@ -170,46 +175,48 @@ rotate_onion_key(void)
|
||||
log_warn(LD_GENERAL, "Couldn't rotate onion key.");
|
||||
}
|
||||
|
||||
/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist,
|
||||
* create a new RSA key and save it in <b>fname</b>. Return the read/created
|
||||
* key, or NULL on error.
|
||||
*/
|
||||
crypto_pk_env_t *
|
||||
init_key_from_file(const char *fname)
|
||||
/** DOCDOC */
|
||||
static crypto_pk_env_t *
|
||||
init_key_from_file_impl(const char *fname, int generate, int severity)
|
||||
{
|
||||
crypto_pk_env_t *prkey = NULL;
|
||||
FILE *file = NULL;
|
||||
|
||||
if (!(prkey = crypto_new_pk_env())) {
|
||||
log_err(LD_GENERAL,"Error constructing key");
|
||||
log(severity, LD_GENERAL,"Error constructing key");
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (file_status(fname)) {
|
||||
case FN_DIR:
|
||||
case FN_ERROR:
|
||||
log_err(LD_FS,"Can't read key from \"%s\"", fname);
|
||||
log(severity, LD_FS,"Can't read key from \"%s\"", fname);
|
||||
goto error;
|
||||
case FN_NOENT:
|
||||
log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
|
||||
fname);
|
||||
if (crypto_pk_generate_key(prkey)) {
|
||||
log_err(LD_GENERAL,"Error generating onion key");
|
||||
goto error;
|
||||
}
|
||||
if (crypto_pk_check_key(prkey) <= 0) {
|
||||
log_err(LD_GENERAL,"Generated key seems invalid");
|
||||
goto error;
|
||||
}
|
||||
log_info(LD_GENERAL, "Generated key seems valid");
|
||||
if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
|
||||
log_err(LD_FS,"Couldn't write generated key to \"%s\".", fname);
|
||||
goto error;
|
||||
if (generate) {
|
||||
log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
|
||||
fname);
|
||||
if (crypto_pk_generate_key(prkey)) {
|
||||
log(severity, LD_GENERAL,"Error generating onion key");
|
||||
goto error;
|
||||
}
|
||||
if (crypto_pk_check_key(prkey) <= 0) {
|
||||
log(severity, LD_GENERAL,"Generated key seems invalid");
|
||||
goto error;
|
||||
}
|
||||
log_info(LD_GENERAL, "Generated key seems valid");
|
||||
if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
|
||||
log(severity, LD_FS,
|
||||
"Couldn't write generated key to \"%s\".", fname);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
log_info(LD_GENERAL, "No key found in \"%s\"", fname);
|
||||
}
|
||||
return prkey;
|
||||
case FN_FILE:
|
||||
if (crypto_pk_read_private_key_from_filename(prkey, fname)) {
|
||||
log_err(LD_GENERAL,"Error loading private key.");
|
||||
log(severity, LD_GENERAL,"Error loading private key.");
|
||||
goto error;
|
||||
}
|
||||
return prkey;
|
||||
@ -225,6 +232,71 @@ init_key_from_file(const char *fname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist,
|
||||
* create a new RSA key and save it in <b>fname</b>. Return the read/created
|
||||
* key, or NULL on error.
|
||||
*/
|
||||
crypto_pk_env_t *
|
||||
init_key_from_file(const char *fname)
|
||||
{
|
||||
return init_key_from_file_impl(fname, 1, LOG_ERR);
|
||||
}
|
||||
|
||||
/** DOCDOC; XXXX020 maybe move to dirserv.c */
|
||||
static void
|
||||
init_v3_authority_keys(const char *keydir)
|
||||
{
|
||||
char *fname = NULL, *cert = NULL;
|
||||
const char *eos = NULL;
|
||||
size_t fname_len = strlen(keydir) + 64;
|
||||
crypto_pk_env_t *signing_key = NULL;
|
||||
authority_cert_t *parsed = NULL;
|
||||
|
||||
fname = tor_malloc(fname_len);
|
||||
tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"authority_signing_key",
|
||||
keydir);
|
||||
signing_key = init_key_from_file_impl(fname, 0, LOG_INFO);
|
||||
if (!signing_key) {
|
||||
log_warn(LD_DIR, "No version 3 directory key found in %s", fname);
|
||||
goto done;
|
||||
}
|
||||
tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"authority_certificate",
|
||||
keydir);
|
||||
cert = read_file_to_str(fname, 0, NULL);
|
||||
if (!cert) {
|
||||
log_warn(LD_DIR, "Signing key found, but no certificate found in %s",
|
||||
fname);
|
||||
goto done;
|
||||
}
|
||||
parsed = authority_cert_parse_from_string(cert, &eos);
|
||||
if (!parsed) {
|
||||
log_warn(LD_DIR, "Unable to parse certificate in %s", fname);
|
||||
goto done;
|
||||
}
|
||||
if (crypto_pk_cmp_keys(signing_key, parsed->signing_key) != 0) {
|
||||
log_warn(LD_DIR, "Stored signing key does not match signing key in "
|
||||
"certificate");
|
||||
goto done;
|
||||
}
|
||||
parsed->cache_info.signed_descriptor_body = cert;
|
||||
parsed->cache_info.signed_descriptor_len = eos-cert;
|
||||
cert = NULL;
|
||||
|
||||
authority_key_certificate = parsed;
|
||||
authority_signing_key = signing_key;
|
||||
parsed = NULL;
|
||||
signing_key = NULL;
|
||||
|
||||
done:
|
||||
tor_free(fname);
|
||||
tor_free(cert);
|
||||
if (signing_key)
|
||||
crypto_free_pk_env(signing_key);
|
||||
if (parsed)
|
||||
authority_cert_free(parsed);
|
||||
}
|
||||
|
||||
|
||||
/** Initialize all OR private keys, and the TLS context, as necessary.
|
||||
* On OPs, this only initializes the tls context. Return 0 on success,
|
||||
* or -1 if Tor should die.
|
||||
@ -282,6 +354,11 @@ init_keys(void)
|
||||
prkey = init_key_from_file(keydir);
|
||||
if (!prkey) return -1;
|
||||
set_identity_key(prkey);
|
||||
|
||||
/* 1b. Read v3 directory authority key/cert information. */
|
||||
if (authdir_mode(options) && options->V3AuthoritativeDir)
|
||||
init_v3_authority_keys(keydir);
|
||||
|
||||
/* 2. Read onion key. Make it if none is found. */
|
||||
tor_snprintf(keydir,sizeof(keydir),
|
||||
"%s"PATH_SEPARATOR"keys"PATH_SEPARATOR"secret_onion_key",datadir);
|
||||
@ -1592,6 +1669,10 @@ router_free_all(void)
|
||||
routerinfo_free(desc_routerinfo);
|
||||
if (desc_extrainfo)
|
||||
extrainfo_free(desc_extrainfo);
|
||||
if (authority_signing_key)
|
||||
crypto_free_pk_env(authority_signing_key);
|
||||
if (authority_key_certificate)
|
||||
authority_cert_free(authority_key_certificate);
|
||||
|
||||
if (warned_nonexistent_family) {
|
||||
SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp));
|
||||
|
@ -49,6 +49,8 @@ static void router_dir_info_changed(void);
|
||||
/** Global list of a trusted_dir_server_t object for each trusted directory
|
||||
* server. */
|
||||
static smartlist_t *trusted_dir_servers = NULL;
|
||||
/** DOCDOC */
|
||||
static int trusted_dir_servers_certs_changed = 0;
|
||||
|
||||
/** Global list of all of the routers that we know about. */
|
||||
static routerlist_t *routerlist = NULL;
|
||||
@ -163,6 +165,89 @@ router_reload_networkstatus(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
int
|
||||
trusted_dirs_reload_certs(void)
|
||||
{
|
||||
char filename[512];
|
||||
char *contents;
|
||||
int r;
|
||||
|
||||
tor_snprintf(filename,sizeof(filename),"%s"PATH_SEPARATOR"cached-certs",
|
||||
get_options()->DataDirectory);
|
||||
contents = read_file_to_str(filename, 0, NULL);
|
||||
if (!contents)
|
||||
return -1;
|
||||
r = trusted_dirs_load_certs_from_string(contents, 1);
|
||||
tor_free(contents);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
int
|
||||
trusted_dirs_load_certs_from_string(const char *contents, int from_store)
|
||||
{
|
||||
trusted_dir_server_t *ds;
|
||||
const char *s, *eos;
|
||||
|
||||
for (s = contents; *s; s = eos) {
|
||||
authority_cert_t *cert = authority_cert_parse_from_string(s, &eos);
|
||||
if (!cert)
|
||||
break;
|
||||
ds = trusteddirserver_get_by_v3_auth_digest(
|
||||
cert->cache_info.identity_digest);
|
||||
if (!ds) {
|
||||
log_info(LD_DIR, "Found cached certificate whose key didn't match "
|
||||
"any v3 authority we recognized; skipping.");
|
||||
authority_cert_free(cert);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ds->v3_cert) {
|
||||
if (ds->v3_cert->expires < cert->expires) {
|
||||
authority_cert_free(ds->v3_cert);
|
||||
} else {
|
||||
authority_cert_free(cert);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
cert->cache_info.signed_descriptor_body = tor_strndup(s, eos-s);
|
||||
cert->cache_info.signed_descriptor_len = eos-s;
|
||||
ds->v3_cert = cert;
|
||||
if (!from_store)
|
||||
trusted_dir_servers_certs_changed = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
void
|
||||
trusted_dirs_flush_certs_to_disk(void)
|
||||
{
|
||||
char filename[512];
|
||||
smartlist_t *chunks = smartlist_create();
|
||||
|
||||
tor_snprintf(filename,sizeof(filename),"%s"PATH_SEPARATOR"cached-certs",
|
||||
get_options()->DataDirectory);
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
|
||||
{
|
||||
if (ds->v3_cert) {
|
||||
sized_chunk_t *c = tor_malloc(sizeof(sized_chunk_t));
|
||||
c->bytes = ds->v3_cert->cache_info.signed_descriptor_body;
|
||||
c->len = ds->v3_cert->cache_info.signed_descriptor_len;
|
||||
smartlist_add(chunks, c);
|
||||
}
|
||||
});
|
||||
if (write_chunks_to_file(filename, chunks, 0)) {
|
||||
log_warn(LD_FS, "Error writing certificates to disk.");
|
||||
}
|
||||
SMARTLIST_FOREACH(chunks, sized_chunk_t *, c, tor_free(c));
|
||||
smartlist_free(chunks);
|
||||
|
||||
trusted_dir_servers_certs_changed = 0;
|
||||
}
|
||||
|
||||
/* Router descriptor storage.
|
||||
*
|
||||
* Routerdescs are stored in a big file, named "cached-routers". As new
|
||||
@ -573,6 +658,24 @@ router_get_trusteddirserver_by_digest(const char *digest)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Return the trusted_dir_server_t for the directory authority whose identity
|
||||
* key hashes to <b>digest</b>, or NULL if no such authority is known.
|
||||
*/
|
||||
trusted_dir_server_t *
|
||||
trusteddirserver_get_by_v3_auth_digest(const char *digest)
|
||||
{
|
||||
if (!trusted_dir_servers)
|
||||
return NULL;
|
||||
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
|
||||
{
|
||||
if (!memcmp(ds->v3_identity_digest, digest, DIGEST_LEN))
|
||||
return ds;
|
||||
});
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Try to find a running trusted dirserver. If there are no running
|
||||
* trusted dirservers and <b>retry_if_no_servers</b> is non-zero,
|
||||
* set them all as running again, and try again.
|
||||
@ -3477,6 +3580,8 @@ add_trusted_dir_server(const char *nickname, const char *address,
|
||||
static void
|
||||
trusted_dir_server_free(trusted_dir_server_t *ds)
|
||||
{
|
||||
if (ds->v3_cert)
|
||||
authority_cert_free(ds->v3_cert);
|
||||
tor_free(ds->nickname);
|
||||
tor_free(ds->description);
|
||||
tor_free(ds->address);
|
||||
|
@ -1289,16 +1289,19 @@ authority_cert_free(authority_cert_t *cert)
|
||||
/** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
|
||||
* the first character after the certificate. */
|
||||
authority_cert_t *
|
||||
authority_cert_parse_from_string(const char *s, char **end_of_string)
|
||||
authority_cert_parse_from_string(const char *s, const char **end_of_string)
|
||||
{
|
||||
authority_cert_t *cert = NULL;
|
||||
smartlist_t *tokens = NULL;
|
||||
char digest[DIGEST_LEN];
|
||||
directory_token_t *tok;
|
||||
char fp_declared[DIGEST_LEN];
|
||||
|
||||
char *eos = strstr(s, "\n-----END SIGNATURE-----\n");
|
||||
char *eos;
|
||||
size_t len;
|
||||
trusted_dir_server_t *ds;
|
||||
|
||||
s = eat_whitespace(s);
|
||||
eos = strstr(s, "\n-----END SIGNATURE-----\n");
|
||||
if (! eos) {
|
||||
log_warn(LD_DIR, "No end-of-signature found on key certificate");
|
||||
return NULL;
|
||||
@ -1324,6 +1327,7 @@ authority_cert_parse_from_string(const char *s, char **end_of_string)
|
||||
}
|
||||
|
||||
cert = tor_malloc_zero(sizeof(authority_cert_t));
|
||||
memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
|
||||
|
||||
tok = find_first_by_keyword(tokens, K_DIR_SIGNING_KEY);
|
||||
tor_assert(tok && tok->key);
|
||||
@ -1371,11 +1375,20 @@ authority_cert_parse_from_string(const char *s, char **end_of_string)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* XXXXX This doesn't check whether the key is an authority. IS that what we
|
||||
* want? */
|
||||
if (check_signature_token(digest, tok, cert->identity_key, 0,
|
||||
"key certificate")) {
|
||||
goto err;
|
||||
/* If we already have this cert, don't bother checking the signature. */
|
||||
ds = trusteddirserver_get_by_v3_auth_digest(
|
||||
cert->cache_info.identity_digest);
|
||||
if (ds && ds->v3_cert &&
|
||||
ds->v3_cert->cache_info.signed_descriptor_len == len &&
|
||||
ds->v3_cert->cache_info.signed_descriptor_body &&
|
||||
! memcmp(s, ds->v3_cert->cache_info.signed_descriptor_body, len)) {
|
||||
log_debug(LD_DIR, "We already checked the signature on this certificate;"
|
||||
" no need to do so again.");
|
||||
} else {
|
||||
if (check_signature_token(digest, tok, cert->identity_key, 0,
|
||||
"key certificate")) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
cert->cache_info.signed_descriptor_len = len;
|
||||
@ -1383,7 +1396,10 @@ authority_cert_parse_from_string(const char *s, char **end_of_string)
|
||||
memcpy(cert->cache_info.signed_descriptor_body, s, len);
|
||||
cert->cache_info.signed_descriptor_body[len] = 0;
|
||||
cert->cache_info.saved_location = SAVED_NOWHERE;
|
||||
*end_of_string = eos;
|
||||
|
||||
if (end_of_string) {
|
||||
*end_of_string = eat_whitespace(eos);
|
||||
}
|
||||
return cert;
|
||||
err:
|
||||
authority_cert_free(cert);
|
||||
|
Loading…
Reference in New Issue
Block a user