unreachable is bunk -- it's leftover from the time when all
servers ran 24/7. now it triggers every time a server goes
away and then returns before the old descriptor has expired.
- - Update dir-spec with decisions made on these issues:
+ o Update dir-spec with decisions made on these issues:
o clients don't log as loudly when they receive them
o they don't count toward the 3-strikes rule
D But eventually, we give up after getting a lot of 503s.
D They can 503 client descriptor requests when they feel like it.
How can they distinguish? Not implemented for now, maybe
should abandon.
- - describe our 302 not modified behaviors.
- - and document a bit more -- e.g. it looks like we return an empty
+ o describe our 302 not modified behaviors.
+ o and document a bit more -- e.g. it looks like we return an empty
200 OK when somebody asks us for a networkstatus and we don't
have it?
- Get authorities voting
. Code to manage key certificates
- Download as needed.
- - Serve list as needed.
+ o Serve list as needed.
o Avoid double-checking signatures every time we get a vote.
- Warn about expired stuff.
- Fix all XXXX020s in vote code
const char *body, size_t body_len)
{
size_t dlen;
- char *url = NULL;
+ char *url = NULL; /* XXX020 every exit point needs to free url. this
+ * function should use 'goto done' for that. */
or_options_t *options = get_options();
time_t if_modified_since = 0;
char *header;
return 0;
}
+ if (!strcmpstart(url,"/tor/keys/")) {
+ smartlist_t *certs = smartlist_create();
+ int compressed;
+ ssize_t len = -1;
+ url += strlen("/tor/keys/");
+ compressed = !strcmpend(url, ".z");
+ if (compressed)
+ url[strlen(url)-2] = '\0';
+ if (!strcmp(url, "all")) {
+ SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
+ trusted_dir_server_t *, ds,
+ {
+ if (!ds->v3_certs)
+ continue;
+ SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ if (cert->cache_info.published_on >= if_modified_since)
+ smartlist_add(certs, cert));
+ });
+ } else if (!strcmp(url, "authority")) {
+ authority_cert_t *cert = get_my_v3_authority_cert();
+ if (cert)
+ smartlist_add(certs, cert);
+ } else if (!strcmpstart(url, "fp/")) {
+ smartlist_t *fps = smartlist_create();
+ dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
+ SMARTLIST_FOREACH(fps, char *, d, {
+ authority_cert_t *c = authority_cert_get_newest_by_id(d);
+ if (c) smartlist_add(certs, c);
+ tor_free(d);
+ });
+ smartlist_free(fps);
+ } else if (!strcmpstart(url, "sk/")) {
+ smartlist_t *fps = smartlist_create();
+ dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
+ SMARTLIST_FOREACH(fps, char *, d, {
+ authority_cert_t *c = authority_cert_get_by_sk_digest(d);
+ if (c) smartlist_add(certs, c);
+ tor_free(d);
+ });
+ smartlist_free(fps);
+ } else {
+ write_http_status_line(conn, 400, "Bad request");
+ tor_free(url);
+ smartlist_free(certs);
+ return 0;
+ }
+ if (!smartlist_len(certs)) {
+ write_http_status_line(conn, 404, "Not found");
+ tor_free(url);
+ smartlist_free(certs);
+ return 0;
+ }
+ if (!compressed) {
+ len = 0;
+ SMARTLIST_FOREACH(certs, authority_cert_t *, c,
+ len += c->cache_info.signed_descriptor_len);
+ }
+ write_http_response_header(conn, len,
+ compressed?"application/octet-stream":"text/plain",
+ compressed?"deflate":"identity",
+ 60*60);
+ if (compressed) {
+ conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD);
+ SMARTLIST_FOREACH(certs, authority_cert_t *, c,
+ connection_write_to_buf_zlib(c->cache_info.signed_descriptor_body,
+ c->cache_info.signed_descriptor_len,
+ conn, 0));
+ connection_write_to_buf_zlib("", 0, conn, 1);
+ } else {
+ SMARTLIST_FOREACH(certs, authority_cert_t *, c,
+ connection_write_to_buf(c->cache_info.signed_descriptor_body,
+ c->cache_info.signed_descriptor_len,
+ TO_CONN(conn)));
+ }
+ smartlist_free(certs);
+ tor_free(url);
+ }
+
if (options->HSAuthoritativeDir &&
(!strcmpstart(url,"/tor/rendezvous/") ||
!strcmpstart(url,"/tor/rendezvous1/"))) {
trusted_dirs_flush_certs_to_disk();
}
+/** DOCDOC */
+authority_cert_t *
+authority_cert_get_newest_by_id(const char *id_digest)
+{
+ trusted_dir_server_t *ds = trusteddirserver_get_by_v3_auth_digest(id_digest);
+ authority_cert_t *best = NULL;
+ if (!ds || !ds->v3_certs)
+ return NULL;
+ SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ {
+ if (!best || cert->cache_info.published_on > best->cache_info.published_on)
+ best = cert;
+ });
+ return best;
+}
+
+/** DOCDOC */
+authority_cert_t *
+authority_cert_get_by_sk_digest(const char *sk_digest)
+{
+ if (!trusted_dir_servers)
+ return NULL;
+ SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
+ {
+ if (!ds->v3_certs)
+ return NULL;
+ SMARTLIST_FOREACH(ds->v3_certs, authority_cert_t *, cert,
+ {
+ if (!memcmp(cert->signing_key_digest, sk_digest, DIGEST_LEN))
+ return cert;
+ });
+ });
+ return NULL;
+}
+
/** Return the v3 authority certificate with signing key matching
* <b>sk_digest</b>, for the authority with identity digest <b>id_digest</b>.
* Return NULL if no such authority is known. */