Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : async getaddrinfo()/dns_lookup() name resolution module
5 :
6 : Copyright (C) Andrew Tridgell 2005
7 : Copyright (C) Stefan Metzmacher 2008
8 : Copyright (C) Matthieu Patou 2011
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : /*
25 : this module uses a fork() per getaddrinfo() or dns_looup() call.
26 : At first that might seem crazy, but it is actually very fast,
27 : and solves many of the tricky problems of keeping a child
28 : hanging around in a librar (like what happens when the parent forks).
29 : We use a talloc destructor to ensure that the child is cleaned up
30 : when we have finished with this name resolution.
31 : */
32 :
33 : #include "includes.h"
34 : #include "system/network.h"
35 : #include "system/filesys.h"
36 : #include "lib/socket/socket.h"
37 : #include "libcli/composite/composite.h"
38 : #include "librpc/gen_ndr/ndr_nbt.h"
39 : #include "libcli/resolve/resolve.h"
40 : #include "lib/util/util_net.h"
41 : #include "lib/addns/dnsquery.h"
42 : #include "lib/addns/dns.h"
43 : #include "lib/util/sys_rw.h"
44 : #include "lib/util/smb_strtox.h"
45 : #include <arpa/nameser.h>
46 : #include <resolv.h>
47 :
48 : struct dns_ex_state {
49 : bool do_fallback;
50 : uint32_t flags;
51 : uint16_t port;
52 : struct nbt_name name;
53 : struct socket_address **addrs;
54 : char **names;
55 : pid_t child;
56 : int child_fd;
57 : struct tevent_fd *fde;
58 : struct tevent_context *event_ctx;
59 : };
60 :
61 : /*
62 : kill off a wayward child if needed. This allows us to stop an async
63 : name resolution without leaving a potentially blocking call running
64 : in a child
65 : */
66 1 : static int dns_ex_destructor(struct dns_ex_state *state)
67 : {
68 0 : int status;
69 :
70 1 : kill(state->child, SIGTERM);
71 1 : if (waitpid(state->child, &status, WNOHANG) == 0) {
72 1 : kill(state->child, SIGKILL);
73 1 : waitpid(state->child, &status, 0);
74 : }
75 :
76 1 : return 0;
77 : }
78 :
79 : struct dns_records_container {
80 : char **list;
81 : uint32_t count;
82 : };
83 :
84 0 : static int reply_to_addrs(TALLOC_CTX *mem_ctx, uint32_t *a_num,
85 : char ***cur_addrs, uint32_t total,
86 : struct dns_request *reply, int port)
87 : {
88 0 : char addrstr[INET6_ADDRSTRLEN];
89 0 : struct dns_rrec *rr;
90 0 : char **addrs;
91 0 : uint32_t i;
92 0 : const char *addr;
93 :
94 : /* at most we over-allocate here, but not by much */
95 0 : addrs = talloc_realloc(mem_ctx, *cur_addrs, char *,
96 : total + reply->num_answers);
97 0 : if (!addrs) {
98 0 : return 0;
99 : }
100 0 : *cur_addrs = addrs;
101 :
102 0 : for (i = 0; i < reply->num_answers; i++) {
103 0 : rr = reply->answers[i];
104 :
105 : /* we are only interested in the IN class */
106 0 : if (rr->r_class != DNS_CLASS_IN) {
107 0 : continue;
108 : }
109 :
110 0 : if (rr->type == QTYPE_NS) {
111 : /*
112 : * After the record for NS will come the A or AAAA
113 : * record of the NS.
114 : */
115 0 : break;
116 : }
117 :
118 : /* verify we actually have a record here */
119 0 : if (!rr->data) {
120 0 : continue;
121 : }
122 :
123 : /* we are only interested in A and AAAA records */
124 0 : switch (rr->type) {
125 0 : case QTYPE_A:
126 0 : addr = inet_ntop(AF_INET,
127 0 : (struct in_addr *)rr->data,
128 : addrstr, sizeof(addrstr));
129 0 : if (addr == NULL) {
130 0 : continue;
131 : }
132 0 : break;
133 0 : case QTYPE_AAAA:
134 : #ifdef HAVE_IPV6
135 0 : addr = inet_ntop(AF_INET6,
136 0 : (struct in6_addr *)rr->data,
137 : addrstr, sizeof(addrstr));
138 : #else
139 : addr = NULL;
140 : #endif
141 0 : if (addr == NULL) {
142 0 : continue;
143 : }
144 0 : break;
145 0 : default:
146 0 : continue;
147 : }
148 :
149 0 : addrs[total] = talloc_asprintf(addrs, "%s@%u/%s",
150 : addrstr, port,
151 0 : rr->name->pLabelList->label);
152 0 : if (addrs[total]) {
153 0 : total++;
154 0 : if (rr->type == QTYPE_A) {
155 0 : (*a_num)++;
156 : }
157 : }
158 : }
159 :
160 0 : return total;
161 : }
162 :
163 0 : static DNS_ERROR dns_lookup(TALLOC_CTX *mem_ctx, const char* name,
164 : uint16_t q_type, struct dns_request **reply)
165 : {
166 0 : int len, rlen;
167 0 : uint8_t *answer;
168 0 : bool loop;
169 0 : struct dns_buffer buf;
170 0 : DNS_ERROR err;
171 :
172 : /* give space for a good sized answer by default */
173 0 : answer = NULL;
174 0 : len = 1500;
175 0 : do {
176 0 : answer = talloc_realloc(mem_ctx, answer, uint8_t, len);
177 0 : if (!answer) {
178 0 : return ERROR_DNS_NO_MEMORY;
179 : }
180 0 : rlen = res_search(name, DNS_CLASS_IN, q_type, answer, len);
181 0 : if (rlen == -1) {
182 0 : if (len >= 65535) {
183 0 : return ERROR_DNS_SOCKET_ERROR;
184 : }
185 : /* retry once with max packet size */
186 0 : len = 65535;
187 0 : loop = true;
188 0 : } else if (rlen > len) {
189 0 : len = rlen;
190 0 : loop = true;
191 : } else {
192 0 : loop = false;
193 : }
194 0 : } while(loop);
195 :
196 0 : buf.data = answer;
197 0 : buf.size = rlen;
198 0 : buf.offset = 0;
199 0 : buf.error = ERROR_DNS_SUCCESS;
200 :
201 0 : err = dns_unmarshall_request(mem_ctx, &buf, reply);
202 :
203 0 : TALLOC_FREE(answer);
204 0 : return err;
205 : }
206 :
207 0 : static struct dns_records_container get_a_aaaa_records(TALLOC_CTX *mem_ctx,
208 : const char* name,
209 : int port)
210 : {
211 0 : struct dns_request *reply;
212 0 : struct dns_records_container ret;
213 0 : char **addrs = NULL;
214 0 : uint32_t a_num, total;
215 0 : uint16_t qtype;
216 0 : TALLOC_CTX *tmp_ctx;
217 0 : DNS_ERROR err;
218 :
219 0 : memset(&ret, 0, sizeof(struct dns_records_container));
220 :
221 0 : tmp_ctx = talloc_new(mem_ctx);
222 0 : if (!tmp_ctx) {
223 0 : return ret;
224 : }
225 :
226 0 : qtype = QTYPE_AAAA;
227 :
228 : /* this is the blocking call we are going to lots of trouble
229 : to avoid them in the parent */
230 0 : err = dns_lookup(tmp_ctx, name, qtype, &reply);
231 0 : if (!ERR_DNS_IS_OK(err)) {
232 0 : qtype = QTYPE_A;
233 0 : err = dns_lookup(tmp_ctx, name, qtype, &reply);
234 0 : if (!ERR_DNS_IS_OK(err)) {
235 0 : goto done;
236 : }
237 : }
238 :
239 0 : a_num = total = 0;
240 0 : total = reply_to_addrs(tmp_ctx, &a_num, &addrs, total, reply, port);
241 :
242 0 : if (qtype == QTYPE_AAAA && a_num == 0) {
243 : /*
244 : * DNS server didn't returned A when asked for AAAA records.
245 : * Most of the server do it, let's ask for A specifically.
246 : */
247 0 : err = dns_lookup(tmp_ctx, name, QTYPE_A, &reply);
248 0 : if (ERR_DNS_IS_OK(err)) {
249 : /*
250 : * Ignore an error here and just return any AAAA
251 : * records we already got. This may be an IPv6-only
252 : * config.
253 : */
254 0 : total = reply_to_addrs(tmp_ctx, &a_num, &addrs, total,
255 : reply, port);
256 : }
257 : }
258 :
259 0 : if (total) {
260 0 : talloc_steal(mem_ctx, addrs);
261 0 : ret.count = total;
262 0 : ret.list = addrs;
263 : }
264 :
265 0 : done:
266 0 : TALLOC_FREE(tmp_ctx);
267 0 : return ret;
268 : }
269 :
270 0 : static struct dns_records_container get_srv_records(TALLOC_CTX *mem_ctx,
271 : const char* name)
272 : {
273 0 : struct dns_records_container ret = {0};
274 0 : char **addrs = NULL;
275 0 : struct dns_rr_srv *dclist;
276 0 : NTSTATUS status;
277 0 : size_t total;
278 0 : size_t i;
279 0 : size_t count = 0;
280 :
281 0 : memset(&ret, 0, sizeof(struct dns_records_container));
282 : /* this is the blocking call we are going to lots of trouble
283 : to avoid them in the parent */
284 0 : status = ads_dns_lookup_srv(mem_ctx, name, &dclist, &count);
285 0 : if (!NT_STATUS_IS_OK(status)) {
286 0 : return ret;
287 : }
288 0 : total = 0;
289 0 : if (count == 0) {
290 0 : return ret;
291 : }
292 :
293 : /* Loop over all returned records and pick the records */
294 0 : for (i = 0; i < count; i++) {
295 0 : struct dns_records_container c;
296 0 : const char* tmp_str;
297 :
298 0 : tmp_str = dclist[i].hostname;
299 0 : if (strchr(tmp_str, '.') && tmp_str[strlen(tmp_str)-1] != '.') {
300 : /* we are asking for a fully qualified name, but the
301 : name doesn't end in a '.'. We need to prevent the
302 : DNS library trying the search domains configured in
303 : resolv.conf */
304 0 : tmp_str = talloc_asprintf(mem_ctx, "%s.", tmp_str);
305 : }
306 :
307 0 : c = get_a_aaaa_records(mem_ctx, tmp_str, dclist[i].port);
308 :
309 : /* wrap check */
310 0 : if (total + c.count < total) {
311 : /* possibly could just break here instead? */
312 0 : TALLOC_FREE(addrs);
313 0 : return ret;
314 : }
315 0 : total += c.count;
316 0 : if (addrs == NULL) {
317 0 : addrs = c.list;
318 : } else {
319 0 : unsigned j;
320 :
321 0 : addrs = talloc_realloc(mem_ctx, addrs, char*, total);
322 0 : for (j=0; j < c.count; j++) {
323 0 : addrs[total - j - 1] = talloc_steal(addrs, c.list[j]);
324 : }
325 : }
326 : }
327 :
328 0 : if (total) {
329 0 : ret.count = total;
330 0 : ret.list = addrs;
331 : }
332 :
333 0 : return ret;
334 : }
335 : /*
336 : the blocking child
337 : */
338 0 : static void run_child_dns_lookup(struct dns_ex_state *state, int fd)
339 : {
340 0 : bool first;
341 0 : bool do_srv = (state->flags & RESOLVE_NAME_FLAG_DNS_SRV);
342 0 : struct dns_records_container c;
343 0 : char* addrs = NULL;
344 0 : unsigned int i;
345 :
346 0 : if (strchr(state->name.name, '.') && state->name.name[strlen(state->name.name)-1] != '.') {
347 : /* we are asking for a fully qualified name, but the
348 : name doesn't end in a '.'. We need to prevent the
349 : DNS library trying the search domains configured in
350 : resolv.conf */
351 0 : state->name.name = talloc_strdup_append(discard_const_p(char, state->name.name),
352 : ".");
353 : }
354 :
355 :
356 0 : if (do_srv) {
357 0 : c = get_srv_records(state, state->name.name);
358 : } else {
359 0 : c = get_a_aaaa_records(state, state->name.name, state->port);
360 : }
361 :
362 : /* This line in critical - if we return without writing to the
363 : * pipe, this is the signal that the name did not exist */
364 0 : if (c.count == 0) {
365 0 : goto done;
366 : }
367 :
368 0 : addrs = talloc_strdup(state, "");
369 0 : if (!addrs) {
370 0 : goto done;
371 : }
372 0 : first = true;
373 :
374 0 : for (i=0; i < c.count; i++) {
375 0 : addrs = talloc_asprintf_append_buffer(addrs, "%s%s",
376 : first?"":",",
377 0 : c.list[i]);
378 0 : first = false;
379 : }
380 :
381 0 : if (addrs) {
382 0 : DEBUG(11, ("Addrs = %s\n", addrs));
383 0 : sys_write_v(fd, addrs, talloc_get_size(addrs));
384 : }
385 :
386 0 : done:
387 0 : close(fd);
388 0 : }
389 :
390 : /*
391 : the blocking child
392 : */
393 0 : static void run_child_getaddrinfo(struct dns_ex_state *state, int fd)
394 : {
395 0 : int ret;
396 0 : struct addrinfo hints;
397 0 : struct addrinfo *res;
398 0 : struct addrinfo *res_list = NULL;
399 0 : char *addrs;
400 0 : bool first;
401 :
402 0 : ZERO_STRUCT(hints);
403 0 : hints.ai_socktype = SOCK_STREAM;
404 0 : hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
405 :
406 0 : ret = getaddrinfo(state->name.name, "0", &hints, &res_list);
407 : /* try to fallback in case of error */
408 0 : if (state->do_fallback) {
409 0 : switch (ret) {
410 : #ifdef EAI_NODATA
411 0 : case EAI_NODATA:
412 : #endif
413 : case EAI_FAIL:
414 : /* Linux returns EAI_NODATA on non-RFC1034-compliant names. FreeBSD returns EAI_FAIL */
415 : case EAI_NONAME:
416 : /* getaddrinfo() doesn't handle CNAME or non-RFC1034 compatible records */
417 0 : run_child_dns_lookup(state, fd);
418 0 : return;
419 0 : default:
420 0 : break;
421 : }
422 : }
423 0 : if (ret != 0) {
424 0 : goto done;
425 : }
426 :
427 0 : addrs = talloc_strdup(state, "");
428 0 : if (!addrs) {
429 0 : goto done;
430 : }
431 0 : first = true;
432 0 : for (res = res_list; res; res = res->ai_next) {
433 0 : char addrstr[INET6_ADDRSTRLEN];
434 0 : if (!print_sockaddr_len(addrstr, sizeof(addrstr), (struct sockaddr *)res->ai_addr, res->ai_addrlen)) {
435 0 : continue;
436 : }
437 0 : addrs = talloc_asprintf_append_buffer(addrs, "%s%s@%u/%s",
438 : first?"":",",
439 : addrstr,
440 0 : state->port,
441 : state->name.name);
442 0 : if (!addrs) {
443 0 : goto done;
444 : }
445 0 : first = false;
446 : }
447 :
448 0 : if (addrs) {
449 0 : sys_write_v(fd, addrs, talloc_get_size(addrs));
450 : }
451 0 : done:
452 0 : if (res_list) {
453 0 : freeaddrinfo(res_list);
454 : }
455 0 : close(fd);
456 : }
457 :
458 : /*
459 : handle a read event on the pipe
460 : */
461 54083 : static void pipe_handler(struct tevent_context *ev, struct tevent_fd *fde,
462 : uint16_t flags, void *private_data)
463 : {
464 54083 : struct composite_context *c = talloc_get_type(private_data, struct composite_context);
465 54083 : struct dns_ex_state *state = talloc_get_type(c->private_data,
466 : struct dns_ex_state);
467 1529 : char *address;
468 1529 : uint32_t num_addrs, i;
469 1529 : char **addrs;
470 1529 : int ret;
471 1529 : int status;
472 54083 : int value = 0;
473 :
474 : /* if we get any event from the child then we know that we
475 : won't need to kill it off */
476 54083 : talloc_set_destructor(state, NULL);
477 :
478 54083 : if (ioctl(state->child_fd, FIONREAD, &value) != 0) {
479 0 : value = 8192;
480 : }
481 :
482 54083 : address = talloc_array(state, char, value+1);
483 54083 : if (address) {
484 : /* yes, we don't care about EAGAIN or other niceities
485 : here. They just can't happen with this parent/child
486 : relationship, and even if they did then giving an error is
487 : the right thing to do */
488 55612 : ret = read(state->child_fd, address, value);
489 : } else {
490 0 : ret = -1;
491 : }
492 54083 : if (waitpid(state->child, &status, WNOHANG) == 0) {
493 53896 : kill(state->child, SIGKILL);
494 53896 : waitpid(state->child, &status, 0);
495 : }
496 :
497 54083 : if (ret <= 0) {
498 : /* The check for ret == 0 here is important, if the
499 : * name does not exist, then no bytes are written to
500 : * the pipe */
501 4524 : DEBUG(3,("dns child failed to find name '%s' of type %s\n",
502 : state->name.name, (state->flags & RESOLVE_NAME_FLAG_DNS_SRV)?"SRV":"A"));
503 4524 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
504 4524 : return;
505 : }
506 :
507 : /* ensure the address looks good */
508 49559 : address[ret] = 0;
509 :
510 49559 : addrs = str_list_make(state, address, ",");
511 49559 : if (composite_nomem(addrs, c)) return;
512 :
513 49559 : num_addrs = str_list_length((const char * const *)addrs);
514 :
515 49559 : state->addrs = talloc_array(state, struct socket_address *,
516 : num_addrs+1);
517 49559 : if (composite_nomem(state->addrs, c)) return;
518 :
519 49559 : state->names = talloc_array(state, char *, num_addrs+1);
520 49559 : if (composite_nomem(state->names, c)) return;
521 :
522 145595 : for (i=0; i < num_addrs; i++) {
523 96036 : uint32_t port = 0;
524 96036 : char *p = strrchr(addrs[i], '@');
525 3058 : char *n;
526 96036 : int error = 0;
527 :
528 96036 : if (!p) {
529 0 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
530 0 : return;
531 : }
532 :
533 96036 : *p = '\0';
534 96036 : p++;
535 :
536 96036 : n = strrchr(p, '/');
537 96036 : if (!n) {
538 0 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
539 0 : return;
540 : }
541 :
542 96036 : *n = '\0';
543 96036 : n++;
544 :
545 96036 : if (strcmp(addrs[i], "0.0.0.0") == 0) {
546 0 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
547 0 : return;
548 : }
549 96036 : port = smb_strtoul(p, NULL, 10, &error, SMB_STR_STANDARD);
550 96036 : if (port > UINT16_MAX || error != 0) {
551 0 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
552 0 : return;
553 : }
554 189014 : state->addrs[i] = socket_address_from_strings(state->addrs,
555 : "ip",
556 92978 : addrs[i],
557 : port);
558 96036 : if (composite_nomem(state->addrs[i], c)) return;
559 :
560 96036 : state->names[i] = talloc_strdup(state->names, n);
561 96036 : if (composite_nomem(state->names[i], c)) return;
562 : }
563 49559 : state->addrs[i] = NULL;
564 49559 : state->names[i] = NULL;
565 :
566 49559 : composite_done(c);
567 : }
568 :
569 : /*
570 : getaddrinfo() or dns_lookup() name resolution method - async send
571 : */
572 54084 : struct composite_context *resolve_name_dns_ex_send(TALLOC_CTX *mem_ctx,
573 : struct tevent_context *event_ctx,
574 : void *privdata,
575 : uint32_t flags,
576 : uint16_t port,
577 : struct nbt_name *name,
578 : bool do_fallback)
579 : {
580 1529 : struct composite_context *c;
581 1529 : struct dns_ex_state *state;
582 54084 : int fd[2] = { -1, -1 };
583 1529 : int ret;
584 :
585 54084 : c = composite_create(mem_ctx, event_ctx);
586 54084 : if (c == NULL) return NULL;
587 :
588 54084 : if (flags & RESOLVE_NAME_FLAG_FORCE_NBT) {
589 0 : composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
590 0 : return c;
591 : }
592 :
593 54084 : state = talloc_zero(c, struct dns_ex_state);
594 54084 : if (composite_nomem(state, c)) return c;
595 54084 : c->private_data = state;
596 :
597 54084 : c->status = nbt_name_dup(state, name, &state->name);
598 54084 : if (!composite_is_ok(c)) return c;
599 :
600 : /* setup a pipe to chat to our child */
601 54084 : ret = pipe(fd);
602 54084 : if (ret == -1) {
603 0 : composite_error(c, map_nt_error_from_unix_common(errno));
604 0 : return c;
605 : }
606 :
607 54084 : state->do_fallback = do_fallback;
608 54084 : state->flags = flags;
609 54084 : state->port = port;
610 :
611 54084 : state->child_fd = fd[0];
612 54084 : state->event_ctx = c->event_ctx;
613 :
614 : /* we need to put the child in our event context so
615 : we know when the dns_lookup() has finished */
616 54084 : state->fde = tevent_add_fd(c->event_ctx, c, state->child_fd, TEVENT_FD_READ,
617 : pipe_handler, c);
618 54084 : if (composite_nomem(state->fde, c)) {
619 0 : close(fd[0]);
620 0 : close(fd[1]);
621 0 : return c;
622 : }
623 54084 : tevent_fd_set_auto_close(state->fde);
624 :
625 54084 : state->child = fork();
626 54084 : if (state->child == (pid_t)-1) {
627 0 : composite_error(c, map_nt_error_from_unix_common(errno));
628 0 : return c;
629 : }
630 :
631 54084 : if (state->child == 0) {
632 0 : close(fd[0]);
633 0 : if (state->flags & RESOLVE_NAME_FLAG_FORCE_DNS) {
634 0 : run_child_dns_lookup(state, fd[1]);
635 : } else {
636 0 : run_child_getaddrinfo(state, fd[1]);
637 : }
638 0 : _exit(0);
639 : }
640 54084 : close(fd[1]);
641 :
642 : /* cleanup wayward children */
643 54084 : talloc_set_destructor(state, dns_ex_destructor);
644 :
645 54084 : return c;
646 : }
647 :
648 : /*
649 : getaddrinfo() or dns_lookup() name resolution method - recv side
650 : */
651 54083 : NTSTATUS resolve_name_dns_ex_recv(struct composite_context *c,
652 : TALLOC_CTX *mem_ctx,
653 : struct socket_address ***addrs,
654 : char ***names)
655 : {
656 1529 : NTSTATUS status;
657 :
658 54083 : status = composite_wait(c);
659 :
660 54083 : if (NT_STATUS_IS_OK(status)) {
661 49559 : struct dns_ex_state *state = talloc_get_type(c->private_data,
662 : struct dns_ex_state);
663 49559 : *addrs = talloc_steal(mem_ctx, state->addrs);
664 49559 : if (names) {
665 49272 : *names = talloc_steal(mem_ctx, state->names);
666 : }
667 : }
668 :
669 54083 : talloc_free(c);
670 54083 : return status;
671 : }
|