diff --git a/src/common/crypto.c b/src/common/crypto.c index f335f99aba..4ea4492898 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1481,7 +1481,8 @@ crypto_digest_algorithm_get_name(digest_algorithm_t alg) } } -/** DOCDOC */ +/** Given the name of a digest algorithm, return its integer value, or -1 if + * the name is not recognized. */ int crypto_digest_algorithm_parse_name(const char *name) { diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 57d1a8d827..251c35dd38 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1885,7 +1885,8 @@ version_from_platform(const char *platform) * The format argument has three possible values: * NS_V2 - Output an entry suitable for a V2 NS opinion document * NS_V3_CONSENSUS - Output the first portion of a V3 NS consensus entry - * NS_V3_CONSENSUS_MICRODESC - DOCDOC + * NS_V3_CONSENSUS_MICRODESC - Output the first portion of a V3 microdesc + * consensus entry. * NS_V3_VOTE - Output a complete V3 NS vote * NS_CONTROL_PORT - Output a NS document for the control port */ diff --git a/src/or/dirvote.c b/src/or/dirvote.c index e50a875411..eb3c7d2cfa 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -11,7 +11,9 @@ * \brief Functions to compute directory consensus, and schedule voting. **/ -/** DOCDOC*/ +/** A consensus that we have built and are appending signatures to. Once it's + * time to publish it, it will become an active consensus if it accumulates + * enough signatures. */ typedef struct pending_consensus_t { /** The body of the consensus that we're currently building. Once we * have it built, it goes into dirserv.c */ @@ -264,7 +266,8 @@ get_voter(const networkstatus_t *vote) return smartlist_get(vote->voters, 0); } -/** DOCDOC */ +/** Return the signature made by voter using the algorithm + * alg, or NULL if none is found. */ document_signature_t * voter_get_sig_by_algorithm(const networkstatus_voter_info_t *voter, digest_algorithm_t alg) @@ -425,7 +428,8 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, char d[DIGEST256_LEN]; if (compare_vote_rs(rs, most)) continue; - if (!vote_routerstatus_find_microdesc_hash(d, rs, consensus_method)) + if (!vote_routerstatus_find_microdesc_hash(d, rs, consensus_method, + DIGEST_SHA256)) smartlist_add(digests, tor_memdup(d, sizeof(d))); } SMARTLIST_FOREACH_END(rs); smartlist_sort_digests256(digests); @@ -439,9 +443,9 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, return most; } -/** Given a list of strings in lst, set the DIGEST_LEN-byte digest at - * digest_out to the hash of the concatenation of those strings. DOCDOC - * new arguments. */ +/** Given a list of strings in lst, set the len_out-byte digest + * at digest_out to the hash of the concatenation of those strings, + * computed with the algorithm alg. */ static void hash_list_members(char *digest_out, size_t len_out, smartlist_t *lst, digest_algorithm_t alg) @@ -1523,7 +1527,11 @@ networkstatus_add_detached_signatures(networkstatus_t *target, return r; } -/** DOCDOC */ +/** Return a newly allocated string containing all the signatures on + * consensus by all voters. If for_detached_signatures is true, + * then the signatures will be put in a detached signatures document, so + * prefix any non-NS-flavored signatures with "additional-signature" rather + * than "directory-signature". */ static char * networkstatus_format_signatures(networkstatus_t *consensus, int for_detached_signatures) @@ -1674,7 +1682,9 @@ networkstatus_get_detached_signatures(smartlist_t *consensuses) return result; } -/** DOCDOC */ +/** Return a newly allocated string holding a detached-signatures document for + * all of the in-progress consensuses in the n_flavors-element array at + * pending. */ static char * get_detached_signatures_from_pending_consensuses(pending_consensus_t *pending, int n_flavors) @@ -2049,7 +2059,8 @@ dirvote_fetch_missing_signatures(void) 0, NULL); } -/** DOCDOC */ +/** Release all storage held by pending consensuses (those waiting for + * signatures). */ static void dirvote_clear_pending_consensuses(void) { @@ -2775,7 +2786,10 @@ dirvote_create_microdescriptor(const routerinfo_t *ri) /** Cached space-separated string to hold */ static char *microdesc_consensus_methods = NULL; -/** DOCDOC */ +/** Format the appropriate vote line to describe the microdescriptor md + * in a consensus vote document. Write it into the out_len-byte buffer + * in out. Return -1 on failure and the number of characters written + * on success. */ int dirvote_format_microdesc_vote_line(char *out, size_t out_len, const microdesc_t *md) @@ -2798,19 +2812,25 @@ dirvote_format_microdesc_vote_line(char *out, size_t out_len, return strlen(out); } -/** DOCDOC */ +/** If vrs has a hash made for the consensus method method with + * the digest algorithm alg, decode it and copy it into + * digest256_out and return 0. Otherwise return -1. */ int vote_routerstatus_find_microdesc_hash(char *digest256_out, const vote_routerstatus_t *vrs, - int method) + int method, + digest_algorithm_t alg) { /* XXXX only returns the sha256 method. */ const vote_microdesc_hash_t *h; char mstr[64]; size_t mlen; + char dstr[64]; tor_snprintf(mstr, sizeof(mstr), "%d", method); mlen = strlen(mstr); + tor_snprintf(dstr, sizeof(dstr), " %s=", + crypto_digest_algorithm_get_name(alg)); for (h = vrs->microdesc; h; h = h->next) { const char *cp = h->microdesc_hash_line; @@ -2824,10 +2844,10 @@ vote_routerstatus_find_microdesc_hash(char *digest256_out, char buf[BASE64_DIGEST256_LEN+1]; /* XXXX ignores extraneous stuff if the digest is too long. This * seems harmless enough, right? */ - cp = strstr(cp, " sha256="); + cp = strstr(cp, dstr); if (!cp) return -1; - cp += strlen(" sha256="); + cp += strlen(dstr); strlcpy(buf, cp, sizeof(buf)); return digest256_from_base64(digest256_out, buf); } diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 2533564dd5..85070650e8 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -3,20 +3,26 @@ #include "or.h" -/** DOCDOC everything here. */ - -#define MICRODESC_IN_CONSENSUS 1 -#define MICRODESC_IN_VOTE 2 - +/** A data structure to hold a bunch of cached microdescriptors. There are + * two active files in the cache: a "cache file" that we mmap, and a "journal + * file" that we append to. Periodically, we rebuild the cache file to hold + * only the microdescriptors that we want to keep */ struct microdesc_cache_t { + /** Map from sha256-digest to microdesc_t for every microdesc_t in the + * cache. */ HT_HEAD(microdesc_map, microdesc_t) map; + /** Name of the cache file. */ char *cache_fname; + /** Name of the journal file. */ char *journal_fname; + /** Mmap'd contents of the cache file, or NULL if there is none. */ tor_mmap_t *cache_content; + /** Number of bytes used in the journal file. */ size_t journal_len; }; +/** Helper: computes a hash of md to place it in a hash table. */ static INLINE unsigned int _microdesc_hash(microdesc_t *md) { @@ -28,6 +34,7 @@ _microdesc_hash(microdesc_t *md) #endif } +/** Helper: compares a and for equality for hash-table purposes. */ static INLINE int _microdesc_eq(microdesc_t *a, microdesc_t *b) { @@ -40,7 +47,10 @@ HT_GENERATE(microdesc_map, microdesc_t, node, _microdesc_hash, _microdesc_eq, 0.6, _tor_malloc, _tor_realloc, _tor_free); -/* returns n bytes written */ +/** Write the body of md into f, with appropriate annotations. + * On success, return the total number of bytes written, and set + * *annotation_len_out to the number of bytes written as + * annotations. */ static int dump_microdescriptor(FILE *f, microdesc_t *md, int *annotation_len_out) { @@ -64,8 +74,11 @@ dump_microdescriptor(FILE *f, microdesc_t *md, int *annotation_len_out) return r; } +/** Holds a pointer to the current microdesc_cache_t object, or NULL if no + * such object has been allocated. */ static microdesc_cache_t *the_microdesc_cache = NULL; +/** Return a pointer to the microdescriptor cache, loading it if necessary. */ microdesc_cache_t * get_microdesc_cache(void) { @@ -86,7 +99,12 @@ get_microdesc_cache(void) 3) Downloaded. */ -/* Returns list of added microdesc_t. */ +/** Decode the microdescriptors from the string starting at s and + * ending at eos, and store them in cache. If no-save, + * mark them as non-writable to disk. If where is SAVED_IN_CACHE, + * leave their bodies as pointers to the mmap'd cache. If where is + * SAVED_NOWHERE, do not allow annotations. Return a list of the added + * microdescriptors. */ smartlist_t * microdescs_add_to_cache(microdesc_cache_t *cache, const char *s, const char *eos, saved_location_t where, @@ -107,8 +125,9 @@ microdescs_add_to_cache(microdesc_cache_t *cache, return added; } -/* Returns list of added microdesc_t. Frees any not added. Updates last_listed. - */ +/* As microdescs_add_to_cache, but takes a list of micrdescriptors instead of + * a string to encode. Frees any members of descriptors that it does + * not add. */ smartlist_t * microdescs_add_list_to_cache(microdesc_cache_t *cache, smartlist_t *descriptors, saved_location_t where, @@ -174,6 +193,7 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, return added; } +/** Remove every microdescriptor in cache. */ void microdesc_cache_clear(microdesc_cache_t *cache) { @@ -190,6 +210,8 @@ microdesc_cache_clear(microdesc_cache_t *cache) } } +/** Reload the contents of cache from disk. If it is empty, load it + * for the first time. Return 0 on success, -1 on failure. */ int microdesc_cache_reload(microdesc_cache_t *cache) { @@ -228,6 +250,9 @@ microdesc_cache_reload(microdesc_cache_t *cache) return 0; } +/** Regenerate the main cache file for cache, clear the journal file, + * and update every microdesc_t in the cache with pointers to its new + * location. */ int microdesc_cache_rebuild(microdesc_cache_t *cache) { @@ -298,6 +323,8 @@ microdesc_cache_rebuild(microdesc_cache_t *cache) return 0; } +/** Deallocate a single microdescriptor. Note: the microdescriptor MUST have + * previously been removed from the cache if it had ever been inserted. */ void microdesc_free(microdesc_t *md) { @@ -316,6 +343,7 @@ microdesc_free(microdesc_t *md) tor_free(md); } +/** Free all storage held in the microdesc.c module. */ void microdesc_free_all(void) { diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 37838f4b08..e9e8663062 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -2082,7 +2082,8 @@ networkstatus_get_flavor_name(consensus_flavor_t flav) } } -/** DOCDOC return -1 on unknown */ +/** Return the consensus_flavor_t value for the flavor called flavname, + * or -1 if the flavor is not recongized. */ int networkstatus_parse_flavor_name(const char *flavname) { diff --git a/src/or/or.h b/src/or/or.h index 63d2eee9da..21e90a4cdf 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1559,27 +1559,48 @@ typedef struct routerstatus_t { } routerstatus_t; -/**DOCDOC*/ +/** A microdescriptor is the smallest amount of information needed to build a + * circuit through a router. They are generated by the directory authorities, + * using information from the uploaded routerinfo documents. They are not + * self-signed, but are rather authenticated by having their hash in a signed + * networkstatus document. */ typedef struct microdesc_t { + /** Hashtable node, used to look up the microdesc by its digest. */ HT_ENTRY(microdesc_t) node; /* Cache information */ + /** When was this microdescriptor last listed in a consensus document? + * Once a microdesc has been unlisted long enough, we can drop it. + */ time_t last_listed; + /** Where is this microdescriptor currently stored? */ saved_location_t saved_location : 3; + /** If true, do not attempt to cache this microdescriptor on disk. */ unsigned int no_save : 1; + /** If saved_location == SAVED_IN_CACHE, this field holds the offset of the + * microdescriptor in the cache. */ off_t off; /* The string containing the microdesc. */ + /** A pointer to the encoded body of the microdescriptor. If the + * saved_location is SAVED_IN_CACHE, then the body is a pointer into an + * mmap'd region. Otherwise, it is a malloc'd string. The string might not + * be NUL-terminated; take the length from bodylen. */ char *body; + /** The length of the microdescriptor in body. */ size_t bodylen; + /** A SHA256-digest of the microdescriptor. */ char digest[DIGEST256_LEN]; /* Fields in the microdescriptor. */ + /** As routerinfo_t.onion_pkey */ crypto_pk_env_t *onion_pkey; + /** As routerinfo_t.family */ smartlist_t *family; + /** Encoded exit policy summary */ char *exitsummary; /**< exit policy summary - * XXX this probably should not stay a string. */ } microdesc_t; @@ -1687,16 +1708,18 @@ typedef enum { NS_TYPE_OPINION, } networkstatus_type_t; -/** DOCDOC */ +/** Enumerates recognized flavors of a consensus networkstatus document. All + * flavors of a consensus are generated from the same set of votes, but they + * present different types information to different versions of Tor. */ typedef enum { FLAV_NS = 0, FLAV_MICRODESC = 1, } consensus_flavor_t; -/** DOCDOC */ +/** Which consensus flavor do we actually want to use to build circuits? */ #define USABLE_CONSENSUS_FLAVOR FLAV_NS -/** DOCDOC */ +/** How many different consensus flavors are there? */ #define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1) /** A common structure to hold a v3 network status vote, or a v3 network @@ -3892,7 +3915,8 @@ int dirvote_format_microdesc_vote_line(char *out, size_t out_len, const microdesc_t *md); int vote_routerstatus_find_microdesc_hash(char *digest256_out, const vote_routerstatus_t *vrs, - int method); + int method, + digest_algorithm_t alg); document_signature_t *voter_get_sig_by_algorithm( const networkstatus_voter_info_t *voter, digest_algorithm_t alg); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index c6278c6efe..1f89cffa01 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -640,7 +640,8 @@ router_get_networkstatus_v2_hash(const char *s, char *digest) DIGEST_SHA1); } -/** DOCDOC */ +/** Set digests to all the digests of the consensus document in + * s */ int router_get_networkstatus_v3_hashes(const char *s, digests_t *digests) { @@ -677,8 +678,6 @@ router_get_extrainfo_hash(const char *s, char *digest) * surround it with -----BEGIN/END----- pairs, and write it to the * buf_len-byte buffer at buf. Return 0 on success, -1 on * failure. - * - * DOCDOC alg */ int router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, @@ -1901,7 +1900,7 @@ find_start_of_next_routerstatus(const char *s) * consensus, and we should parse it according to the method used to * make that consensus. * - * DOCDOC flav + * Parse according to the syntax used by the consensus flavor flav. **/ static routerstatus_t * routerstatus_parse_entry_from_string(memarea_t *area, @@ -2832,7 +2831,9 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, return ns; } -/** DOCDOC */ +/** Return the digests_t that holds the digests of the + * flavor_name-flavored networkstatus according to the detached + * signatures document sigs, allocating a new digests_t as neeeded. */ static digests_t * detached_get_digests(ns_detached_signatures_t *sigs, const char *flavor_name) { @@ -2844,7 +2845,9 @@ detached_get_digests(ns_detached_signatures_t *sigs, const char *flavor_name) return d; } -/** DOCDOC */ +/** Return the list of signatures of the flavor_name-flavored + * networkstatus according to the detached signatures document sigs, + * allocating a new digests_t as neeeded. */ static smartlist_t * detached_get_signatures(ns_detached_signatures_t *sigs, const char *flavor_name) @@ -3719,8 +3722,8 @@ router_get_hashes_impl(const char *s, digests_t *digests, return 0; } -/** DOCDOC Assuming that s starts with a microdesc, return the start of the - * *NEXT* one. */ +/** Assuming that s starts with a microdesc, return the start of the + * *NEXT* one. Return NULL on "not found." */ static const char * find_start_of_next_microdesc(const char *s, const char *eos) { @@ -3771,7 +3774,11 @@ find_start_of_next_microdesc(const char *s, const char *eos) #undef NEXT_LINE } -/**DOCDOC*/ +/** Parse as many microdescriptors as are found from the string starting at + * s and ending at eos. If allow_annotations is set, read any + * annotations we recognize and ignore ones we don't. If copy_body is + * true, then strdup the bodies of the microdescriptors. Return all newly + * parsed microdescriptors in a newly allocated smartlist_t. */ smartlist_t * microdescs_parse_from_string(const char *s, const char *eos, int allow_annotations, int copy_body)