|
@@ -1392,6 +1392,124 @@ connection_ap_handshake_rewrite(entry_connection_t *conn,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+connection_ap_handle_onion(entry_connection_t *conn,
|
|
|
+ socks_request_t *socks,
|
|
|
+ origin_circuit_t *circ)
|
|
|
+{
|
|
|
+ time_t now = approx_time();
|
|
|
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
|
|
|
+
|
|
|
+ /* If .onion address requests are disabled, refuse the request */
|
|
|
+ if (!conn->entry_cfg.onion_traffic) {
|
|
|
+ log_warn(LD_APP, "Onion address %s requested from a port with .onion "
|
|
|
+ "disabled", safe_str_client(socks->address));
|
|
|
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Check whether it's RESOLVE or RESOLVE_PTR. We don't handle those
|
|
|
+ * for hidden service addresses. */
|
|
|
+ if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) {
|
|
|
+ /* if it's a resolve request, fail it right now, rather than
|
|
|
+ * building all the circuits and then realizing it won't work. */
|
|
|
+ log_warn(LD_APP,
|
|
|
+ "Resolve requests to hidden services not allowed. Failing.");
|
|
|
+ connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,
|
|
|
+ 0,NULL,-1,TIME_MAX);
|
|
|
+ connection_mark_unattached_ap(conn,
|
|
|
+ END_STREAM_REASON_SOCKSPROTOCOL |
|
|
|
+ END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* If we were passed a circuit, then we need to fail. .onion addresses
|
|
|
+ * only work when we launch our own circuits for now. */
|
|
|
+ if (circ) {
|
|
|
+ log_warn(LD_CONTROL, "Attachstream to a circuit is not "
|
|
|
+ "supported for .onion addresses currently. Failing.");
|
|
|
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Look up if we have client authorization configured for this hidden
|
|
|
+ * service. If we do, associate it with the rend_data. */
|
|
|
+ rend_service_authorization_t *client_auth =
|
|
|
+ rend_client_lookup_service_authorization(socks->address);
|
|
|
+
|
|
|
+ const uint8_t *cookie = NULL;
|
|
|
+ rend_auth_type_t auth_type = REND_NO_AUTH;
|
|
|
+ if (client_auth) {
|
|
|
+ log_info(LD_REND, "Using previously configured client authorization "
|
|
|
+ "for hidden service request.");
|
|
|
+ auth_type = client_auth->auth_type;
|
|
|
+ cookie = client_auth->descriptor_cookie;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Fill in the rend_data field so we can start doing a connection to
|
|
|
+ * a hidden service. */
|
|
|
+ rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data =
|
|
|
+ rend_data_client_create(socks->address, NULL, (char *) cookie,
|
|
|
+ auth_type);
|
|
|
+ if (rend_data == NULL) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ const char *onion_address = rend_data_get_address(rend_data);
|
|
|
+ log_info(LD_REND,"Got a hidden service request for ID '%s'",
|
|
|
+ safe_str_client(onion_address));
|
|
|
+
|
|
|
+ /* Lookup the given onion address. If invalid, stop right now.
|
|
|
+ * Otherwise, we might have it in the cache or not. */
|
|
|
+ unsigned int refetch_desc = 0;
|
|
|
+ rend_cache_entry_t *entry = NULL;
|
|
|
+ const int rend_cache_lookup_result =
|
|
|
+ rend_cache_lookup_entry(onion_address, -1, &entry);
|
|
|
+ if (rend_cache_lookup_result < 0) {
|
|
|
+ switch (-rend_cache_lookup_result) {
|
|
|
+ case EINVAL:
|
|
|
+ /* We should already have rejected this address! */
|
|
|
+ log_warn(LD_BUG,"Invalid service name '%s'",
|
|
|
+ safe_str_client(onion_address));
|
|
|
+ connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
+ return -1;
|
|
|
+ case ENOENT:
|
|
|
+ /* We didn't have this; we should look it up. */
|
|
|
+ refetch_desc = 1;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ log_warn(LD_BUG, "Unknown cache lookup error %d",
|
|
|
+ rend_cache_lookup_result);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Help predict that we'll want to do hidden service circuits in the
|
|
|
+ * future. We're not sure if it will need a stable circuit yet, but
|
|
|
+ * we know we'll need *something*. */
|
|
|
+ rep_hist_note_used_internal(now, 0, 1);
|
|
|
+
|
|
|
+ /* Now we have a descriptor but is it usable or not? If not, refetch.
|
|
|
+ * Also, a fetch could have been requested if the onion address was not
|
|
|
+ * found in the cache previously. */
|
|
|
+ if (refetch_desc || !rend_client_any_intro_points_usable(entry)) {
|
|
|
+ connection_ap_mark_as_non_pending_circuit(conn);
|
|
|
+ base_conn->state = AP_CONN_STATE_RENDDESC_WAIT;
|
|
|
+ log_info(LD_REND, "Unknown descriptor %s. Fetching.",
|
|
|
+ safe_str_client(onion_address));
|
|
|
+ rend_client_refetch_v2_renddesc(rend_data);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* We have the descriptor! So launch a connection to the HS. */
|
|
|
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
|
|
|
+ log_info(LD_REND, "Descriptor is here. Great.");
|
|
|
+
|
|
|
+ /* We'll try to attach it at the next event loop, or whenever
|
|
|
+ * we call connection_ap_attach_pending() */
|
|
|
+ connection_ap_mark_as_pending_circuit(conn);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/** Connection <b>conn</b> just finished its socks handshake, or the
|
|
|
* controller asked us to take care of it. If <b>circ</b> is defined,
|
|
|
* then that's where we'll want to attach it. Otherwise we have to
|
|
@@ -1837,115 +1955,9 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
|
|
|
} else {
|
|
|
/* If we get here, it's a request for a .onion address! */
|
|
|
tor_assert(!automap);
|
|
|
-
|
|
|
- /* If .onion address requests are disabled, refuse the request */
|
|
|
- if (!conn->entry_cfg.onion_traffic) {
|
|
|
- log_warn(LD_APP, "Onion address %s requested from a port with .onion "
|
|
|
- "disabled", safe_str_client(socks->address));
|
|
|
- connection_mark_unattached_ap(conn, END_STREAM_REASON_ENTRYPOLICY);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- /* Check whether it's RESOLVE or RESOLVE_PTR. We don't handle those
|
|
|
- * for hidden service addresses. */
|
|
|
- if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) {
|
|
|
- /* if it's a resolve request, fail it right now, rather than
|
|
|
- * building all the circuits and then realizing it won't work. */
|
|
|
- log_warn(LD_APP,
|
|
|
- "Resolve requests to hidden services not allowed. Failing.");
|
|
|
- connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,
|
|
|
- 0,NULL,-1,TIME_MAX);
|
|
|
- connection_mark_unattached_ap(conn,
|
|
|
- END_STREAM_REASON_SOCKSPROTOCOL |
|
|
|
- END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- /* If we were passed a circuit, then we need to fail. .onion addresses
|
|
|
- * only work when we launch our own circuits for now. */
|
|
|
- if (circ) {
|
|
|
- log_warn(LD_CONTROL, "Attachstream to a circuit is not "
|
|
|
- "supported for .onion addresses currently. Failing.");
|
|
|
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- /* Look up if we have client authorization configured for this hidden
|
|
|
- * service. If we do, associate it with the rend_data. */
|
|
|
- rend_service_authorization_t *client_auth =
|
|
|
- rend_client_lookup_service_authorization(socks->address);
|
|
|
-
|
|
|
- const uint8_t *cookie = NULL;
|
|
|
- rend_auth_type_t auth_type = REND_NO_AUTH;
|
|
|
- if (client_auth) {
|
|
|
- log_info(LD_REND, "Using previously configured client authorization "
|
|
|
- "for hidden service request.");
|
|
|
- auth_type = client_auth->auth_type;
|
|
|
- cookie = client_auth->descriptor_cookie;
|
|
|
- }
|
|
|
-
|
|
|
- /* Fill in the rend_data field so we can start doing a connection to
|
|
|
- * a hidden service. */
|
|
|
- rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data =
|
|
|
- rend_data_client_create(socks->address, NULL, (char *) cookie,
|
|
|
- auth_type);
|
|
|
- if (rend_data == NULL) {
|
|
|
+ if (connection_ap_handle_onion(conn, socks, circ) < 0) {
|
|
|
return -1;
|
|
|
}
|
|
|
- const char *onion_address = rend_data_get_address(rend_data);
|
|
|
- log_info(LD_REND,"Got a hidden service request for ID '%s'",
|
|
|
- safe_str_client(onion_address));
|
|
|
-
|
|
|
- /* Lookup the given onion address. If invalid, stop right now.
|
|
|
- * Otherwise, we might have it in the cache or not. */
|
|
|
- unsigned int refetch_desc = 0;
|
|
|
- rend_cache_entry_t *entry = NULL;
|
|
|
- const int rend_cache_lookup_result =
|
|
|
- rend_cache_lookup_entry(onion_address, -1, &entry);
|
|
|
- if (rend_cache_lookup_result < 0) {
|
|
|
- switch (-rend_cache_lookup_result) {
|
|
|
- case EINVAL:
|
|
|
- /* We should already have rejected this address! */
|
|
|
- log_warn(LD_BUG,"Invalid service name '%s'",
|
|
|
- safe_str_client(onion_address));
|
|
|
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
|
|
|
- return -1;
|
|
|
- case ENOENT:
|
|
|
- /* We didn't have this; we should look it up. */
|
|
|
- refetch_desc = 1;
|
|
|
- break;
|
|
|
- default:
|
|
|
- log_warn(LD_BUG, "Unknown cache lookup error %d",
|
|
|
- rend_cache_lookup_result);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Help predict that we'll want to do hidden service circuits in the
|
|
|
- * future. We're not sure if it will need a stable circuit yet, but
|
|
|
- * we know we'll need *something*. */
|
|
|
- rep_hist_note_used_internal(now, 0, 1);
|
|
|
-
|
|
|
- /* Now we have a descriptor but is it usable or not? If not, refetch.
|
|
|
- * Also, a fetch could have been requested if the onion address was not
|
|
|
- * found in the cache previously. */
|
|
|
- if (refetch_desc || !rend_client_any_intro_points_usable(entry)) {
|
|
|
- connection_ap_mark_as_non_pending_circuit(conn);
|
|
|
- base_conn->state = AP_CONN_STATE_RENDDESC_WAIT;
|
|
|
- log_info(LD_REND, "Unknown descriptor %s. Fetching.",
|
|
|
- safe_str_client(onion_address));
|
|
|
- rend_client_refetch_v2_renddesc(rend_data);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* We have the descriptor! So launch a connection to the HS. */
|
|
|
- base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
|
|
|
- log_info(LD_REND, "Descriptor is here. Great.");
|
|
|
-
|
|
|
- /* We'll try to attach it at the next event loop, or whenever
|
|
|
- * we call connection_ap_attach_pending() */
|
|
|
- connection_ap_mark_as_pending_circuit(conn);
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
return 0; /* unreached but keeps the compiler happy */
|