diff options
author | Nick Mathewson <nickm@torproject.org> | 2004-03-31 03:42:56 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2004-03-31 03:42:56 +0000 |
commit | b32440a02896d39f44664104a935f71741a8b4c4 (patch) | |
tree | 472883576d0028431d5afbe894732fdbf20495be /src/or | |
parent | 6ea61d5e0dd7a5990ab2a5a8198cef425718f81f (diff) | |
download | tor-b32440a02896d39f44664104a935f71741a8b4c4.tar tor-b32440a02896d39f44664104a935f71741a8b4c4.tar.gz |
Implement hidserv_XX functions; there is still an XXX in directory_handle_command
svn:r1404
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/directory.c | 20 | ||||
-rw-r--r-- | src/or/main.c | 3 | ||||
-rw-r--r-- | src/or/or.h | 6 | ||||
-rw-r--r-- | src/or/rendcommon.c | 119 |
4 files changed, 136 insertions, 12 deletions
diff --git a/src/or/directory.c b/src/or/directory.c index 0251c953a..9c9cc9d38 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -288,11 +288,6 @@ int connection_dir_process_inbuf(connection_t *conn) { return 0; } -/* XXX stubs, probably shouldn't be located here */ -#define MAX_HIDSERV_DESC_SIZE 2048 -int hidserv_lookup(char *query, char *desc, int max_desc_size) { return 0; } -int hidserv_store(char *desc) { return 0; } - static char answer200[] = "HTTP/1.0 200 OK\r\n\r\n"; static char answer400[] = "HTTP/1.0 400 Bad request\r\n\r\n"; static char answer403[] = "HTTP/1.0 403 Unapproved server\r\n\r\n"; @@ -331,12 +326,13 @@ static int directory_handle_command_get(connection_t *conn, } if(!strncmp(url,"/hidserv/",9)) { /* hidserv descriptor fetch */ - char desc[MAX_HIDSERV_DESC_SIZE]; + const char *descp; + int desc_len; - switch(hidserv_lookup(url+9, desc, MAX_HIDSERV_DESC_SIZE)) { + switch(hidserv_lookup(url+9, &descp, &desc_len)) { case 1: /* valid */ connection_write_to_buf(answer200, strlen(answer200), conn); - connection_write_to_buf(desc, strlen(desc)+1, conn); + connection_write_to_buf(descp, desc_len, conn); /* XXXX Contains NULs*/ break; case 0: /* well-formed but not present */ connection_write_to_buf(answer404, strlen(answer404), conn); @@ -355,7 +351,8 @@ static int directory_handle_command_get(connection_t *conn, /* always returns 0 */ static int directory_handle_command_post(connection_t *conn, - char *headers, char *body) { + char *headers, char *body, + int body_len) { const char *cp; char *url; @@ -387,7 +384,7 @@ static int directory_handle_command_post(connection_t *conn, } if(!strncmp(url,"/hidserv/",9)) { /* hidserv descriptor post */ - if(hidserv_store(body) < 0) + if(hidserv_store(body, body_len) < 0) connection_write_to_buf(answer400, strlen(answer400), conn); else connection_write_to_buf(answer200, strlen(answer200), conn); @@ -420,7 +417,8 @@ static int directory_handle_command(connection_t *conn) { if(!strncasecmp(headers,"GET",3)) r = directory_handle_command_get(conn, headers, body); else if (!strncasecmp(headers,"POST",4)) - r = directory_handle_command_post(conn, headers, body); + /* XXXX this takes a length now, and will fail if the body has NULs. */ + r = directory_handle_command_post(conn, headers, body, strlen(body)); else { log_fn(LOG_WARN,"Got headers '%s' with unknown command. Closing.", headers); r = -1; diff --git a/src/or/main.c b/src/or/main.c index eab26058f..516e300b8 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -334,6 +334,7 @@ static void run_scheduled_events(time_t now) { /* We're a directory; dump any old descriptors. */ dirserv_remove_old_servers(); } + hidserv_cache_clean(); /* should this go elsewhere? */ time_to_fetch_directory = now + options.DirFetchPostPeriod; } @@ -547,6 +548,8 @@ static int do_main_loop(void) { /* Initialize the history structures. */ rep_hist_init(); + /* Intialize the service cache. */ + hidserv_cache_init(); /* load the private keys, if we're supposed to have them, and set up the * TLS context. */ diff --git a/src/or/or.h b/src/or/or.h index 14dbdb926..7fa70435c 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -985,6 +985,12 @@ int rend_encode_service_descriptor(rend_service_descriptor_t *desc, char **str_out, int *len_out); rend_service_descriptor_t *rend_parse_service_descriptor(const char *str, int len); +int rend_get_service_id(crypto_pk_env_t *pk, char *out); + +void hidserv_cache_init(void); +void hidserv_cache_clean(void); +int hidserv_lookup(char *query, const char **desc, int *desc_len); +int hidserv_store(char *desc, int desc_len); #endif diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index f1e1b0160..d460721f6 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -67,7 +67,6 @@ rend_encode_service_descriptor(rend_service_descriptor_t *desc, return 0; } - rend_service_descriptor_t *rend_parse_service_descriptor( const char *str, int len) { @@ -128,3 +127,121 @@ rend_service_descriptor_t *rend_parse_service_descriptor( return NULL; } +int rend_get_service_id(crypto_pk_env_t *pk, char *out) +{ + char buf[CRYPTO_SHA1_DIGEST_LEN]; + assert(pk); + if (crypto_pk_get_digest(pk, buf) < 0) + return -1; + if (base32_encode(out, REND_SERVICE_ID_LEN+1, buf, 10) < 0) + return -1; + return 0; +} + +/* ==== Hidden service descriptor cache. */ +#define HIDSERV_MAX_AGE 24*60*60 +#define HIDSERV_MAX_SKEW 60*60 + +typedef struct hidserv_cache_entry_t { + int len; + char *desc; + rend_service_descriptor_t *parsed; +} hidserv_cache_entry_t; + +static strmap_t *hidserv_cache = NULL; + +void hidserv_cache_init(void) +{ + hidserv_cache = strmap_new(); +} + +void hidserv_cache_clean(void) +{ + strmap_iter_t *iter; + const char *key; + void *val; + hidserv_cache_entry_t *ent; + time_t cutoff; + cutoff = time(NULL) - HIDSERV_MAX_AGE; + for (iter = strmap_iter_init(hidserv_cache); !strmap_iter_done(iter); ) { + strmap_iter_get(iter, &key, &val); + ent = (hidserv_cache_entry_t*)val; + if (ent->parsed->timestamp < cutoff) { + iter = strmap_iter_next_rmv(hidserv_cache, iter); + rend_service_descriptor_free(ent->parsed); + tor_free(ent->desc); + tor_free(ent); + } else { + iter = strmap_iter_next(hidserv_cache, iter); + } + } +} + +int hidserv_lookup(char *query, const char **desc, int *desc_len) +{ + hidserv_cache_entry_t *e; + assert(hidserv_cache); + if (strlen(query) != REND_SERVICE_ID_LEN) + return -1; /* XXXX also check for bad chars. */ + e = (hidserv_cache_entry_t*) strmap_get_lc(hidserv_cache, query); + if (!e) + return 0; + *desc = e->desc; + *desc_len = e->len; + return 1; +} + +int hidserv_store(char *desc, int desc_len) +{ + hidserv_cache_entry_t *e; + rend_service_descriptor_t *parsed; + char query[REND_SERVICE_ID_LEN+1]; + time_t now; + assert(hidserv_cache); + parsed = rend_parse_service_descriptor(desc,desc_len); + if (!parsed) { + log_fn(LOG_WARN,"Couldn't parse service descriptor"); + return -1; + } + if (rend_get_service_id(parsed->pk, query)<0) { + log_fn(LOG_WARN,"Couldn't compute service ID"); + rend_service_descriptor_free(parsed); + return -1; + } + now = time(NULL); + if (parsed->timestamp < now-HIDSERV_MAX_AGE) { + log_fn(LOG_WARN,"Service descriptor is too old"); + rend_service_descriptor_free(parsed); + return -1; + } + if (parsed->timestamp > now+HIDSERV_MAX_SKEW) { + log_fn(LOG_WARN,"Service descriptor is too far in the future"); + rend_service_descriptor_free(parsed); + return -1; + } + e = (hidserv_cache_entry_t*) strmap_get_lc(hidserv_cache, query); + if (e && e->parsed->timestamp > parsed->timestamp) { + log_fn(LOG_WARN,"We already have a newer service descriptor with the same ID"); + rend_service_descriptor_free(parsed); + return -1; + } + if (e && e->len == desc_len && !memcmp(desc,e->desc,desc_len)) { + log_fn(LOG_WARN,"We already have this service descriptor"); + rend_service_descriptor_free(parsed); + return -1; + } + if (!e) { + e = tor_malloc_zero(sizeof(hidserv_cache_entry_t)); + strmap_set_lc(hidserv_cache, query, e); + } else { + rend_service_descriptor_free(e->parsed); + tor_free(e->desc); + } + e->parsed = parsed; + e->len = desc_len; + e->desc = tor_strdup(desc); + + return 0; +} + + |