|
@@ -216,16 +216,30 @@ rend_service_free_all(void)
|
|
rend_service_list = NULL;
|
|
rend_service_list = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
+
|
|
|
|
+ * the global rend_service_list if <b>service_list</b> is NULL.
|
|
* Return 0 on success. On failure, free <b>service</b> and return -1.
|
|
* Return 0 on success. On failure, free <b>service</b> and return -1.
|
|
* Takes ownership of <b>service</b>.
|
|
* Takes ownership of <b>service</b>.
|
|
*/
|
|
*/
|
|
static int
|
|
static int
|
|
-rend_add_service(rend_service_t *service)
|
|
+rend_add_service(smartlist_t *service_list, rend_service_t *service)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
rend_service_port_config_t *p;
|
|
rend_service_port_config_t *p;
|
|
|
|
|
|
|
|
+ smartlist_t *s_list;
|
|
|
|
+
|
|
|
|
+ if (!service_list) {
|
|
|
|
+ if (BUG(!rend_service_list)) {
|
|
|
|
+
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ s_list = rend_service_list;
|
|
|
|
+ } else {
|
|
|
|
+ s_list = service_list;
|
|
|
|
+ }
|
|
|
|
+
|
|
service->intro_nodes = smartlist_new();
|
|
service->intro_nodes = smartlist_new();
|
|
service->expiring_nodes = smartlist_new();
|
|
service->expiring_nodes = smartlist_new();
|
|
|
|
|
|
@@ -247,7 +261,8 @@ rend_add_service(rend_service_t *service)
|
|
}
|
|
}
|
|
|
|
|
|
if (service->auth_type != REND_NO_AUTH &&
|
|
if (service->auth_type != REND_NO_AUTH &&
|
|
- smartlist_len(service->clients) == 0) {
|
|
+ (!service->clients ||
|
|
|
|
+ smartlist_len(service->clients) == 0)) {
|
|
log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no "
|
|
log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no "
|
|
"clients; ignoring.",
|
|
"clients; ignoring.",
|
|
rend_service_escaped_dir(service));
|
|
rend_service_escaped_dir(service));
|
|
@@ -255,7 +270,7 @@ rend_add_service(rend_service_t *service)
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!smartlist_len(service->ports)) {
|
|
+ if (!service->ports || !smartlist_len(service->ports)) {
|
|
log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured; "
|
|
log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured; "
|
|
"ignoring.",
|
|
"ignoring.",
|
|
rend_service_escaped_dir(service));
|
|
rend_service_escaped_dir(service));
|
|
@@ -278,8 +293,9 @@ rend_add_service(rend_service_t *service)
|
|
* lock file. But this is enough to detect a simple mistake that
|
|
* lock file. But this is enough to detect a simple mistake that
|
|
* at least one person has actually made.
|
|
* at least one person has actually made.
|
|
*/
|
|
*/
|
|
- if (service->directory != NULL) {
|
|
+ if (service->directory != NULL) {
|
|
- SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr,
|
|
+
|
|
|
|
+ SMARTLIST_FOREACH(s_list, rend_service_t*, ptr,
|
|
dupe = dupe ||
|
|
dupe = dupe ||
|
|
!strcmp(ptr->directory, service->directory));
|
|
!strcmp(ptr->directory, service->directory));
|
|
if (dupe) {
|
|
if (dupe) {
|
|
@@ -290,7 +306,7 @@ rend_add_service(rend_service_t *service)
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- smartlist_add(rend_service_list, service);
|
|
+ smartlist_add(s_list, service);
|
|
log_debug(LD_REND,"Configuring service with directory \"%s\"",
|
|
log_debug(LD_REND,"Configuring service with directory \"%s\"",
|
|
service->directory);
|
|
service->directory);
|
|
for (i = 0; i < smartlist_len(service->ports); ++i) {
|
|
for (i = 0; i < smartlist_len(service->ports); ++i) {
|
|
@@ -445,16 +461,18 @@ rend_service_port_config_free(rend_service_port_config_t *p)
|
|
tor_free(p);
|
|
tor_free(p);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
+
|
|
- * list if <b>validate_only</b> is false.
|
|
+ * <b>service_list</b>, or to the global list if <b>service_list</b> is NULL.
|
|
|
|
+ * Only add the service to the list if <b>validate_only</b> is false.
|
|
* If <b>validate_only</b> is true, free the service.
|
|
* If <b>validate_only</b> is true, free the service.
|
|
* If <b>service</b> is NULL, ignore it, and return 0.
|
|
* If <b>service</b> is NULL, ignore it, and return 0.
|
|
* Returns 0 on success, and -1 on failure.
|
|
* Returns 0 on success, and -1 on failure.
|
|
* Takes ownership of <b>service</b>, either freeing it, or adding it to the
|
|
* Takes ownership of <b>service</b>, either freeing it, or adding it to the
|
|
* global service list.
|
|
* global service list.
|
|
*/
|
|
*/
|
|
-static int
|
|
+STATIC int
|
|
-rend_service_check_dir_and_add(const or_options_t *options,
|
|
+rend_service_check_dir_and_add(smartlist_t *service_list,
|
|
|
|
+ const or_options_t *options,
|
|
rend_service_t *service,
|
|
rend_service_t *service,
|
|
int validate_only)
|
|
int validate_only)
|
|
{
|
|
{
|
|
@@ -463,6 +481,22 @@ rend_service_check_dir_and_add(const or_options_t *options,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ smartlist_t *s_list = NULL;
|
|
|
|
+
|
|
|
|
+ if (!service_list) {
|
|
|
|
+ if (!rend_service_list) {
|
|
|
|
+
|
|
|
|
+ if (BUG(!validate_only)) {
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ s_list = rend_service_list;
|
|
|
|
+ } else {
|
|
|
|
+ s_list = service_list;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (rend_service_check_private_dir(options, service, !validate_only)
|
|
if (rend_service_check_private_dir(options, service, !validate_only)
|
|
< 0) {
|
|
< 0) {
|
|
rend_service_free(service);
|
|
rend_service_free(service);
|
|
@@ -474,8 +508,12 @@ rend_service_check_dir_and_add(const or_options_t *options,
|
|
return 0;
|
|
return 0;
|
|
} else {
|
|
} else {
|
|
|
|
|
|
|
|
+ * s_list can not be NULL here - if both service_list and rend_service_list
|
|
|
|
+ * are NULL, and validate_only is false, we exit earlier in the function
|
|
*/
|
|
*/
|
|
- rend_add_service(service);
|
|
+ tor_assert(s_list);
|
|
|
|
+
|
|
|
|
+ rend_add_service(s_list, service);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -504,8 +542,8 @@ rend_config_services(const or_options_t *options, int validate_only)
|
|
|
|
|
|
* this code registers every service except the last one parsed,
|
|
* this code registers every service except the last one parsed,
|
|
* which is registered below the loop */
|
|
* which is registered below the loop */
|
|
- if (rend_service_check_dir_and_add(options, service, !validate_only)
|
|
+ if (rend_service_check_dir_and_add(NULL, options, service,
|
|
- < 0) {
|
|
+ validate_only) < 0) {
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
service = tor_malloc_zero(sizeof(rend_service_t));
|
|
service = tor_malloc_zero(sizeof(rend_service_t));
|
|
@@ -715,8 +753,8 @@ rend_config_services(const or_options_t *options, int validate_only)
|
|
|
|
|
|
* this code only registers the last service, other services are registered
|
|
* this code only registers the last service, other services are registered
|
|
* within the loop */
|
|
* within the loop */
|
|
- if (rend_service_check_dir_and_add(options, service, !validate_only)
|
|
+ if (rend_service_check_dir_and_add(NULL, options, service,
|
|
- < 0) {
|
|
+ validate_only) < 0) {
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -874,7 +912,7 @@ rend_service_add_ephemeral(crypto_pk_t *pk,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- if (rend_add_service(s)) {
|
|
+ if (rend_add_service(NULL, s)) {
|
|
return RSAE_INTERNAL;
|
|
return RSAE_INTERNAL;
|
|
}
|
|
}
|
|
*service_id_out = tor_strdup(s->service_id);
|
|
*service_id_out = tor_strdup(s->service_id);
|
|
@@ -1310,6 +1348,7 @@ rend_service_check_private_dir(const or_options_t *options,
|
|
}
|
|
}
|
|
|
|
|
|
if (check_private_dir(s->directory, check_opts, options->User) < 0) {
|
|
if (check_private_dir(s->directory, check_opts, options->User) < 0) {
|
|
|
|
+ log_warn(LD_REND, "Checking service directory %s failed.", s->directory);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|