1 /**
2 *
3 * /brief getdns contect management functions
4 *
5 * This is the meat of the API
6 * Originally taken from the getdns API description pseudo implementation.
7 *
8 */
9 /*
10 * Copyright (c) 2013, NLnet Labs, Verisign, Inc.
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * * Neither the names of the copyright holders nor the
21 * names of its contributors may be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
28 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include "config.h"
37 #include "types-internal.h"
38 #include "util-internal.h"
39 #include "gldns/rrdef.h"
40 #include "gldns/str2wire.h"
41 #include "gldns/gbuffer.h"
42 #include "gldns/pkthdr.h"
43 #include "dict.h"
44 #include "debug.h"
45 #include "convert.h"
46 #include "general.h"
47 #include "tls.h"
48
49 /* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256
50 * TSIG type (uint16_t) : 2
51 * TSIG class (uint16_t) : 2
52 * TSIG TTL (uint32_t) : 4
53 * RdLen (uint16_t) : 2
54 * Algorithm name (dname) : 256
55 * Time Signed (uint48_t) : 6
56 * Fudge (uint16_t) : 2
57 * Mac Size (uint16_t) : 2
58 * Mac (variable) : GETDNS_TLS_MAX_DIGEST_LENGTH
59 * Original Id (uint16_t) : 2
60 * Error (uint16_t) : 2
61 * Other Len (uint16_t) : 2
62 * Other Data (nothing) : 0
63 * ---- +
64 * 538 + GETDNS_TLS_MAX_DIGEST_LENGTH
65 */
66 #define MAXIMUM_TSIG_SPACE (538 + GETDNS_TLS_MAX_DIGEST_LENGTH)
67
68 getdns_dict dnssec_ok_checking_disabled_spc = {
69 { RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
70 { NULL, {{ NULL, NULL, NULL }}}
71 };
72 getdns_dict *dnssec_ok_checking_disabled = &dnssec_ok_checking_disabled_spc;
73
74 getdns_dict dnssec_ok_checking_disabled_roadblock_avoidance_spc = {
75 { RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
76 { NULL, {{ NULL, NULL, NULL }}}
77 };
78 getdns_dict *dnssec_ok_checking_disabled_roadblock_avoidance
79 = &dnssec_ok_checking_disabled_roadblock_avoidance_spc;
80
81 getdns_dict dnssec_ok_checking_disabled_avoid_roadblocks_spc = {
82 { RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
83 { NULL, {{ NULL, NULL, NULL }}}
84 };
85 getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks
86 = &dnssec_ok_checking_disabled_avoid_roadblocks_spc;
87
88 getdns_dict no_dnssec_checking_disabled_opportunistic_spc = {
89 { RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
90 { NULL, {{ NULL, NULL, NULL }}}
91 };
92 getdns_dict *no_dnssec_checking_disabled_opportunistic
93 = &no_dnssec_checking_disabled_opportunistic_spc;
94
95 static int
is_extension_set(const getdns_dict * extensions,const char * name,int default_value)96 is_extension_set(const getdns_dict *extensions, const char *name, int default_value)
97 {
98 getdns_return_t r;
99 uint32_t value;
100
101 if ( ! extensions
102 || extensions == dnssec_ok_checking_disabled
103 || extensions == dnssec_ok_checking_disabled_roadblock_avoidance
104 || extensions == dnssec_ok_checking_disabled_avoid_roadblocks
105 || extensions == no_dnssec_checking_disabled_opportunistic)
106 return 0;
107
108 r = getdns_dict_get_int(extensions, name, &value);
109 return r == GETDNS_RETURN_GOOD ? ( value == GETDNS_EXTENSION_TRUE )
110 : default_value;
111 }
112
113 static void
network_req_cleanup(getdns_network_req * net_req)114 network_req_cleanup(getdns_network_req *net_req)
115 {
116 assert(net_req);
117
118 if (net_req->query_id_registered) {
119 (void) _getdns_rbtree_delete(
120 net_req->query_id_registered, net_req->node.key);
121 net_req->query_id_registered = NULL;
122 net_req->node.key = NULL;
123 }
124 if (net_req->response && (net_req->response < net_req->wire_data ||
125 net_req->response > net_req->wire_data+ net_req->wire_data_sz))
126 GETDNS_FREE(net_req->owner->my_mf, net_req->response);
127 if (net_req->debug_tls_peer_cert.size &&
128 net_req->debug_tls_peer_cert.data)
129 GETDNS_FREE(net_req->owner->my_mf, net_req->debug_tls_peer_cert.data);
130 }
131
132 static uint8_t *
netreq_reset(getdns_network_req * net_req)133 netreq_reset(getdns_network_req *net_req)
134 {
135 uint8_t *buf;
136 /* variables that need to be reset on reinit
137 */
138 net_req->first_upstream = NULL;
139 net_req->unbound_id = -1;
140 _getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT);
141 if (net_req->query_id_registered) {
142 (void) _getdns_rbtree_delete(net_req->query_id_registered,
143 (void *)(intptr_t)GLDNS_ID_WIRE(net_req->query));
144 net_req->query_id_registered = NULL;
145 net_req->node.key = NULL;
146 }
147 net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
148 net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
149 net_req->response_len = 0;
150 /* Some fields to record info for return_call_reporting */
151 net_req->debug_start_time = 0;
152 net_req->debug_end_time = 0;
153 if (!net_req->query)
154 return NULL;
155
156 buf = net_req->query + GLDNS_HEADER_SIZE;
157 (void) memcpy(buf, net_req->owner->name, net_req->owner->name_len);
158 buf += net_req->owner->name_len;
159
160 gldns_write_uint16(buf, net_req->request_type);
161 gldns_write_uint16(buf + 2, net_req->owner->request_class);
162 return buf + 4;
163 }
164
165 static int
network_req_init(getdns_network_req * net_req,getdns_dns_req * owner,uint16_t request_type,int checking_disabled,int opportunistic,int with_opt,int edns_maximum_udp_payload_size,uint8_t edns_extended_rcode,uint8_t edns_version,int edns_do_bit,uint16_t opt_options_size,size_t noptions,getdns_list * options,size_t wire_data_sz,size_t max_query_sz,const getdns_dict * extensions)166 network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
167 uint16_t request_type, int checking_disabled, int opportunistic,
168 int with_opt, int edns_maximum_udp_payload_size,
169 uint8_t edns_extended_rcode, uint8_t edns_version, int edns_do_bit,
170 uint16_t opt_options_size, size_t noptions, getdns_list *options,
171 size_t wire_data_sz, size_t max_query_sz, const getdns_dict *extensions)
172 {
173 uint8_t *buf;
174 getdns_dict *option;
175 uint32_t option_code;
176 getdns_bindata *option_data;
177 size_t i;
178 int r = 0;
179 gldns_buffer gbuf;
180
181 /* variables that stay the same on reinit, don't touch
182 */
183 net_req->request_type = request_type;
184 net_req->owner = owner;
185 net_req->edns_maximum_udp_payload_size = edns_maximum_udp_payload_size;
186 net_req->max_udp_payload_size = edns_maximum_udp_payload_size != -1
187 ? edns_maximum_udp_payload_size : 1432;
188 net_req->base_query_option_sz = opt_options_size;
189 net_req->wire_data_sz = wire_data_sz;
190
191 net_req->transport_count = owner->context->dns_transport_count;
192 memcpy(net_req->transports, owner->context->dns_transports,
193 net_req->transport_count * sizeof(getdns_transport_list_t));
194 net_req->tls_auth_min =
195 owner->context->tls_auth == GETDNS_AUTHENTICATION_REQUIRED
196 && owner->context->dns_transport_count == 1
197 && owner->context->dns_transports[0] == GETDNS_TRANSPORT_TLS
198 && !opportunistic
199 ? GETDNS_AUTHENTICATION_REQUIRED
200 : GETDNS_AUTHENTICATION_NONE;
201
202 net_req->follow_redirects = owner->context->follow_redirects;
203
204 /* state variables from the resolver, don't touch
205 */
206 net_req->upstream = NULL;
207 net_req->fd = -1;
208 net_req->transport_current = 0;
209 memset(&net_req->event, 0, sizeof(net_req->event));
210 net_req->keepalive_sent = 0;
211 net_req->write_queue_tail = NULL;
212 /* Some fields to record info for return_call_reporting */
213 net_req->debug_tls_auth_status = GETDNS_AUTH_NONE;
214 net_req->debug_tls_peer_cert.size = 0;
215 net_req->debug_tls_peer_cert.data = NULL;
216 net_req->debug_tls_version = NULL;
217 net_req->debug_udp = 0;
218
219 /* Scheduling, touch only via _getdns_netreq_change_state!
220 */
221 net_req->state = NET_REQ_NOT_SENT;
222 /* A registered netreq (on a statefull transport)
223 * Deregister on reset and cleanup.
224 */
225 net_req->query_id_registered = NULL;
226 net_req->node.key = NULL;
227
228 if (max_query_sz == 0) {
229 net_req->query = NULL;
230 net_req->opt = NULL;
231 net_req->response = net_req->wire_data;
232 netreq_reset(net_req);
233 return r;
234 }
235 /* first two bytes will contain query length (for tcp) */
236 net_req->query = net_req->wire_data + 2;
237
238 buf = net_req->query;
239 gldns_write_uint16(buf + 2, 0); /* reset all flags */
240 GLDNS_RD_SET(buf);
241 GLDNS_OPCODE_SET(buf, GLDNS_PACKET_QUERY);
242 gldns_write_uint16(buf + GLDNS_QDCOUNT_OFF, 1); /* 1 query */
243 gldns_write_uint16(buf + GLDNS_ANCOUNT_OFF, 0); /* 0 answers */
244 gldns_write_uint16(buf + GLDNS_NSCOUNT_OFF, 0); /* 0 authorities */
245 gldns_write_uint16(buf + GLDNS_ARCOUNT_OFF, with_opt ? 1 : 0);
246
247 buf = netreq_reset(net_req);
248 gldns_buffer_init_frm_data(
249 &gbuf, net_req->query, net_req->wire_data_sz - 2);
250 if (owner->context->header)
251 _getdns_reply_dict2wire(owner->context->header, &gbuf, 1);
252 gldns_buffer_rewind(&gbuf);
253 _getdns_reply_dict2wire(extensions, &gbuf, 1);
254 if (checking_disabled) /* We will do validation ourselves */
255 GLDNS_CD_SET(net_req->query);
256
257 if (with_opt) {
258 net_req->opt = buf;
259 buf[0] = 0; /* dname for . */
260 gldns_write_uint16(buf + 1, GLDNS_RR_TYPE_OPT);
261 gldns_write_uint16(net_req->opt + 3,
262 net_req->max_udp_payload_size);
263 buf[5] = edns_extended_rcode;
264 buf[6] = edns_version;
265 buf[7] = edns_do_bit ? 0x80 : 0;
266 buf[8] = 0;
267 gldns_write_uint16(buf + 9, opt_options_size);
268 buf += 11;
269 for (i = 0; i < noptions; i++) {
270 if (getdns_list_get_dict(options, i, &option))
271 continue;
272 if (getdns_dict_get_int(
273 option, "option_code", &option_code))
274 continue;
275 if (getdns_dict_get_bindata(
276 option, "option_data", &option_data))
277 continue;
278
279 gldns_write_uint16(buf, (uint16_t) option_code);
280 gldns_write_uint16(buf + 2,
281 (uint16_t) option_data->size);
282 (void) memcpy(buf + 4, option_data->data,
283 option_data->size);
284
285 buf += option_data->size + 4;
286 }
287 } else
288 net_req->opt = NULL;
289
290 net_req->response = buf;
291 gldns_write_uint16(net_req->wire_data, net_req->response - net_req->query);
292
293 return r;
294 }
295
296 /* req->opt + 9 is the length; req->opt + 11 is the start of the
297 options.
298
299 clear_upstream_options() goes back to the per-query options.
300 */
301
302 void
_getdns_network_req_clear_upstream_options(getdns_network_req * req)303 _getdns_network_req_clear_upstream_options(getdns_network_req * req)
304 {
305 size_t pktlen;
306 if (req->opt) {
307 gldns_write_uint16(req->opt + 9, (uint16_t) req->base_query_option_sz);
308 req->response = req->opt + 11 + req->base_query_option_sz;
309 pktlen = req->response - req->query;
310 gldns_write_uint16(req->query - 2, (uint16_t) pktlen);
311 }
312 }
313
314 void
_getdns_netreq_reinit(getdns_network_req * netreq)315 _getdns_netreq_reinit(getdns_network_req *netreq)
316 {
317 uint8_t *base_opt_backup;
318 size_t base_opt_rr_sz;
319
320 if (!netreq->query) {
321 (void) netreq_reset(netreq);
322 return;
323
324 } else if (!netreq->opt) {
325 /* Remove TSIG (if any) */
326 gldns_write_uint16(netreq->query + GLDNS_ARCOUNT_OFF, 0);
327 netreq->response = netreq_reset(netreq);
328 gldns_write_uint16(netreq->wire_data,
329 netreq->response - netreq->query);
330 return;
331 }
332 _getdns_network_req_clear_upstream_options(netreq);
333 base_opt_rr_sz = netreq->base_query_option_sz + 11;
334 base_opt_backup = netreq->wire_data + netreq->wire_data_sz
335 - base_opt_rr_sz;
336 (void) memcpy(base_opt_backup, netreq->opt, base_opt_rr_sz);
337 netreq->opt = netreq_reset(netreq);
338 (void) memcpy(netreq->opt, base_opt_backup, base_opt_rr_sz);
339 netreq->response = netreq->opt + base_opt_rr_sz;
340 /* Remove TSIG (if any), but leave the opt RR */
341 gldns_write_uint16(netreq->query + GLDNS_ARCOUNT_OFF, 1);
342 gldns_write_uint16(netreq->wire_data,
343 netreq->response - netreq->query);
344 }
345
346
347 /* add_upstream_option appends an option that is derived at send time.
348 (you can send data as NULL and it will fill with all zeros) */
349 getdns_return_t
_getdns_network_req_add_upstream_option(getdns_network_req * req,uint16_t code,uint16_t sz,const void * data)350 _getdns_network_req_add_upstream_option(getdns_network_req * req, uint16_t code, uint16_t sz, const void* data)
351 {
352 uint16_t oldlen;
353 uint32_t newlen;
354 uint32_t pktlen;
355 size_t cur_upstream_option_sz;
356
357 /* if no options are set, we can't add upstream options */
358 if (!req->opt)
359 return GETDNS_RETURN_GENERIC_ERROR;
360
361 /* if TCP, no overflow allowed for length field
362 https://tools.ietf.org/html/rfc1035#section-4.2.2 */
363 pktlen = req->response - req->query;
364 pktlen += 4 + sz;
365 if (pktlen > UINT16_MAX)
366 return GETDNS_RETURN_GENERIC_ERROR;
367
368 /* no overflow allowed for OPT size either (maybe this is overkill
369 given the above check?) */
370 oldlen = gldns_read_uint16(req->opt + 9);
371 newlen = oldlen + 4 + sz;
372 if (newlen > UINT16_MAX)
373 return GETDNS_RETURN_GENERIC_ERROR;
374
375 /* avoid overflowing MAXIMUM_UPSTREAM_OPTION_SPACE */
376 cur_upstream_option_sz = (size_t)oldlen - req->base_query_option_sz;
377 if (cur_upstream_option_sz + 4 + sz > MAXIMUM_UPSTREAM_OPTION_SPACE)
378 return GETDNS_RETURN_GENERIC_ERROR;
379
380 /* actually add the option: */
381 gldns_write_uint16(req->opt + 11 + oldlen, code);
382 gldns_write_uint16(req->opt + 11 + oldlen + 2, sz);
383 if (data != NULL)
384 memcpy(req->opt + 11 + oldlen + 4, data, sz);
385 else
386 memset(req->opt + 11 + oldlen + 4, 0, sz);
387 gldns_write_uint16(req->opt + 9, newlen);
388
389 /* the response should start right after the options end: */
390 req->response = req->opt + 11 + newlen;
391
392 /* for TCP, adjust the size of the wire format itself: */
393 gldns_write_uint16(req->query - 2, pktlen);
394
395 return GETDNS_RETURN_GOOD;
396 }
397
398 size_t
_getdns_network_req_add_tsig(getdns_network_req * req)399 _getdns_network_req_add_tsig(getdns_network_req *req)
400 {
401 getdns_upstream *upstream = req->upstream;
402 gldns_buffer gbuf;
403 uint16_t arcount;
404 const getdns_tsig_info *tsig_info;
405 unsigned char* md_buf;
406 size_t md_len;
407
408 /* Should only be called when in stub mode */
409 assert(req->query);
410
411 if (upstream->tsig_alg == GETDNS_NO_TSIG || !upstream->tsig_dname_len)
412 return req->response - req->query;
413
414 arcount = gldns_read_uint16(req->query + 10);
415
416 #if defined(STUB_DEBUG) && STUB_DEBUG
417 /* TSIG should not have been written yet. */
418 if (req->opt) {
419 assert(arcount == 1);
420 assert(req->opt + 11 + gldns_read_uint16(req->opt + 9)
421 == req->response);
422 } else
423 assert(arcount == 0);
424 #endif
425 tsig_info = _getdns_get_tsig_info(upstream->tsig_alg);
426
427 gldns_buffer_init_vfixed_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE);
428 gldns_buffer_write(&gbuf,
429 upstream->tsig_dname, upstream->tsig_dname_len); /* Name */
430 gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */
431 gldns_buffer_write_u32(&gbuf, 0); /* TTL */
432 gldns_buffer_write(&gbuf,
433 tsig_info->dname, tsig_info->dname_len); /* Algorithm Name */
434 gldns_buffer_write_u48(&gbuf, time(NULL)); /* Time Signed */
435 gldns_buffer_write_u16(&gbuf, 300); /* Fudge */
436 gldns_buffer_write_u16(&gbuf, 0); /* Error */
437 gldns_buffer_write_u16(&gbuf, 0); /* Other len */
438
439 md_buf = _getdns_tls_hmac_hash(&req->owner->my_mf, upstream->tsig_alg, upstream->tsig_key, upstream->tsig_size, (void *)req->query, gldns_buffer_current(&gbuf) - req->query, &md_len);
440 if (!md_buf)
441 return req->response - req->query;
442
443 gldns_buffer_rewind(&gbuf);
444 gldns_buffer_write(&gbuf,
445 upstream->tsig_dname, upstream->tsig_dname_len); /* Name */
446 gldns_buffer_write_u16(&gbuf, GETDNS_RRTYPE_TSIG); /* Type*/
447 gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */
448 gldns_buffer_write_u32(&gbuf, 0); /* TTL */
449 gldns_buffer_write_u16(&gbuf,
450 (uint16_t)(tsig_info->dname_len + 10 + md_len + 6)); /* RdLen */
451 gldns_buffer_write(&gbuf,
452 tsig_info->dname, tsig_info->dname_len); /* Algorithm Name */
453 gldns_buffer_write_u48(&gbuf, time(NULL)); /* Time Signed */
454 gldns_buffer_write_u16(&gbuf, 300); /* Fudge */
455 gldns_buffer_write_u16(&gbuf, md_len); /* MAC Size */
456 gldns_buffer_write(&gbuf, md_buf, md_len); /* MAC*/
457 gldns_buffer_write(&gbuf, req->query, 2); /* Original ID */
458 gldns_buffer_write_u16(&gbuf, 0); /* Error */
459 gldns_buffer_write_u16(&gbuf, 0); /* Other len */
460
461 GETDNS_FREE(req->owner->my_mf, md_buf);
462
463 if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
464 return req->response - req->query;
465
466 DEBUG_STUB("Sending with TSIG, mac length: %d\n", (int)md_len);
467 req->tsig_status = GETDNS_DNSSEC_INSECURE;
468 gldns_write_uint16(req->query + 10, arcount + 1);
469 req->response = gldns_buffer_current(&gbuf);
470 return req->response - req->query;
471 }
472
473
474
475 void
_getdns_network_validate_tsig(getdns_network_req * req)476 _getdns_network_validate_tsig(getdns_network_req *req)
477 {
478 #if defined(HAVE_NSS) || defined(HAVE_NETTLE)
479 (void)req;
480 #else
481 _getdns_rr_iter rr_spc, *rr;
482 _getdns_rdf_iter rdf_spc, *rdf;
483 const uint8_t *request_mac;
484 uint16_t request_mac_len;
485 uint8_t tsig_vars[MAXIMUM_TSIG_SPACE];
486 gldns_buffer gbuf;
487 const uint8_t *dname;
488 size_t dname_len;
489 const uint8_t *response_mac;
490 uint16_t response_mac_len;
491 uint8_t other_len;
492 unsigned char *result_mac;
493 size_t result_mac_len;
494 uint16_t original_id;
495 _getdns_tls_hmac *hmac;
496
497 DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__);
498 for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
499 (req->response - req->query))
500 ; rr
501 ; rr = _getdns_rr_iter_next(rr)) {
502
503 if (_getdns_rr_iter_section(rr) == SECTION_ADDITIONAL &&
504 gldns_read_uint16(rr->rr_type) == GETDNS_RRTYPE_TSIG)
505 break;
506 }
507 if (!rr || !(rdf = _getdns_rdf_iter_init_at(&rdf_spc, rr, 3)))
508 return; /* No good TSIG sent, so nothing expected on reply */
509
510 request_mac_len = gldns_read_uint16(rdf->pos);
511 if (request_mac_len != rdf->nxt - rdf->pos - 2)
512 return;
513 DEBUG_STUB("%s %-35s: Request MAC found length %d\n",
514 STUB_DEBUG_TSIG, __FUNC__, (int)(request_mac_len));
515
516 request_mac = rdf->pos + 2;
517
518 /* Now we expect a TSIG on the response! */
519 req->tsig_status = GETDNS_DNSSEC_BOGUS;
520
521 for ( rr = _getdns_rr_iter_init(
522 &rr_spc, req->response, req->response_len)
523 ; rr
524 ; rr = _getdns_rr_iter_next(rr)) {
525
526 if (_getdns_rr_iter_section(rr) == SECTION_ADDITIONAL &&
527 gldns_read_uint16(rr->rr_type) == GETDNS_RRTYPE_TSIG)
528 break;
529 }
530 if (!rr || !(rdf = _getdns_rdf_iter_init(&rdf_spc, rr)))
531 return;
532 gldns_buffer_init_frm_data(&gbuf, tsig_vars, MAXIMUM_TSIG_SPACE);
533
534 dname_len = gldns_buffer_remaining(&gbuf);
535 if (!(dname = _getdns_owner_if_or_as_decompressed(
536 rr, gldns_buffer_current(&gbuf), &dname_len)))
537 return;
538 if (dname == gldns_buffer_current(&gbuf))
539 gldns_buffer_skip(&gbuf, dname_len);
540 else
541 gldns_buffer_write(&gbuf, dname, dname_len);
542
543 gldns_buffer_write(&gbuf, rr->rr_type + 2, 2); /* Class */
544 gldns_buffer_write(&gbuf, rr->rr_type + 4, 4); /* TTL */
545
546 dname_len = gldns_buffer_remaining(&gbuf);
547 if (!(dname = _getdns_rdf_if_or_as_decompressed(
548 rdf, gldns_buffer_current(&gbuf), &dname_len)))
549 return;
550 if (dname == gldns_buffer_current(&gbuf))
551 gldns_buffer_skip(&gbuf, dname_len);
552 else
553 gldns_buffer_write(&gbuf, dname, dname_len);
554
555 if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
556 rdf->nxt - rdf->pos != 6)
557 return;
558 gldns_buffer_write(&gbuf, rdf->pos, 6); /* Time Signed */
559
560 if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
561 rdf->nxt - rdf->pos != 2)
562 return;
563 gldns_buffer_write(&gbuf, rdf->pos, 2); /* Fudge */
564
565 if (!(rdf = _getdns_rdf_iter_next(rdf))) /* mac */
566 return;
567 response_mac_len = gldns_read_uint16(rdf->pos);
568 if (response_mac_len != rdf->nxt - rdf->pos - 2)
569 return;
570 DEBUG_STUB("%s %-35s: Response MAC found length: %d\n",
571 STUB_DEBUG_TSIG, __FUNC__, (int)(response_mac_len));
572 response_mac = rdf->pos + 2;
573
574 if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
575 rdf->nxt -rdf->pos != 2) /* Original ID */
576 return;
577 original_id = gldns_read_uint16(rdf->pos);
578
579 if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
580 rdf->nxt - rdf->pos != 2)
581 return;
582 gldns_buffer_write(&gbuf, rdf->pos, 2); /* Error */
583
584 if (!(rdf = _getdns_rdf_iter_next(rdf))) /* Other */
585 return;
586
587 gldns_buffer_write_u16(&gbuf, 0); /* Other len */
588 other_len = (uint8_t) gldns_read_uint16(rdf->pos);
589 if (other_len != rdf->nxt - rdf->pos - 2)
590 return;
591 if (other_len)
592 gldns_buffer_write(&gbuf, rdf->pos, other_len);
593
594 /* TSIG found */
595 DEBUG_STUB("%s %-35s: TSIG found, original ID: %d\n",
596 STUB_DEBUG_TSIG, __FUNC__, (int)original_id);
597
598 gldns_write_uint16(req->response + 10,
599 gldns_read_uint16(req->response + 10) - 1);
600 gldns_write_uint16(req->response, original_id);
601
602 hmac = _getdns_tls_hmac_new(&req->owner->my_mf, req->upstream->tsig_alg, req->upstream->tsig_key, req->upstream->tsig_size);
603 if (!hmac)
604 return;
605
606 _getdns_tls_hmac_add(hmac, request_mac - 2, request_mac_len + 2);
607 _getdns_tls_hmac_add(hmac, req->response, rr->pos - req->response);
608 _getdns_tls_hmac_add(hmac, tsig_vars, gldns_buffer_position(&gbuf));
609 result_mac = _getdns_tls_hmac_end(&req->owner->my_mf, hmac, &result_mac_len);
610 if (!result_mac)
611 return;
612
613 DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
614 STUB_DEBUG_TSIG, __FUNC__, (int)(result_mac_len));
615 if (result_mac_len == response_mac_len &&
616 memcmp(result_mac, response_mac, result_mac_len) == 0)
617 req->tsig_status = GETDNS_DNSSEC_SECURE;
618
619 GETDNS_FREE(req->owner->my_mf, result_mac);
620
621 gldns_write_uint16(req->response, gldns_read_uint16(req->query));
622 gldns_write_uint16(req->response + 10,
623 gldns_read_uint16(req->response + 10) + 1);
624 #endif
625 }
626
627 void
_getdns_dns_req_free(getdns_dns_req * req)628 _getdns_dns_req_free(getdns_dns_req * req)
629 {
630 getdns_network_req **net_req;
631 if (!req) {
632 return;
633 }
634
635 _getdns_upstreams_dereference(req->upstreams);
636
637 /* cleanup network requests */
638 for (net_req = req->netreqs; *net_req; net_req++)
639 network_req_cleanup(*net_req);
640
641 /* clear timeout event */
642 if (req->loop && req->loop->vmt && req->timeout.timeout_cb) {
643 req->loop->vmt->clear(req->loop, &req->timeout);
644 req->timeout.timeout_cb = NULL;
645 }
646 if (req->freed)
647 *req->freed = 1;
648 GETDNS_FREE(req->my_mf, req);
649 }
650
651 static const uint8_t no_suffixes[] = { 1, 0 };
652
653 /* create a new dns req to be submitted */
654 getdns_dns_req *
_getdns_dns_req_new(getdns_context * context,getdns_eventloop * loop,const char * name,uint16_t request_type,const getdns_dict * extensions,uint64_t * now_ms)655 _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
656 const char *name, uint16_t request_type, const getdns_dict *extensions,
657 uint64_t *now_ms)
658 {
659 int dnssec = is_extension_set(
660 extensions, "dnssec",
661 context->dnssec);
662 int dnssec_return_status = is_extension_set(
663 extensions, "dnssec_return_status",
664 context->dnssec_return_status);
665 int dnssec_return_only_secure = is_extension_set(
666 extensions, "dnssec_return_only_secure",
667 context->dnssec_return_only_secure);
668 int dnssec_return_all_statuses = is_extension_set(
669 extensions, "dnssec_return_all_statuses",
670 context->dnssec_return_all_statuses);
671 int dnssec_return_full_validation_chain = is_extension_set(
672 extensions, "dnssec_return_full_validation_chain",
673 context->dnssec_return_full_validation_chain);
674 int dnssec_return_validation_chain = is_extension_set(
675 extensions, "dnssec_return_validation_chain",
676 context->dnssec_return_validation_chain);
677 int edns_cookies = is_extension_set(
678 extensions, "edns_cookies",
679 context->edns_cookies);
680 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
681 int avoid_dnssec_roadblocks
682 = (extensions == dnssec_ok_checking_disabled_avoid_roadblocks);
683 int dnssec_roadblock_avoidance = avoid_dnssec_roadblocks
684 || (extensions == dnssec_ok_checking_disabled_roadblock_avoidance)
685 || is_extension_set(extensions, "dnssec_roadblock_avoidance",
686 context->dnssec_roadblock_avoidance);
687 #endif
688 int dnssec_extension_set = dnssec || dnssec_return_status
689 || dnssec_return_only_secure || dnssec_return_all_statuses
690 || dnssec_return_validation_chain
691 || dnssec_return_full_validation_chain
692 || (extensions == dnssec_ok_checking_disabled)
693 || (extensions == dnssec_ok_checking_disabled_roadblock_avoidance)
694 || (extensions == dnssec_ok_checking_disabled_avoid_roadblocks)
695 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
696 || dnssec_roadblock_avoidance
697 #endif
698 ;
699
700 uint32_t edns_do_bit;
701 int edns_maximum_udp_payload_size;
702 uint32_t get_edns_maximum_udp_payload_size;
703 uint32_t edns_extended_rcode;
704 uint32_t edns_version;
705
706 getdns_dict *add_opt_parameters;
707 int have_add_opt_parameters;
708
709 getdns_list *options = NULL;
710 size_t noptions = 0;
711 size_t i;
712
713 getdns_dict *option;
714 uint32_t option_code;
715 getdns_bindata *option_data;
716 size_t opt_options_size = 0;
717
718 int with_opt;
719
720 getdns_dns_req *result = NULL;
721 uint32_t klass = context->specify_class;
722 int a_aaaa_query = is_extension_set(extensions,
723 "return_both_v4_and_v6", context->return_both_v4_and_v6) &&
724 ( request_type == GETDNS_RRTYPE_A ||
725 request_type == GETDNS_RRTYPE_AAAA );
726 /* Reserve for the buffer at least one more byte
727 * (to test for udp overflow) (hence the + 1),
728 * And align on the 8 byte boundary (hence the (x + 7) / 8 * 8)
729 */
730 size_t max_query_sz, max_response_sz, netreq_sz, dnsreq_base_sz;
731 uint8_t *region, *suffixes;
732 int checking_disabled = dnssec_extension_set;
733 int opportunistic = 0;
734
735 if (extensions == no_dnssec_checking_disabled_opportunistic) {
736 dnssec = 0;
737 dnssec_return_status = 0;
738 dnssec_return_only_secure = 0;
739 dnssec_return_all_statuses = 0;
740 dnssec_return_full_validation_chain = 0;
741 dnssec_return_validation_chain = 0;
742 dnssec_extension_set = 0;
743 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
744 dnssec_roadblock_avoidance = 0;
745 avoid_dnssec_roadblocks = 0;
746 #endif
747 extensions = NULL;
748 checking_disabled = 1;
749 opportunistic = 1;
750 } else if (extensions == dnssec_ok_checking_disabled ||
751 extensions == dnssec_ok_checking_disabled_roadblock_avoidance ||
752 extensions == dnssec_ok_checking_disabled_avoid_roadblocks)
753 extensions = NULL;
754
755 have_add_opt_parameters = getdns_dict_get_dict(extensions,
756 "add_opt_parameters", &add_opt_parameters) == GETDNS_RETURN_GOOD;
757 if (!have_add_opt_parameters && context->add_opt_parameters) {
758 add_opt_parameters = context->add_opt_parameters;
759 have_add_opt_parameters = 1;
760 }
761 if (dnssec_extension_set) {
762 edns_maximum_udp_payload_size = -1;
763 edns_extended_rcode = 0;
764 edns_version = 0;
765 edns_do_bit = 1;
766 } else {
767 edns_maximum_udp_payload_size =
768 context->edns_maximum_udp_payload_size;
769 edns_extended_rcode = context->edns_extended_rcode;
770 edns_version = context->edns_version;
771 edns_do_bit = context->edns_do_bit;
772
773 if (have_add_opt_parameters) {
774 if (getdns_dict_get_int(add_opt_parameters,
775 "maximum_udp_payload_size",
776 &get_edns_maximum_udp_payload_size)) {
777 if (!getdns_dict_get_int(
778 add_opt_parameters, "udp_payload_size",
779 &get_edns_maximum_udp_payload_size))
780 edns_maximum_udp_payload_size =
781 get_edns_maximum_udp_payload_size;
782 } else
783 edns_maximum_udp_payload_size =
784 get_edns_maximum_udp_payload_size;
785
786 (void) getdns_dict_get_int(add_opt_parameters,
787 "extended_rcode", &edns_extended_rcode);
788 (void) getdns_dict_get_int(add_opt_parameters,
789 "version", &edns_version);
790 if (getdns_dict_get_int(add_opt_parameters,
791 "do_bit", &edns_do_bit))
792 (void) getdns_dict_get_int(
793 add_opt_parameters, "do", &edns_do_bit);
794 }
795 }
796 if (have_add_opt_parameters && getdns_dict_get_list(
797 add_opt_parameters, "options", &options) == GETDNS_RETURN_GOOD)
798 (void) getdns_list_get_length(options, &noptions);
799
800 with_opt = edns_do_bit != 0 || edns_maximum_udp_payload_size != 512 ||
801 edns_extended_rcode != 0 || edns_version != 0 || noptions ||
802 edns_cookies || context->edns_client_subnet_private ||
803 context->tls_query_padding_blocksize > 1;
804
805 edns_maximum_udp_payload_size = with_opt &&
806 ( edns_maximum_udp_payload_size == -1 ||
807 edns_maximum_udp_payload_size > 512 )
808 ? edns_maximum_udp_payload_size : 512;
809
810 /* (x + 7) / 8 * 8 to align on 8 byte boundries */
811 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
812 if (context->resolution_type == GETDNS_RESOLUTION_RECURSING
813 && (!dnssec_roadblock_avoidance || avoid_dnssec_roadblocks))
814 #else
815 if (context->resolution_type == GETDNS_RESOLUTION_RECURSING)
816 #endif
817 max_query_sz = 0;
818 else {
819 for (i = 0; i < noptions; i++) {
820 if (getdns_list_get_dict(options, i, &option)) continue;
821 if (getdns_dict_get_int(
822 option, "option_code", &option_code)) continue;
823 if (getdns_dict_get_bindata(
824 option, "option_data", &option_data)) continue;
825
826 opt_options_size += option_data->size
827 + 2 /* option-code */
828 + 2 /* option-length */
829 ;
830 }
831 max_query_sz = ( GLDNS_HEADER_SIZE
832 + 256 + 4 /* dname maximum 255 bytes (256 with mdns)*/
833 + 12 + opt_options_size /* space needed for OPT (if needed) */
834 + MAXIMUM_UPSTREAM_OPTION_SPACE
835 + MAXIMUM_TSIG_SPACE
836 + 7) / 8 * 8;
837 }
838 max_response_sz = (( edns_maximum_udp_payload_size != -1
839 ? edns_maximum_udp_payload_size : 1432
840 ) + 1 /* +1 for udp overflow detection */
841 + 7 ) / 8 * 8;
842
843 netreq_sz = ( sizeof(getdns_network_req)
844 + max_query_sz + max_response_sz + 7 ) / 8 * 8;
845 dnsreq_base_sz = (( sizeof(getdns_dns_req)
846 + (a_aaaa_query ? 3 : 2) * sizeof(getdns_network_req*)
847 + context->suffixes_len
848 ) + 7) / 8 * 8;
849
850 if (! (region = GETDNS_XMALLOC(context->mf, uint8_t,
851 dnsreq_base_sz + (a_aaaa_query ? 2 : 1) * netreq_sz)))
852 return NULL;
853 (void) memset(region, 0, sizeof(getdns_dns_req));
854
855 result = (getdns_dns_req *)region;
856 result->netreqs[0] = (getdns_network_req *)(region + dnsreq_base_sz);
857 if (a_aaaa_query) {
858 result->netreqs[1] = (getdns_network_req *)
859 (region + dnsreq_base_sz + netreq_sz);
860 result->netreqs[2] = NULL;
861 } else
862 result->netreqs[1] = NULL;
863
864 result->my_mf = context->mf;
865
866 suffixes = region + dnsreq_base_sz - context->suffixes_len;
867 assert(context->suffixes);
868 assert(context->suffixes_len);
869 memcpy(suffixes, context->suffixes, context->suffixes_len);
870
871 result->append_name = context->append_name;
872 if (!strlen(name) || name[strlen(name)-1] == '.' ||
873 result->append_name == GETDNS_APPEND_NAME_NEVER) {
874 /* Absolute query string, no appending */
875 result->suffix_len = no_suffixes[0];
876 result->suffix = no_suffixes + 1;
877 result->suffix_appended = 1;
878 } else {
879 result->suffix_len = suffixes[0];
880 result->suffix = suffixes + 1;
881 result->suffix_appended = 0;
882 }
883 result->name_len = sizeof(result->name);
884 if (gldns_str2wire_dname_buf(name, result->name, &result->name_len)) {
885 GETDNS_FREE(result->my_mf, result);
886 return NULL;
887 }
888 if (result->append_name == GETDNS_APPEND_NAME_ALWAYS ||
889 ( result->append_name == GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST
890 && result->name[0] && result->name[result->name[0]+1] == 0)){
891 for (
892 ; result->suffix_len > 1 && *result->suffix
893 ; result->suffix += result->suffix_len
894 , result->suffix_len = *result->suffix++) {
895
896 if (result->suffix_len + result->name_len - 1 <
897 sizeof(result->name)) {
898 memcpy(result->name + result->name_len - 1,
899 result->suffix, result->suffix_len);
900 result->name_len += result->suffix_len - 1;
901 result->suffix_appended = 1;
902 break;
903 }
904 }
905 } else if (result->append_name ==
906 GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE &&
907 result->name[0] &&
908 result->name[result->name[0]+1] != 0) {
909 /* We have multiple labels, no appending */
910 result->suffix_len = no_suffixes[0];
911 result->suffix = no_suffixes + 1;
912 result->suffix_appended = 1;
913 }
914 result->context = context;
915 result->loop = loop;
916 result->trans_id = (uint64_t) (intptr_t) result;
917 result->dnssec = dnssec;
918 result->dnssec_return_status = dnssec_return_status;
919 result->dnssec_return_only_secure = dnssec_return_only_secure;
920 result->dnssec_return_all_statuses = dnssec_return_all_statuses;
921 result->dnssec_return_full_validation_chain =
922 dnssec_return_full_validation_chain;
923 result->dnssec_return_validation_chain = dnssec_return_validation_chain
924 || dnssec_return_full_validation_chain;
925 result->dnssec_extension_set = dnssec_extension_set;
926 result->edns_cookies = edns_cookies;
927 #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
928 result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance;
929 result->avoid_dnssec_roadblocks = avoid_dnssec_roadblocks;
930 #endif
931 result->edns_client_subnet_private = context->edns_client_subnet_private;
932 result->tls_query_padding_blocksize = context->tls_query_padding_blocksize;
933 result->return_call_reporting = is_extension_set(extensions,
934 "return_call_reporting" , context->return_call_reporting);
935 result->add_warning_for_bad_dns = is_extension_set(extensions,
936 "add_warning_for_bad_dns", context->add_warning_for_bad_dns);
937
938 /* will be set by caller */
939 result->user_pointer = NULL;
940 result->user_callback = NULL;
941 memset(&result->timeout, 0, sizeof(result->timeout));
942
943 /* check the specify_class extension */
944 (void) getdns_dict_get_int(extensions, "specify_class", &klass);
945 result->request_class = klass;
946
947 result->upstreams = context->upstreams;
948 if (result->upstreams)
949 result->upstreams->referenced++;
950
951 result->finished_next = NULL;
952 result->ta_notify = NULL;
953 result->freed = NULL;
954 result->validating = 0;
955 result->waiting_for_ta = 0;
956 result->is_dns_request = 1;
957 result->request_timed_out = 0;
958 result->chain = NULL;
959
960 network_req_init(result->netreqs[0], result,
961 request_type, checking_disabled, opportunistic,
962 with_opt, edns_maximum_udp_payload_size,
963 edns_extended_rcode, edns_version, edns_do_bit,
964 (uint16_t) opt_options_size, noptions, options,
965 netreq_sz - sizeof(getdns_network_req), max_query_sz,
966 extensions);
967
968 if (a_aaaa_query)
969 network_req_init(result->netreqs[1], result,
970 ( request_type == GETDNS_RRTYPE_A
971 ? GETDNS_RRTYPE_AAAA : GETDNS_RRTYPE_A ),
972 checking_disabled, opportunistic, with_opt,
973 edns_maximum_udp_payload_size,
974 edns_extended_rcode, edns_version, edns_do_bit,
975 (uint16_t) opt_options_size, noptions, options,
976 netreq_sz - sizeof(getdns_network_req), max_query_sz,
977 extensions);
978
979 if (*now_ms == 0 && (*now_ms = _getdns_get_now_ms()) == 0)
980 result->expires = 0;
981 else
982 result->expires = *now_ms + context->timeout;
983
984 return result;
985 }
986