summaryrefslogtreecommitdiff
path: root/src/or/directory.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-08-14 21:09:30 +0000
committerNick Mathewson <nickm@torproject.org>2007-08-14 21:09:30 +0000
commit484a5806985e617e311fd76fd9a6c5bf24fb3268 (patch)
tree8d81b988883d7ec4a685cc41bc2957572e340b5c /src/or/directory.c
parent9a30f8ba0e146c328b7d4f05fd03b125e639bfbe (diff)
downloadtor-484a5806985e617e311fd76fd9a6c5bf24fb3268.tar.gz
tor-484a5806985e617e311fd76fd9a6c5bf24fb3268.zip
r14028@Kushana: nickm | 2007-08-14 17:07:51 -0400
Implement cert-retrieval URLs. (Also, update TODO) svn:r11112
Diffstat (limited to 'src/or/directory.c')
-rw-r--r--src/or/directory.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/src/or/directory.c b/src/or/directory.c
index e964ed33ef..3082078d48 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -1737,7 +1737,8 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
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;
@@ -2007,6 +2008,84 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
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/"))) {