/src/tor/src/feature/client/dnsserv.c
Line | Count | Source |
1 | | /* Copyright (c) 2007-2021, The Tor Project, Inc. */ |
2 | | /* See LICENSE for licensing information */ |
3 | | |
4 | | /** |
5 | | * \file dnsserv.c |
6 | | * \brief Implements client-side DNS proxy server code. |
7 | | * |
8 | | * When a user enables the DNSPort configuration option to have their local |
9 | | * Tor client handle DNS requests, this module handles it. It functions as a |
10 | | * "DNS Server" on the client side, which client applications use. |
11 | | * |
12 | | * Inbound DNS requests are represented as entry_connection_t here (since |
13 | | * that's how Tor represents client-side streams), which are kept associated |
14 | | * with an evdns_server_request structure as exposed by Libevent's |
15 | | * evdns code. |
16 | | * |
17 | | * Upon receiving a DNS request, libevent calls our evdns_server_callback() |
18 | | * function here, which causes this module to create an entry_connection_t |
19 | | * request as appropriate. Later, when that request is answered, |
20 | | * connection_edge.c calls dnsserv_resolved() so we can finish up and tell the |
21 | | * DNS client. |
22 | | **/ |
23 | | |
24 | | #include "core/or/or.h" |
25 | | #include "feature/client/dnsserv.h" |
26 | | #include "app/config/config.h" |
27 | | #include "core/mainloop/connection.h" |
28 | | #include "core/or/connection_edge.h" |
29 | | #include "feature/control/control_events.h" |
30 | | #include "core/mainloop/mainloop.h" |
31 | | #include "core/mainloop/netstatus.h" |
32 | | #include "core/or/policies.h" |
33 | | |
34 | | #include "feature/control/control_connection_st.h" |
35 | | #include "core/or/entry_connection_st.h" |
36 | | #include "core/or/listener_connection_st.h" |
37 | | #include "core/or/socks_request_st.h" |
38 | | #include "lib/evloop/compat_libevent.h" |
39 | | |
40 | | #include <event2/dns.h> |
41 | | #include <event2/dns_compat.h> |
42 | | /* XXXX this implies we want an improved evdns */ |
43 | | #include <event2/dns_struct.h> |
44 | | |
45 | | /** Helper function: called by evdns whenever the client sends a request to our |
46 | | * DNSPort. We need to eventually answer the request <b>req</b>. |
47 | | */ |
48 | | static void |
49 | | evdns_server_callback(struct evdns_server_request *req, void *data_) |
50 | 0 | { |
51 | 0 | const listener_connection_t *listener = data_; |
52 | 0 | entry_connection_t *entry_conn; |
53 | 0 | edge_connection_t *conn; |
54 | 0 | int i = 0; |
55 | 0 | struct evdns_server_question *q = NULL, *supported_q = NULL; |
56 | 0 | struct sockaddr_storage addr; |
57 | 0 | struct sockaddr *sa; |
58 | 0 | int addrlen; |
59 | 0 | tor_addr_t tor_addr; |
60 | 0 | uint16_t port; |
61 | 0 | int err = DNS_ERR_NONE; |
62 | 0 | char *q_name; |
63 | |
|
64 | 0 | tor_assert(req); |
65 | |
|
66 | 0 | log_info(LD_APP, "Got a new DNS request!"); |
67 | | |
68 | | /* Receiving a request on the DNSPort counts as user activity. */ |
69 | 0 | note_user_activity(approx_time()); |
70 | |
|
71 | 0 | req->flags |= 0x80; /* set RA */ |
72 | | |
73 | | /* First, check whether the requesting address matches our SOCKSPolicy. */ |
74 | 0 | if ((addrlen = evdns_server_request_get_requesting_addr(req, |
75 | 0 | (struct sockaddr*)&addr, (socklen_t)sizeof(addr))) < 0) { |
76 | 0 | log_warn(LD_APP, "Couldn't get requesting address."); |
77 | 0 | evdns_server_request_respond(req, DNS_ERR_SERVERFAILED); |
78 | 0 | return; |
79 | 0 | } |
80 | 0 | (void) addrlen; |
81 | 0 | sa = (struct sockaddr*) &addr; |
82 | 0 | if (tor_addr_from_sockaddr(&tor_addr, sa, &port)<0) { |
83 | 0 | log_warn(LD_APP, "Requesting address wasn't recognized."); |
84 | 0 | evdns_server_request_respond(req, DNS_ERR_SERVERFAILED); |
85 | 0 | return; |
86 | 0 | } |
87 | | |
88 | 0 | if (!socks_policy_permits_address(&tor_addr)) { |
89 | 0 | log_warn(LD_APP, "Rejecting DNS request from disallowed IP."); |
90 | 0 | evdns_server_request_respond(req, DNS_ERR_REFUSED); |
91 | 0 | return; |
92 | 0 | } |
93 | | |
94 | | /* Now, let's find the first actual question of a type we can answer in this |
95 | | * DNS request. It makes us a little noncompliant to act like this; we |
96 | | * should fix that eventually if it turns out to make a difference for |
97 | | * anybody. */ |
98 | 0 | if (req->nquestions == 0) { |
99 | 0 | log_info(LD_APP, "No questions in DNS request; sending back nil reply."); |
100 | 0 | evdns_server_request_respond(req, 0); |
101 | 0 | return; |
102 | 0 | } |
103 | 0 | if (req->nquestions > 1) { |
104 | 0 | log_info(LD_APP, "Got a DNS request with more than one question; I only " |
105 | 0 | "handle one question at a time for now. Skipping the extras."); |
106 | 0 | } |
107 | 0 | for (i = 0; i < req->nquestions; ++i) { |
108 | 0 | if (req->questions[i]->dns_question_class != EVDNS_CLASS_INET) |
109 | 0 | continue; |
110 | 0 | switch (req->questions[i]->type) { |
111 | 0 | case EVDNS_TYPE_A: |
112 | 0 | case EVDNS_TYPE_AAAA: |
113 | 0 | case EVDNS_TYPE_PTR: |
114 | | /* We always pick the first one of these questions, if there is |
115 | | one. */ |
116 | 0 | if (! supported_q) |
117 | 0 | supported_q = req->questions[i]; |
118 | 0 | break; |
119 | 0 | default: |
120 | 0 | break; |
121 | 0 | } |
122 | 0 | } |
123 | 0 | if (supported_q) |
124 | 0 | q = supported_q; |
125 | 0 | if (!q) { |
126 | 0 | log_info(LD_APP, "None of the questions we got were ones we're willing " |
127 | 0 | "to support. Sending NOTIMPL."); |
128 | 0 | evdns_server_request_respond(req, DNS_ERR_NOTIMPL); |
129 | 0 | return; |
130 | 0 | } |
131 | | |
132 | | /* Make sure the name isn't too long: This should be impossible, I think. */ |
133 | 0 | if (err == DNS_ERR_NONE && strlen(q->name) > MAX_SOCKS_ADDR_LEN-1) |
134 | 0 | err = DNS_ERR_FORMAT; |
135 | |
|
136 | 0 | if (err != DNS_ERR_NONE || !supported_q) { |
137 | | /* We got an error? There's no question we're willing to answer? Then |
138 | | * send back an answer immediately; we're done. */ |
139 | 0 | evdns_server_request_respond(req, err); |
140 | 0 | return; |
141 | 0 | } |
142 | | |
143 | | /* Make a new dummy AP connection, and attach the request to it. */ |
144 | 0 | entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET); |
145 | 0 | conn = ENTRY_TO_EDGE_CONN(entry_conn); |
146 | 0 | CONNECTION_AP_EXPECT_NONPENDING(entry_conn); |
147 | 0 | TO_CONN(conn)->state = AP_CONN_STATE_RESOLVE_WAIT; |
148 | 0 | conn->is_dns_request = 1; |
149 | |
|
150 | 0 | tor_addr_copy(&TO_CONN(conn)->addr, &tor_addr); |
151 | 0 | TO_CONN(conn)->port = port; |
152 | 0 | TO_CONN(conn)->address = tor_addr_to_str_dup(&tor_addr); |
153 | |
|
154 | 0 | if (q->type == EVDNS_TYPE_A || q->type == EVDNS_TYPE_AAAA || |
155 | 0 | q->type == EVDNS_QTYPE_ALL) { |
156 | 0 | entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE; |
157 | 0 | } else { |
158 | 0 | tor_assert(q->type == EVDNS_TYPE_PTR); |
159 | 0 | entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; |
160 | 0 | } |
161 | | |
162 | | /* This serves our DNS port so enable DNS request by default. */ |
163 | 0 | entry_conn->entry_cfg.dns_request = 1; |
164 | 0 | if (q->type == EVDNS_TYPE_A || q->type == EVDNS_QTYPE_ALL) { |
165 | 0 | entry_conn->entry_cfg.ipv4_traffic = 1; |
166 | 0 | entry_conn->entry_cfg.ipv6_traffic = 0; |
167 | 0 | entry_conn->entry_cfg.prefer_ipv6 = 0; |
168 | 0 | } else if (q->type == EVDNS_TYPE_AAAA) { |
169 | 0 | entry_conn->entry_cfg.ipv4_traffic = 0; |
170 | 0 | entry_conn->entry_cfg.ipv6_traffic = 1; |
171 | 0 | entry_conn->entry_cfg.prefer_ipv6 = 1; |
172 | 0 | } |
173 | |
|
174 | 0 | strlcpy(entry_conn->socks_request->address, q->name, |
175 | 0 | sizeof(entry_conn->socks_request->address)); |
176 | |
|
177 | 0 | entry_conn->socks_request->listener_type = listener->base_.type; |
178 | 0 | entry_conn->dns_server_request = req; |
179 | 0 | entry_conn->entry_cfg.isolation_flags = listener->entry_cfg.isolation_flags; |
180 | 0 | entry_conn->entry_cfg.session_group = listener->entry_cfg.session_group; |
181 | 0 | entry_conn->nym_epoch = get_signewnym_epoch(); |
182 | |
|
183 | 0 | if (connection_add(ENTRY_TO_CONN(entry_conn)) < 0) { |
184 | 0 | log_warn(LD_APP, "Couldn't register dummy connection for DNS request"); |
185 | 0 | evdns_server_request_respond(req, DNS_ERR_SERVERFAILED); |
186 | 0 | connection_free_(ENTRY_TO_CONN(entry_conn)); |
187 | 0 | return; |
188 | 0 | } |
189 | | |
190 | 0 | control_event_stream_status(entry_conn, STREAM_EVENT_NEW_RESOLVE, 0); |
191 | | |
192 | | /* Now, unless a controller asked us to leave streams unattached, |
193 | | * throw the connection over to get rewritten (which will |
194 | | * answer it immediately if it's in the cache, or completely bogus, or |
195 | | * automapped), and then attached to a circuit. */ |
196 | 0 | log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", |
197 | 0 | escaped_safe_str_client(q->name)); |
198 | 0 | q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */ |
199 | 0 | connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL); |
200 | | /* Now, the connection is marked if it was bad. */ |
201 | |
|
202 | 0 | log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.", |
203 | 0 | escaped_safe_str_client(q_name)); |
204 | 0 | tor_free(q_name); |
205 | 0 | } |
206 | | |
207 | | /** Helper function: called whenever the client sends a resolve request to our |
208 | | * controller. We need to eventually answer the request <b>req</b>. |
209 | | * Returns 0 if the controller will be getting (or has gotten) an event in |
210 | | * response; -1 if we couldn't launch the request. |
211 | | */ |
212 | | int |
213 | | dnsserv_launch_request(const char *name, int reverse, |
214 | | control_connection_t *control_conn) |
215 | 0 | { |
216 | 0 | entry_connection_t *entry_conn; |
217 | 0 | edge_connection_t *conn; |
218 | 0 | char *q_name; |
219 | | |
220 | | /* Launching a request for a user counts as user activity. */ |
221 | 0 | note_user_activity(approx_time()); |
222 | | |
223 | | /* Make a new dummy AP connection, and attach the request to it. */ |
224 | 0 | entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET); |
225 | 0 | entry_conn->entry_cfg.dns_request = 1; |
226 | 0 | conn = ENTRY_TO_EDGE_CONN(entry_conn); |
227 | 0 | CONNECTION_AP_EXPECT_NONPENDING(entry_conn); |
228 | 0 | conn->base_.state = AP_CONN_STATE_RESOLVE_WAIT; |
229 | |
|
230 | 0 | tor_addr_copy(&TO_CONN(conn)->addr, &control_conn->base_.addr); |
231 | 0 | #ifdef AF_UNIX |
232 | | /* |
233 | | * The control connection can be AF_UNIX and if so tor_addr_to_str_dup will |
234 | | * unhelpfully say "<unknown address type>"; say "(Tor_internal)" |
235 | | * instead. |
236 | | */ |
237 | 0 | if (control_conn->base_.socket_family == AF_UNIX) { |
238 | 0 | TO_CONN(conn)->port = 0; |
239 | 0 | TO_CONN(conn)->address = tor_strdup("(Tor_internal)"); |
240 | 0 | } else { |
241 | 0 | TO_CONN(conn)->port = control_conn->base_.port; |
242 | 0 | TO_CONN(conn)->address = tor_addr_to_str_dup(&control_conn->base_.addr); |
243 | 0 | } |
244 | | #else /* !defined(AF_UNIX) */ |
245 | | TO_CONN(conn)->port = control_conn->base_.port; |
246 | | TO_CONN(conn)->address = tor_addr_to_str_dup(&control_conn->base_.addr); |
247 | | #endif /* defined(AF_UNIX) */ |
248 | |
|
249 | 0 | if (reverse) |
250 | 0 | entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; |
251 | 0 | else |
252 | 0 | entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE; |
253 | |
|
254 | 0 | conn->is_dns_request = 1; |
255 | |
|
256 | 0 | strlcpy(entry_conn->socks_request->address, name, |
257 | 0 | sizeof(entry_conn->socks_request->address)); |
258 | |
|
259 | 0 | entry_conn->socks_request->listener_type = CONN_TYPE_CONTROL_LISTENER; |
260 | 0 | entry_conn->original_dest_address = tor_strdup(name); |
261 | 0 | entry_conn->entry_cfg.session_group = SESSION_GROUP_CONTROL_RESOLVE; |
262 | 0 | entry_conn->nym_epoch = get_signewnym_epoch(); |
263 | 0 | entry_conn->entry_cfg.isolation_flags = ISO_DEFAULT; |
264 | |
|
265 | 0 | if (connection_add(TO_CONN(conn))<0) { |
266 | 0 | log_warn(LD_APP, "Couldn't register dummy connection for RESOLVE request"); |
267 | 0 | connection_free_(TO_CONN(conn)); |
268 | 0 | return -1; |
269 | 0 | } |
270 | | |
271 | 0 | control_event_stream_status(entry_conn, STREAM_EVENT_NEW_RESOLVE, 0); |
272 | | |
273 | | /* Now, unless a controller asked us to leave streams unattached, |
274 | | * throw the connection over to get rewritten (which will |
275 | | * answer it immediately if it's in the cache, or completely bogus, or |
276 | | * automapped), and then attached to a circuit. */ |
277 | 0 | log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", |
278 | 0 | escaped_safe_str_client(name)); |
279 | 0 | q_name = tor_strdup(name); /* q could be freed in rewrite_and_attach */ |
280 | 0 | connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL); |
281 | | /* Now, the connection is marked if it was bad. */ |
282 | |
|
283 | 0 | log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.", |
284 | 0 | escaped_safe_str_client(q_name)); |
285 | 0 | tor_free(q_name); |
286 | 0 | return 0; |
287 | 0 | } |
288 | | |
289 | | /** If there is a pending request on <b>conn</b> that's waiting for an answer, |
290 | | * send back an error and free the request. */ |
291 | | void |
292 | | dnsserv_reject_request(entry_connection_t *conn) |
293 | 0 | { |
294 | 0 | if (conn->dns_server_request) { |
295 | 0 | evdns_server_request_respond(conn->dns_server_request, |
296 | 0 | DNS_ERR_SERVERFAILED); |
297 | 0 | conn->dns_server_request = NULL; |
298 | 0 | } |
299 | 0 | } |
300 | | |
301 | | /** Look up the original name that corresponds to 'addr' in req. We use this |
302 | | * to preserve case in order to facilitate clients using 0x20-hacks to avoid |
303 | | * DNS poisoning. */ |
304 | | static const char * |
305 | | evdns_get_orig_address(const struct evdns_server_request *req, |
306 | | int rtype, const char *addr) |
307 | 0 | { |
308 | 0 | int i, type; |
309 | |
|
310 | 0 | switch (rtype) { |
311 | 0 | case RESOLVED_TYPE_IPV4: |
312 | 0 | type = EVDNS_TYPE_A; |
313 | 0 | break; |
314 | 0 | case RESOLVED_TYPE_HOSTNAME: |
315 | 0 | type = EVDNS_TYPE_PTR; |
316 | 0 | break; |
317 | 0 | case RESOLVED_TYPE_IPV6: |
318 | 0 | type = EVDNS_TYPE_AAAA; |
319 | 0 | break; |
320 | 0 | case RESOLVED_TYPE_ERROR: |
321 | 0 | case RESOLVED_TYPE_ERROR_TRANSIENT: |
322 | 0 | case RESOLVED_TYPE_NOERROR: |
323 | | /* Addr doesn't matter, since we're not sending it back in the reply.*/ |
324 | 0 | return addr; |
325 | 0 | default: |
326 | 0 | tor_fragile_assert(); |
327 | 0 | return addr; |
328 | 0 | } |
329 | | |
330 | 0 | for (i = 0; i < req->nquestions; ++i) { |
331 | 0 | const struct evdns_server_question *q = req->questions[i]; |
332 | 0 | if (q->type == type && !strcasecmp(q->name, addr)) |
333 | 0 | return q->name; |
334 | 0 | } |
335 | 0 | return addr; |
336 | 0 | } |
337 | | |
338 | | /** Tell the dns request waiting for an answer on <b>conn</b> that we have an |
339 | | * answer of type <b>answer_type</b> (RESOLVE_TYPE_IPV4/IPV6/ERR), of length |
340 | | * <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>. Doesn't do |
341 | | * any caching; that's handled elsewhere. */ |
342 | | void |
343 | | dnsserv_resolved(entry_connection_t *conn, |
344 | | int answer_type, |
345 | | size_t answer_len, |
346 | | const char *answer, |
347 | | int ttl) |
348 | 0 | { |
349 | 0 | struct evdns_server_request *req = conn->dns_server_request; |
350 | 0 | const char *name; |
351 | 0 | int err = DNS_ERR_NONE; |
352 | 0 | if (!req) |
353 | 0 | return; |
354 | 0 | name = evdns_get_orig_address(req, answer_type, |
355 | 0 | conn->socks_request->address); |
356 | | |
357 | | /* XXXX Re-do; this is dumb. */ |
358 | 0 | if (ttl < 60) |
359 | 0 | ttl = 60; |
360 | | |
361 | | /* The evdns interface is: add a bunch of reply items (corresponding to one |
362 | | * or more of the questions in the request); then, call |
363 | | * evdns_server_request_respond. */ |
364 | 0 | if (answer_type == RESOLVED_TYPE_IPV6) { |
365 | 0 | evdns_server_request_add_aaaa_reply(req, |
366 | 0 | name, |
367 | 0 | 1, answer, ttl); |
368 | 0 | } else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4 && |
369 | 0 | conn->socks_request->command == SOCKS_COMMAND_RESOLVE) { |
370 | 0 | evdns_server_request_add_a_reply(req, |
371 | 0 | name, |
372 | 0 | 1, answer, ttl); |
373 | 0 | } else if (answer_type == RESOLVED_TYPE_HOSTNAME && |
374 | 0 | answer_len < 256 && |
375 | 0 | conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR) { |
376 | 0 | char *ans = tor_strndup(answer, answer_len); |
377 | 0 | evdns_server_request_add_ptr_reply(req, NULL, |
378 | 0 | name, |
379 | 0 | ans, ttl); |
380 | 0 | tor_free(ans); |
381 | 0 | } else if (answer_type == RESOLVED_TYPE_ERROR) { |
382 | 0 | err = DNS_ERR_NOTEXIST; |
383 | 0 | } else if (answer_type == RESOLVED_TYPE_NOERROR) { |
384 | 0 | err = DNS_ERR_NONE; |
385 | 0 | } else { /* answer_type == RESOLVED_TYPE_ERROR_TRANSIENT */ |
386 | 0 | err = DNS_ERR_SERVERFAILED; |
387 | 0 | } |
388 | |
|
389 | 0 | evdns_server_request_respond(req, err); |
390 | |
|
391 | 0 | conn->dns_server_request = NULL; |
392 | 0 | } |
393 | | |
394 | | /** Set up the evdns server port for the UDP socket on <b>conn</b>, which |
395 | | * must be an AP_DNS_LISTENER */ |
396 | | void |
397 | | dnsserv_configure_listener(connection_t *conn) |
398 | 0 | { |
399 | 0 | listener_connection_t *listener_conn; |
400 | 0 | tor_assert(conn); |
401 | 0 | tor_assert(SOCKET_OK(conn->s)); |
402 | 0 | tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); |
403 | |
|
404 | 0 | listener_conn = TO_LISTENER_CONN(conn); |
405 | 0 | listener_conn->dns_server_port = |
406 | 0 | tor_evdns_add_server_port(conn->s, 0, evdns_server_callback, |
407 | 0 | listener_conn); |
408 | 0 | } |
409 | | |
410 | | /** Free the evdns server port for <b>conn</b>, which must be an |
411 | | * AP_DNS_LISTENER. */ |
412 | | void |
413 | | dnsserv_close_listener(connection_t *conn) |
414 | 0 | { |
415 | 0 | listener_connection_t *listener_conn; |
416 | 0 | tor_assert(conn); |
417 | 0 | tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); |
418 | |
|
419 | 0 | listener_conn = TO_LISTENER_CONN(conn); |
420 | |
|
421 | 0 | if (listener_conn->dns_server_port) { |
422 | 0 | evdns_close_server_port(listener_conn->dns_server_port); |
423 | | listener_conn->dns_server_port = NULL; |
424 | 0 | } |
425 | 0 | } |