aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gnunet-service-gns_interceptor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns/gnunet-service-gns_interceptor.c')
-rw-r--r--src/gns/gnunet-service-gns_interceptor.c419
1 files changed, 0 insertions, 419 deletions
diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c
deleted file mode 100644
index 255f85598..000000000
--- a/src/gns/gnunet-service-gns_interceptor.c
+++ /dev/null
@@ -1,419 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file gns/gnunet-service-gns_interceptor.c
22 * @brief GNUnet GNS interceptor logic
23 * @author Martin Schanzenbach
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_dns_service.h"
29#include "gnunet_dnsparser_lib.h"
30#include "gnunet-service-gns.h"
31#include "gnunet-service-gns_resolver.h"
32#include "gnunet-service-gns_interceptor.h"
33#include "gns.h"
34
35
36/**
37 * How deep do we allow recursions to go before we abort?
38 */
39#define MAX_RECURSION 256
40
41
42/**
43 * Handle to a DNS intercepted
44 * reslution request
45 */
46struct InterceptLookupHandle
47{
48 /**
49 * We keep these in a DLL.
50 */
51 struct InterceptLookupHandle *next;
52
53 /**
54 * We keep these in a DLL.
55 */
56 struct InterceptLookupHandle *prev;
57
58 /**
59 * the request handle to reply to
60 */
61 struct GNUNET_DNS_RequestHandle *request_handle;
62
63 /**
64 * the dns parser packet received
65 */
66 struct GNUNET_DNSPARSER_Packet *packet;
67
68 /**
69 * Handle for the lookup operation.
70 */
71 struct GNS_ResolverHandle *lookup;
72};
73
74
75/**
76 * Our handle to the DNS handler library
77 */
78static struct GNUNET_DNS_Handle *dns_handle;
79
80/**
81 * Head of the DLL.
82 */
83static struct InterceptLookupHandle *ilh_head;
84
85/**
86 * Tail of the DLL.
87 */
88static struct InterceptLookupHandle *ilh_tail;
89
90
91/**
92 * Reply to dns request with the result from our lookup.
93 *
94 * @param cls the closure to the request (an InterceptLookupHandle)
95 * @param rd_count the number of records to return
96 * @param rd the record data
97 */
98static void
99reply_to_dns (void *cls, uint32_t rd_count,
100 const struct GNUNET_GNSRECORD_Data *rd)
101{
102 struct InterceptLookupHandle *ilh = cls;
103 struct GNUNET_DNSPARSER_Packet *packet = ilh->packet;
104 struct GNUNET_DNSPARSER_Query *query = &packet->queries[0];
105 uint32_t i;
106 size_t len;
107 int ret;
108 char *buf;
109 unsigned int num_answers;
110 unsigned int skip_answers;
111 unsigned int skip_additional;
112 size_t off = 0;
113
114 /* Put records in the DNS packet */
115 num_answers = 0;
116 for (i = 0; i < rd_count; i++)
117 if (rd[i].record_type == query->type)
118 num_answers++;
119 skip_answers = 0;
120 skip_additional = 0;
121
122 {
123 struct GNUNET_DNSPARSER_Record answer_records[num_answers];
124 struct GNUNET_DNSPARSER_Record additional_records[rd_count - num_answers];
125
126 packet->answers = answer_records;
127 packet->additional_records = additional_records;
128 /* FIXME: need to handle #GNUNET_GNSRECORD_RF_SHADOW_RECORD option
129 (by ignoring records where this flag is set if there is any
130 other record of that type in the result set) */
131 for (i = 0; i < rd_count; i++)
132 {
133 if (rd[i].record_type == query->type)
134 {
135 answer_records[i - skip_answers].name = query->name;
136 answer_records[i - skip_answers].type = rd[i].record_type;
137 switch (rd[i].record_type)
138 {
139 case GNUNET_DNSPARSER_TYPE_NS:
140 case GNUNET_DNSPARSER_TYPE_CNAME:
141 case GNUNET_DNSPARSER_TYPE_PTR:
142 answer_records[i - skip_answers].data.hostname
143 = GNUNET_DNSPARSER_parse_name (rd[i].data,
144 rd[i].data_size,
145 &off);
146 if ((off != rd[i].data_size) ||
147 (NULL == answer_records[i].data.hostname))
148 {
149 GNUNET_break_op (0);
150 skip_answers++;
151 }
152 break;
153
154 case GNUNET_DNSPARSER_TYPE_SOA:
155 answer_records[i - skip_answers].data.soa
156 = GNUNET_DNSPARSER_parse_soa (rd[i].data,
157 rd[i].data_size,
158 &off);
159 if ((off != rd[i].data_size) ||
160 (NULL == answer_records[i].data.soa))
161 {
162 GNUNET_break_op (0);
163 skip_answers++;
164 }
165 break;
166
167 case GNUNET_DNSPARSER_TYPE_SRV:
168 /* FIXME: SRV is not yet supported */
169 skip_answers++;
170 break;
171
172 case GNUNET_DNSPARSER_TYPE_MX:
173 answer_records[i - skip_answers].data.mx
174 = GNUNET_DNSPARSER_parse_mx (rd[i].data,
175 rd[i].data_size,
176 &off);
177 if ((off != rd[i].data_size) ||
178 (NULL == answer_records[i].data.hostname))
179 {
180 GNUNET_break_op (0);
181 skip_answers++;
182 }
183 break;
184
185 default:
186 answer_records[i - skip_answers].data.raw.data_len = rd[i].data_size;
187 answer_records[i - skip_answers].data.raw.data = (char *) rd[i].data;
188 break;
189 }
190 GNUNET_break (0 == (rd[i - skip_answers].flags
191 & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION));
192 answer_records[i - skip_answers].expiration_time.abs_value_us =
193 rd[i].expiration_time;
194 answer_records[i - skip_answers].dns_traffic_class =
195 GNUNET_TUN_DNS_CLASS_INTERNET;
196 }
197 else
198 {
199 additional_records[i - skip_additional].name = query->name;
200 additional_records[i - skip_additional].type = rd[i].record_type;
201 switch (rd[i].record_type)
202 {
203 case GNUNET_DNSPARSER_TYPE_NS:
204 case GNUNET_DNSPARSER_TYPE_CNAME:
205 case GNUNET_DNSPARSER_TYPE_PTR:
206 additional_records[i - skip_additional].data.hostname
207 = GNUNET_DNSPARSER_parse_name (rd[i].data,
208 rd[i].data_size,
209 &off);
210 if ((off != rd[i].data_size) ||
211 (NULL == additional_records[i].data.hostname))
212 {
213 GNUNET_break_op (0);
214 skip_additional++;
215 }
216 break;
217
218 case GNUNET_DNSPARSER_TYPE_SOA:
219 additional_records[i - skip_additional].data.soa
220 = GNUNET_DNSPARSER_parse_soa (rd[i].data,
221 rd[i].data_size,
222 &off);
223 if ((off != rd[i].data_size) ||
224 (NULL == additional_records[i].data.hostname))
225 {
226 GNUNET_break_op (0);
227 skip_additional++;
228 }
229 break;
230
231 case GNUNET_DNSPARSER_TYPE_MX:
232 additional_records[i - skip_additional].data.mx
233 = GNUNET_DNSPARSER_parse_mx (rd[i].data,
234 rd[i].data_size,
235 &off);
236 if ((off != rd[i].data_size) ||
237 (NULL == additional_records[i].data.hostname))
238 {
239 GNUNET_break_op (0);
240 skip_additional++;
241 }
242 break;
243
244 case GNUNET_DNSPARSER_TYPE_SRV:
245 /* FIXME: SRV is not yet supported */
246 skip_answers++;
247 break;
248
249 default:
250 additional_records[i - skip_additional].data.raw.data_len =
251 rd[i].data_size;
252 additional_records[i - skip_additional].data.raw.data =
253 (char *) rd[i].data;
254 break;
255 }
256 GNUNET_break (0 == (rd[i - skip_additional].flags
257 & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION));
258 additional_records[i - skip_additional].expiration_time.abs_value_us =
259 rd[i].expiration_time;
260 additional_records[i - skip_additional].dns_traffic_class =
261 GNUNET_TUN_DNS_CLASS_INTERNET;
262 }
263 }
264 packet->num_answers = num_answers - skip_answers;
265 packet->num_additional_records = rd_count - num_answers - skip_additional;
266 packet->flags.authoritative_answer = 1;
267 if (NULL == rd)
268 packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NAME_ERROR;
269 else
270 packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR;
271 packet->flags.query_or_response = 1;
272 ret = GNUNET_DNSPARSER_pack (packet,
273 1024, /* maximum allowed size for DNS reply */
274 &buf,
275 &len);
276 if (GNUNET_OK != ret)
277 {
278 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
279 _ ("Error converting GNS response to DNS response!\n"));
280 if (GNUNET_NO == ret)
281 GNUNET_free (buf);
282 }
283 else
284 {
285 GNUNET_DNS_request_answer (ilh->request_handle,
286 len,
287 buf);
288 GNUNET_free (buf);
289 }
290 packet->num_answers = 0;
291 packet->answers = NULL;
292 packet->num_additional_records = 0;
293 packet->additional_records = NULL;
294 GNUNET_DNSPARSER_free_packet (packet);
295 }
296 GNUNET_CONTAINER_DLL_remove (ilh_head, ilh_tail, ilh);
297 GNUNET_free (ilh);
298}
299
300
301/**
302 * The DNS request handler. Called for every incoming DNS request.
303 *
304 * @param cls closure, unused
305 * @param rh request handle to user for reply
306 * @param request_length number of bytes in @a request
307 * @param request UDP payload of the DNS request
308 */
309static void
310handle_dns_request (void *cls,
311 struct GNUNET_DNS_RequestHandle *rh,
312 size_t request_length,
313 const char *request)
314{
315 struct GNUNET_DNSPARSER_Packet *p;
316 struct InterceptLookupHandle *ilh;
317 struct GNUNET_IDENTITY_PublicKey zone;
318
319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
320 "Hijacked a DNS request. Processing.\n");
321 if (NULL == (p = GNUNET_DNSPARSER_parse (request, request_length)))
322 {
323 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
324 "Received malformed DNS packet, leaving it untouched.\n");
325 GNUNET_DNS_request_forward (rh);
326 return;
327 }
328
329 /* Check TLD and decide if we or legacy dns is responsible */
330 if (1 != p->num_queries)
331 {
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
333 "Not exactly one query in DNS packet. Forwarding untouched.\n");
334 GNUNET_DNS_request_forward (rh);
335 GNUNET_DNSPARSER_free_packet (p);
336 return;
337 }
338
339 /* Check for GNS TLDs. */
340 if (GNUNET_YES ==
341 GNS_find_tld (GNS_get_tld (p->queries[0].name),
342 &zone))
343 {
344 /* Start resolution in GNS */
345 ilh = GNUNET_new (struct InterceptLookupHandle);
346 GNUNET_CONTAINER_DLL_insert (ilh_head,
347 ilh_tail,
348 ilh);
349 ilh->packet = p;
350 ilh->request_handle = rh;
351 ilh->lookup = GNS_resolver_lookup (&zone,
352 p->queries[0].type,
353 p->queries[0].name,
354 GNUNET_GNS_LO_DEFAULT,
355 MAX_RECURSION,
356 &reply_to_dns, ilh);
357 return;
358 }
359 /* This request does not concern us. Forward to real DNS. */
360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
361 "Request for `%s' is forwarded to DNS untouched.\n",
362 p->queries[0].name);
363 GNUNET_DNS_request_forward (rh);
364 GNUNET_DNSPARSER_free_packet (p);
365}
366
367
368/**
369 * Initialized the interceptor
370 *
371 * @param c the configuration
372 * @return #GNUNET_OK on success
373 */
374int
375GNS_interceptor_init (const struct GNUNET_CONFIGURATION_Handle *c)
376{
377 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
378 "DNS hijacking enabled. Connecting to DNS service.\n");
379 dns_handle = GNUNET_DNS_connect (c,
380 GNUNET_DNS_FLAG_PRE_RESOLUTION,
381 &handle_dns_request,
382 NULL);
383 if (NULL == dns_handle)
384 {
385 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
386 _ ("Failed to connect to the DNS service!\n"));
387 return GNUNET_SYSERR;
388 }
389 return GNUNET_YES;
390}
391
392
393/**
394 * Disconnect from interceptor
395 */
396void
397GNS_interceptor_done ()
398{
399 struct InterceptLookupHandle *ilh;
400
401 while (NULL != (ilh = ilh_head))
402 {
403 GNUNET_CONTAINER_DLL_remove (ilh_head,
404 ilh_tail,
405 ilh);
406 GNS_resolver_lookup_cancel (ilh->lookup);
407 GNUNET_DNS_request_drop (ilh->request_handle);
408 GNUNET_DNSPARSER_free_packet (ilh->packet);
409 GNUNET_free (ilh);
410 }
411 if (NULL != dns_handle)
412 {
413 GNUNET_DNS_disconnect (dns_handle);
414 dns_handle = NULL;
415 }
416}
417
418
419/* end of gnunet-service-gns_interceptor.c */