| 
					
				 | 
			
			
				@@ -129,6 +129,9 @@ typedef struct rend_service_t { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    * when they do, this keeps us from launching multiple simultaneous attempts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    * to connect to the same rend point. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   replaycache_t *accepted_intro_dh_parts; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** If true, we don't close circuits for making requests to unsupported 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * ports. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int allow_unknown_ports; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } rend_service_t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** A list of rend_service_t's for services run on this OP. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -397,6 +400,19 @@ rend_config_services(const or_options_t *options, int validate_only) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				        smartlist_add(service->ports, portcfg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     } else if (!strcasecmp(line->key, "HiddenServiceAllowUnknownPorts")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       service->allow_unknown_ports = (int)tor_parse_long(line->value, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                                         10, 0, 1, &ok, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       if (!ok) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         log_warn(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "HiddenServiceAllowUnknownPorts should be 0 or 1, not %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  line->value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         rend_service_free(service); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       log_info(LD_CONFIG, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "HiddenServiceAllowUnknownPorts=%d for %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (int)service->allow_unknown_ports, service->directory); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      } else if (!strcasecmp(line->key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             "HiddenServiceDirGroupReadable")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          service->dir_group_readable = (int)tor_parse_long(line->value, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3382,7 +3398,8 @@ rend_service_dump_stats(int severity) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 'circ', and look up the port and address based on conn-\>port. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Assign the actual conn-\>addr and conn-\>port. Return -2 on failure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * for which the circuit should be closed, -1 on other failure, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * or 0 for success. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3405,7 +3422,7 @@ rend_service_set_connection_addr_port(edge_connection_t *conn, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     log_warn(LD_REND, "Couldn't find any service associated with pk %s on " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              "rendezvous circuit %u; closing.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              serviceid, (unsigned)circ->base_.n_circ_id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return -2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   matching_ports = smartlist_new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3423,6 +3440,9 @@ rend_service_set_connection_addr_port(edge_connection_t *conn, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   log_info(LD_REND, "No virtual port mapping exists for port %d on service %s", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				            conn->base_.port,serviceid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (service->allow_unknown_ports) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return -2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |