diff --git a/doc/TODO b/doc/TODO index 680690eead..28dc289375 100644 --- a/doc/TODO +++ b/doc/TODO @@ -104,12 +104,13 @@ Rendezvous service: (We should also enumerate all the states that these operations can be in.) [NM] 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 configure hidden services [NM] 4 hours + o Service descriptors + o OPs need to maintain identity keys for hidden services [NM] o Code to generate and parse service descriptors [NM] - - Advertisement + . Advertisement o Generate y.onion hostnames [NM] + o Store y.onion hostnames to disk. [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 diff --git a/src/or/Makefile.am b/src/or/Makefile.am index 7568df7f37..fbdac98201 100644 --- a/src/or/Makefile.am +++ b/src/or/Makefile.am @@ -4,17 +4,21 @@ noinst_PROGRAMS = test bin_PROGRAMS = tor -tor_SOURCES = buffers.c circuit.c command.c connection.c \ - connection_or.c config.c dirserv.c rendcommon.c \ - onion.c router.c routerlist.c directory.c dns.c connection_edge.c \ - rephist.c cpuworker.c main.c tor_main.c +tor_SOURCES = buffers.c circuit.c command.c config.c \ + connection.c connection_edge.c connection_or.c \ + cpuworker.c directory.c dirserv.c dns.c main.c \ + onion.c rendcommon.c rendservice.c rephist.c \ + router.c routerlist.c \ + tor_main.c tor_LDADD = ../common/libor.a -test_SOURCES = buffers.c circuit.c command.c connection.c \ - connection_or.c config.c dirserv.c rendcommon.c \ - onion.c router.c routerlist.c directory.c dns.c connection_edge.c \ - rephist.c cpuworker.c main.c test.c +test_SOURCES = buffers.c circuit.c command.c config.c \ + connection.c connection_edge.c connection_or.c \ + cpuworker.c directory.c dirserv.c dns.c main.c \ + onion.c rendcommon.c rendservice.c rephist.c \ + router.c routerlist.c \ + test.c test_LDADD = ../common/libor.a diff --git a/src/or/config.c b/src/or/config.c index d23453c6f6..eead3a594f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -11,22 +11,17 @@ #define CONFIG_TYPE_LONG 3 #define CONFIG_TYPE_DOUBLE 4 #define CONFIG_TYPE_BOOL 5 +#define CONFIG_TYPE_LINELIST 6 -#define CONFIG_LINE_MAXLEN 4096 - -struct config_line { - char *key; - char *value; - struct config_line *next; -}; +#define CONFIG_LINE_T_MAXLEN 4096 static FILE *config_open(const unsigned char *filename); static int config_close(FILE *f); -static struct config_line *config_get_commandlines(int argc, char **argv); -static struct config_line *config_get_lines(FILE *f); -static void config_free_lines(struct config_line *front); -static int config_compare(struct config_line *c, char *key, int type, void *arg); -static int config_assign(or_options_t *options, struct config_line *list); +static struct config_line_t *config_get_commandlines(int argc, char **argv); +static struct config_line_t *config_get_lines(FILE *f); +static void config_free_lines(struct config_line_t *front); +static int config_compare(struct config_line_t *c, char *key, int type, void *arg); +static int config_assign(or_options_t *options, struct config_line_t *list); /* open configuration file for reading */ static FILE *config_open(const unsigned char *filename) { @@ -44,9 +39,9 @@ static int config_close(FILE *f) { return fclose(f); } -static struct config_line *config_get_commandlines(int argc, char **argv) { - struct config_line *new; - struct config_line *front = NULL; +static struct config_line_t *config_get_commandlines(int argc, char **argv) { + struct config_line_t *new; + struct config_line_t *front = NULL; char *s; int i = 1; @@ -57,7 +52,7 @@ static struct config_line *config_get_commandlines(int argc, char **argv) { continue; } - new = tor_malloc(sizeof(struct config_line)); + new = tor_malloc(sizeof(struct config_line_t)); s = argv[i]; while(*s == '-') s++; @@ -73,31 +68,39 @@ static struct config_line *config_get_commandlines(int argc, char **argv) { return front; } +static struct config_line_t * +config_line_prepend(struct config_line_t *front, + const char *key, + const char *val) +{ + struct config_line_t *newline; + newline = tor_malloc(sizeof(struct config_line_t)); + newline->key = tor_strdup(key); + newline->value = tor_strdup(val); + newline->next = front; + return newline; +} + /* parse the config file and strdup into key/value strings. Return list, * or NULL if parsing the file failed. * Warn and ignore mangled lines. */ -static struct config_line *config_get_lines(FILE *f) { - struct config_line *new; - struct config_line *front = NULL; - char line[CONFIG_LINE_MAXLEN]; +static struct config_line_t *config_get_lines(FILE *f) { + + struct config_line_t *front = NULL; + char line[CONFIG_LINE_T_MAXLEN]; int result; char *key, *value; while( (result=parse_line_from_file(line,sizeof(line),f,&key,&value)) > 0) { - new = tor_malloc(sizeof(struct config_line)); - new->key = tor_strdup(key); - new->value = tor_strdup(value); - - new->next = front; - front = new; + front = config_line_prepend(front, key, value); } if(result < 0) return NULL; return front; } -static void config_free_lines(struct config_line *front) { - struct config_line *tmp; +static void config_free_lines(struct config_line_t *front) { + struct config_line_t *tmp; while(front) { tmp = front; @@ -109,7 +112,7 @@ static void config_free_lines(struct config_line *front) { } } -static int config_compare(struct config_line *c, char *key, int type, void *arg) { +static int config_compare(struct config_line_t *c, char *key, int type, void *arg) { int i; if(strncasecmp(c->key,key,strlen(c->key))) @@ -137,6 +140,13 @@ static int config_compare(struct config_line *c, char *key, int type, void *arg) case CONFIG_TYPE_DOUBLE: *(double *)arg = atof(c->value); break; + case CONFIG_TYPE_LINELIST: + /* Note: this reverses the order that the lines appear in. That's + * just fine, since we build up the list of lines reversed in the + * first place. */ + *(struct config_line_t**)arg = + config_line_prepend(*(struct config_line_t**)arg, c->key, c->value); + break; } return 1; } @@ -145,7 +155,7 @@ static int config_compare(struct config_line *c, char *key, int type, void *arg) * For each item, convert as appropriate and assign to 'options'. * If an item is unrecognized, return -1 immediately, * else return 0 for success. */ -static int config_assign(or_options_t *options, struct config_line *list) { +static int config_assign(or_options_t *options, struct config_line_t *list) { while(list) { if( @@ -202,7 +212,9 @@ static int config_assign(or_options_t *options, struct config_line *list) { config_compare(list, "TrafficShaping", CONFIG_TYPE_BOOL, &options->TrafficShaping) || config_compare(list, "User", CONFIG_TYPE_STRING, &options->User) || - config_compare(list, "RunTesting", CONFIG_TYPE_BOOL, &options->RunTesting) + config_compare(list, "RunTesting", CONFIG_TYPE_BOOL, &options->RunTesting) || + config_compare(list, "HiddenServiceDir", CONFIG_TYPE_LINELIST, &options->RendConfigLines) || + config_compare(list, "HiddenServicePort", CONFIG_TYPE_LINELIST, &options->RendConfigLines) ) { /* then we're ok. it matched something. */ } else { @@ -414,6 +426,7 @@ static void free_options(or_options_t *options) { tor_free(options->RecommendedVersions); tor_free(options->User); tor_free(options->Group); + config_free_lines(options->RendConfigLines); } static void init_options(or_options_t *options) { @@ -440,11 +453,12 @@ static void init_options(or_options_t *options) { options->BandwidthRate = 800000; /* at most 800kB/s total sustained incoming */ options->BandwidthBurst = 10000000; /* max burst on the token bucket */ options->NumCpus = 1; + options->RendConfigLines = NULL; } /* return 0 if success, <0 if failure. */ int getconfig(int argc, char **argv, or_options_t *options) { - struct config_line *cl; + struct config_line_t *cl; FILE *cf; char *fname; int i; @@ -632,6 +646,10 @@ int getconfig(int argc, char **argv, or_options_t *options) { result = -1; } + if (rend_config_services(options) < 0) { + result = -1; + } + return result; } diff --git a/src/or/main.c b/src/or/main.c index a9b4451ed6..a0addd9cbe 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -553,7 +553,7 @@ static int do_main_loop(void) { /* load the private keys, if we're supposed to have them, and set up the * TLS context. */ - if (init_keys() < 0) { + if (init_keys() < 0 || rend_service_init_keys() < 0) { log_fn(LOG_ERR,"Error initializing keys; exiting"); return -1; } diff --git a/src/or/or.h b/src/or/or.h index 4db5bcc00a..84ca3e0480 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -589,6 +589,7 @@ typedef struct { int NumCpus; int loglevel; int RunTesting; + struct config_line_t *RendConfigLines; } or_options_t; /* XXX are these good enough defaults? */ @@ -709,6 +710,12 @@ extern unsigned long stats_n_destroy_cells_processed; /********************************* config.c ***************************/ +struct config_line_t { + char *key; + char *value; + struct config_line_t *next; +}; + int config_assign_default_dirservers(void); int getconfig(int argc, char **argv, or_options_t *options); @@ -907,6 +914,7 @@ void set_identity_key(crypto_pk_env_t *k); crypto_pk_env_t *get_identity_key(void); crypto_pk_env_t *get_link_key(void); int init_keys(void); +crypto_pk_env_t *init_key_from_file(const char *fname); void router_retry_connections(void); void router_upload_desc_to_dirservers(void); @@ -992,6 +1000,11 @@ void rend_cache_clean(void); int rend_cache_lookup(char *query, const char **desc, int *desc_len); int rend_cache_store(char *desc, int desc_len); +/********************************* rendservice.c ***************************/ + +int rend_config_services(or_options_t *options); +int rend_service_init_keys(void); + #endif /* diff --git a/src/or/router.c b/src/or/router.c index fe1cc070c8..bf7c2247bc 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -44,7 +44,11 @@ crypto_pk_env_t *get_identity_key(void) { /************************************************************/ -static crypto_pk_env_t *init_key_from_file(const char *fname) +/* Try to read an RSA key from 'fname'. If 'fname' doesn't exist, create a new + * RSA key and save it in 'fname'. Return the read/created key, or NULL on + * error. + */ +crypto_pk_env_t *init_key_from_file(const char *fname) { crypto_pk_env_t *prkey = NULL; int fd = -1;