mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-23 14:40:51 +01:00
Implement hidserv_XX functions; there is still an XXX in directory_handle_command
svn:r1404
This commit is contained in:
parent
6ea61d5e0d
commit
b32440a028
7 changed files with 142 additions and 18 deletions
8
doc/TODO
8
doc/TODO
|
@ -103,19 +103,19 @@ Rendezvous service:
|
|||
o Joined to another circuit at the rendezvous point.
|
||||
(We should also enumerate all the states that these operations
|
||||
can be in.) [NM]
|
||||
o Add circuit metadata [NM] 3 hours
|
||||
o Add circuit metadata [NM]
|
||||
- Code to configure hidden services [NM] 4 hours
|
||||
. Service descriptors
|
||||
- OPs need to maintain identity keys for hidden services [NM] 1 hour
|
||||
o Code to generate and parse service descriptors [NM] 4 hours
|
||||
o Code to generate and parse service descriptors [NM]
|
||||
- Advertisement
|
||||
. Generate y.onion hostnames [NM] 1 hour
|
||||
o Generate y.onion hostnames [NM]
|
||||
- Code to do an HTTP connection over Tor from within Tor [RD]
|
||||
- Publish service descriptors to directory [RD]
|
||||
- Directory accepts and remembers service descriptors, and
|
||||
delivers them as requested
|
||||
- Frontend [RD]
|
||||
- Backend [NM] 1 hour
|
||||
o Backend [NM]
|
||||
- Code for OPs to retrieve (and cache?) service descriptors [RD]
|
||||
- Rendezvous
|
||||
- Code as needed to generate and parse all rendezvous-related
|
||||
|
|
|
@ -186,7 +186,7 @@ Tor Rendezvous Spec
|
|||
1.6. Alice's OP retrieves a service descriptor
|
||||
|
||||
Alice opens a stream to a directory server via Tor, and makes an HTTP GET
|
||||
request for the document '/rendevous/<y>', where '<y> is replaced with the
|
||||
request for the document '/hidserv/<y>', where '<y> is replaced with the
|
||||
encoding of Bob's public key as described above. The directory replies
|
||||
with a 404 HTTP response if it does not recognize <y>, and otherwise
|
||||
returns Bob's most recently uploaded service descriptor.
|
||||
|
|
|
@ -380,7 +380,7 @@ void strmap_foreach(strmap_t *map,
|
|||
*
|
||||
* // uppercase values in "map", removing empty values.
|
||||
*
|
||||
* strmap_iterator_t *iter;
|
||||
* strmap_iter_t *iter;
|
||||
* const char *key;
|
||||
* void *val;
|
||||
* char *cp;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue