| 
					
				 | 
			
			
				@@ -556,6 +556,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   smartlist_t *old_service_list = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   smartlist_t *temp_service_list = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int ok = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int rv = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Use a temporary service list, so that we can check the new services' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    * consistency with each other */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -568,7 +569,8 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        * which is registered below the loop */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (rend_service_check_dir_and_add(temp_service_list, options, service, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                          validate_only) < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        service = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       service = tor_malloc_zero(sizeof(rend_service_t)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       service->directory = tor_strdup(line->value); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -580,8 +582,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!service) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       log_warn(LD_CONFIG, "%s with no preceding HiddenServiceDir directive", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                line->key); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!strcasecmp(line->key, "HiddenServicePort")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       char *err_msg = NULL; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -590,8 +591,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (err_msg) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           log_warn(LD_CONFIG, "%s", err_msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         tor_free(err_msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       tor_assert(!err_msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       smartlist_add(service->ports, portcfg); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -602,8 +602,8 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_warn(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  "HiddenServiceAllowUnknownPorts should be 0 or 1, not %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  line->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        smartlist_free(temp_service_list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       log_info(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                "HiddenServiceAllowUnknownPorts=%d for %s", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -617,8 +617,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             log_warn(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                      "HiddenServiceDirGroupReadable should be 0 or 1, not %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                      line->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_info(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  "HiddenServiceDirGroupReadable=%d for %s", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -631,8 +630,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_warn(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  "HiddenServiceMaxStreams should be between 0 and %d, not %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  65535, line->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       log_info(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                "HiddenServiceMaxStreams=%d for %s", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -646,8 +644,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  "HiddenServiceMaxStreamsCloseCircuit should be 0 or 1, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  "not %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  line->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       log_info(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                "HiddenServiceMaxStreamsCloseCircuit=%d for %s", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -664,8 +661,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  "should be between %d and %d, not %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  NUM_INTRO_POINTS_DEFAULT, NUM_INTRO_POINTS_MAX, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  line->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       log_info(LD_CONFIG, "HiddenServiceNumIntroductionPoints=%d for %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                service->n_intro_points_wanted, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -680,8 +676,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (service->auth_type != REND_NO_AUTH) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_warn(LD_CONFIG, "Got multiple HiddenServiceAuthorizeClient " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  "lines for a single service."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       type_names_split = smartlist_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       smartlist_split_string(type_names_split, line->value, " ", 0, 2); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -689,9 +684,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_warn(LD_BUG, "HiddenServiceAuthorizeClient has no value. This " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                          "should have been prevented when parsing the " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                          "configuration."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        smartlist_free(type_names_split); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       authname = smartlist_get(type_names_split, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (!strcasecmp(authname, "basic")) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -705,8 +698,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  (char *) smartlist_get(type_names_split, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         SMARTLIST_FOREACH(type_names_split, char *, cp, tor_free(cp)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         smartlist_free(type_names_split); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       service->clients = smartlist_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (smartlist_len(type_names_split) < 2) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -743,8 +735,7 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                    client_name, REND_CLIENTNAME_MAX_LEN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           smartlist_free(clients); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         client = tor_malloc_zero(sizeof(rend_authorized_client_t)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         client->client_name = tor_strdup(client_name); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -766,16 +757,14 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  smartlist_len(service->clients), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  service->auth_type == REND_BASIC_AUTH ? 512 : 16, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  service->auth_type == REND_BASIC_AUTH ? "basic" : "stealth"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       tor_assert(!strcasecmp(line->key, "HiddenServiceVersion")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (strcmp(line->value, "2")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_warn(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                  "The only supported HiddenServiceVersion is 2."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -784,16 +773,15 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    * within the loop. It is ok for this service to be NULL, it is ignored. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (rend_service_check_dir_and_add(temp_service_list, options, service, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                      validate_only) < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    service = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  service = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Free the newly added services if validating */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (validate_only) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    SMARTLIST_FOREACH(temp_service_list, rend_service_t *, ptr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                      rend_service_free(ptr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    smartlist_free(temp_service_list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    temp_service_list = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    rv = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    goto free_and_return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Otherwise, use the newly added services as the new service list 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -889,6 +877,12 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ free_and_return: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  SMARTLIST_FOREACH(temp_service_list, rend_service_t *, ptr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    rend_service_free(ptr)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  smartlist_free(temp_service_list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return rv; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Add the ephemeral service <b>pk</b>/<b>ports</b> if possible, using 
			 |