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