CVE-2019-10218 - s3: libsmb: Protect SMB2 client code from evil server returned names.
[Samba.git] / lib / addns / dnsquery.c
blobe5600367c4b14b9c17c13ca570ca791e0dde2ddf
1 /*
2 Unix SMB/CIFS implementation.
3 DNS utility library
4 Copyright (C) Gerald (Jerry) Carter 2006.
5 Copyright (C) Jeremy Allison 2007.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "lib/util/util_net.h"
23 #include "lib/util/tsort.h"
24 #include "librpc/gen_ndr/dns.h"
25 #include "libcli/dns/dns_lookup.h"
26 #include "lib/util/tevent_ntstatus.h"
27 #include "dnsquery.h"
29 /* AIX resolv.h uses 'class' in struct ns_rr */
31 #if defined(AIX)
32 # if defined(class)
33 # undef class
34 # endif
35 #endif /* AIX */
37 /* resolver headers */
39 #include <sys/types.h>
40 #include <netinet/in.h>
41 #include <arpa/nameser.h>
42 #include <resolv.h>
43 #include <netdb.h>
45 #define MAX_DNS_PACKET_SIZE 0xffff
47 #ifdef NS_HFIXEDSZ /* Bind 8/9 interface */
48 #if !defined(C_IN) /* AIX 5.3 already defines C_IN */
49 # define C_IN ns_c_in
50 #endif
51 #if !defined(T_A) /* AIX 5.3 already defines T_A */
52 # define T_A ns_t_a
53 #endif
55 #if defined(HAVE_IPV6)
56 #if !defined(T_AAAA)
57 # define T_AAAA ns_t_aaaa
58 #endif
59 #endif
61 # define T_SRV ns_t_srv
62 #if !defined(T_NS) /* AIX 5.3 already defines T_NS */
63 # define T_NS ns_t_ns
64 #endif
65 #else
66 # ifdef HFIXEDSZ
67 # define NS_HFIXEDSZ HFIXEDSZ
68 # else
69 # define NS_HFIXEDSZ sizeof(HEADER)
70 # endif /* HFIXEDSZ */
71 # ifdef PACKETSZ
72 # define NS_PACKETSZ PACKETSZ
73 # else /* 512 is usually the default */
74 # define NS_PACKETSZ 512
75 # endif /* PACKETSZ */
76 # define T_SRV 33
77 #endif
79 /*********************************************************************
80 Sort SRV record list based on weight and priority. See RFC 2782.
81 *********************************************************************/
83 static int dnssrvcmp( struct dns_rr_srv *a, struct dns_rr_srv *b )
85 if ( a->priority == b->priority ) {
87 /* randomize entries with an equal weight and priority */
88 if ( a->weight == b->weight )
89 return 0;
91 /* higher weights should be sorted lower */
92 if ( a->weight > b->weight )
93 return -1;
94 else
95 return 1;
98 if ( a->priority < b->priority )
99 return -1;
101 return 1;
104 struct ads_dns_lookup_srv_state {
105 struct dns_rr_srv *srvs;
106 size_t num_srvs;
109 static void ads_dns_lookup_srv_done(struct tevent_req *subreq);
111 struct tevent_req *ads_dns_lookup_srv_send(TALLOC_CTX *mem_ctx,
112 struct tevent_context *ev,
113 const char *name)
115 struct tevent_req *req, *subreq;
116 struct ads_dns_lookup_srv_state *state;
118 req = tevent_req_create(mem_ctx, &state,
119 struct ads_dns_lookup_srv_state);
120 if (req == NULL) {
121 return NULL;
124 subreq = dns_lookup_send(
125 state,
127 NULL,
128 name,
129 DNS_QCLASS_IN,
130 DNS_QTYPE_SRV);
132 if (tevent_req_nomem(subreq, req)) {
133 return tevent_req_post(req, ev);
135 tevent_req_set_callback(subreq, ads_dns_lookup_srv_done, req);
136 return req;
139 static void ads_dns_lookup_srv_done(struct tevent_req *subreq)
141 struct tevent_req *req = tevent_req_callback_data(
142 subreq, struct tevent_req);
143 struct ads_dns_lookup_srv_state *state = tevent_req_data(
144 req, struct ads_dns_lookup_srv_state);
145 int ret;
146 struct dns_name_packet *reply;
147 uint16_t i, idx;
149 ret = dns_lookup_recv(subreq, state, &reply);
150 TALLOC_FREE(subreq);
151 if (ret != 0) {
152 tevent_req_nterror(req, map_nt_error_from_unix_common(ret));
153 return;
156 for (i=0; i<reply->ancount; i++) {
157 if (reply->answers[i].rr_type == DNS_QTYPE_SRV) {
158 state->num_srvs += 1;
162 state->srvs = talloc_array(state, struct dns_rr_srv, state->num_srvs);
163 if (tevent_req_nomem(state->srvs, req)) {
164 return;
167 idx = 0;
169 for (i=0; i<reply->ancount; i++) {
170 struct dns_res_rec *an = &reply->answers[i];
171 struct dns_rr_srv *dst = &state->srvs[idx];
172 struct dns_srv_record *src;
174 if (an->rr_type != DNS_QTYPE_SRV) {
175 continue;
177 src = &an->rdata.srv_record;
179 *dst = (struct dns_rr_srv) {
180 .hostname = talloc_move(state->srvs, &src->target),
181 .priority = src->priority,
182 .weight = src->weight,
183 .port = src->port,
185 idx += 1;
188 for (i=0; i<reply->arcount; i++) {
189 struct dns_res_rec *ar = &reply->additional[i];
190 struct sockaddr_storage addr;
191 bool ok;
192 size_t j;
194 ok = dns_res_rec_get_sockaddr(ar, &addr);
195 if (!ok) {
196 continue;
199 for (j=0; j<state->num_srvs; j++) {
200 struct dns_rr_srv *srv = &state->srvs[j];
201 struct sockaddr_storage *tmp;
203 if (strcmp(srv->hostname, ar->name) != 0) {
204 continue;
207 tmp = talloc_realloc(
208 state->srvs,
209 srv->ss_s,
210 struct sockaddr_storage,
211 srv->num_ips+1);
213 if (tevent_req_nomem(tmp, req)) {
214 return;
216 srv->ss_s = tmp;
218 srv->ss_s[srv->num_ips] = addr;
219 srv->num_ips += 1;
223 TYPESAFE_QSORT(state->srvs, state->num_srvs, dnssrvcmp);
225 tevent_req_done(req);
228 NTSTATUS ads_dns_lookup_srv_recv(struct tevent_req *req,
229 TALLOC_CTX *mem_ctx,
230 struct dns_rr_srv **srvs,
231 size_t *num_srvs)
233 struct ads_dns_lookup_srv_state *state = tevent_req_data(
234 req, struct ads_dns_lookup_srv_state);
235 NTSTATUS status;
237 if (tevent_req_is_nterror(req, &status)) {
238 return status;
240 *srvs = talloc_move(mem_ctx, &state->srvs);
241 *num_srvs = state->num_srvs;
242 tevent_req_received(req);
243 return NT_STATUS_OK;
246 /*********************************************************************
247 Simple wrapper for a DNS SRV query
248 *********************************************************************/
250 NTSTATUS ads_dns_lookup_srv(TALLOC_CTX *ctx,
251 const char *name,
252 struct dns_rr_srv **dclist,
253 int *numdcs)
255 struct tevent_context *ev;
256 struct tevent_req *req;
257 NTSTATUS status = NT_STATUS_NO_MEMORY;
258 size_t num_srvs;
260 ev = samba_tevent_context_init(ctx);
261 if (ev == NULL) {
262 goto fail;
264 req = ads_dns_lookup_srv_send(ev, ev, name);
265 if (req == NULL) {
266 goto fail;
268 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
269 goto fail;
271 status = ads_dns_lookup_srv_recv(req, ctx, dclist, &num_srvs);
272 *numdcs = num_srvs; /* size_t->int */
273 fail:
274 TALLOC_FREE(ev);
275 return status;
278 struct ads_dns_lookup_ns_state {
279 struct dns_rr_ns *nss;
280 size_t num_nss;
283 static void ads_dns_lookup_ns_done(struct tevent_req *subreq);
285 struct tevent_req *ads_dns_lookup_ns_send(TALLOC_CTX *mem_ctx,
286 struct tevent_context *ev,
287 const char *name)
289 struct tevent_req *req, *subreq;
290 struct ads_dns_lookup_ns_state *state;
292 req = tevent_req_create(mem_ctx, &state,
293 struct ads_dns_lookup_ns_state);
294 if (req == NULL) {
295 return NULL;
298 subreq = dns_lookup_send(state, ev, NULL, name, DNS_QCLASS_IN,
299 DNS_QTYPE_NS);
300 if (tevent_req_nomem(subreq, req)) {
301 return tevent_req_post(req, ev);
303 tevent_req_set_callback(subreq, ads_dns_lookup_ns_done, req);
304 return req;
307 static void ads_dns_lookup_ns_done(struct tevent_req *subreq)
309 struct tevent_req *req = tevent_req_callback_data(
310 subreq, struct tevent_req);
311 struct ads_dns_lookup_ns_state *state = tevent_req_data(
312 req, struct ads_dns_lookup_ns_state);
313 int ret;
314 struct dns_name_packet *reply;
315 uint16_t i, idx;
317 ret = dns_lookup_recv(subreq, state, &reply);
318 TALLOC_FREE(subreq);
319 if (ret != 0) {
320 tevent_req_nterror(req, map_nt_error_from_unix_common(ret));
321 return;
324 for (i=0; i<reply->ancount; i++) {
325 if (reply->answers[i].rr_type == DNS_QTYPE_NS) {
326 state->num_nss += 1;
330 state->nss = talloc_array(state, struct dns_rr_ns, state->num_nss);
331 if (tevent_req_nomem(state->nss, req)) {
332 return;
335 idx = 0;
337 for (i=0; i<reply->ancount; i++) {
338 struct dns_res_rec *an = &reply->answers[i];
340 if (an->rr_type != DNS_QTYPE_NS) {
341 continue;
344 state->nss[idx].hostname = talloc_move(state->nss,
345 &an->rdata.ns_record);
346 idx += 1;
349 for (i=0; i<reply->arcount; i++) {
350 struct dns_res_rec *ar = &reply->additional[i];
351 struct sockaddr_storage addr;
352 bool ok;
353 size_t j;
355 ok = dns_res_rec_get_sockaddr(ar, &addr);
356 if (!ok) {
357 continue;
360 for (j=0; j<state->num_nss; j++) {
361 struct dns_rr_ns *ns = &state->nss[j];
363 if (strcmp(ns->hostname, ar->name) == 0) {
364 ns->ss = addr;
369 tevent_req_done(req);
372 NTSTATUS ads_dns_lookup_ns_recv(struct tevent_req *req,
373 TALLOC_CTX *mem_ctx,
374 struct dns_rr_ns **nss,
375 size_t *num_nss)
377 struct ads_dns_lookup_ns_state *state = tevent_req_data(
378 req, struct ads_dns_lookup_ns_state);
379 NTSTATUS status;
381 if (tevent_req_is_nterror(req, &status)) {
382 return status;
384 *nss = talloc_move(mem_ctx, &state->nss);
385 *num_nss = state->num_nss;
386 tevent_req_received(req);
387 return NT_STATUS_OK;
390 /*********************************************************************
391 Simple wrapper for a DNS NS query
392 *********************************************************************/
394 NTSTATUS ads_dns_lookup_ns(TALLOC_CTX *ctx,
395 const char *dnsdomain,
396 struct dns_rr_ns **nslist,
397 int *numns)
399 struct tevent_context *ev;
400 struct tevent_req *req;
401 NTSTATUS status = NT_STATUS_NO_MEMORY;
402 size_t num_ns = 0;
404 ev = samba_tevent_context_init(ctx);
405 if (ev == NULL) {
406 goto fail;
408 req = ads_dns_lookup_ns_send(ev, ev, dnsdomain);
409 if (req == NULL) {
410 goto fail;
412 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
413 goto fail;
415 status = ads_dns_lookup_ns_recv(req, ctx, nslist, &num_ns);
416 *numns = num_ns;
417 fail:
418 TALLOC_FREE(ev);
419 return status;
423 /********************************************************************
424 Query with optional sitename.
425 ********************************************************************/
427 static NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
428 const char *servicename,
429 const char *dc_pdc_gc_domains,
430 const char *realm,
431 const char *sitename,
432 struct dns_rr_srv **dclist,
433 int *numdcs )
435 char *name;
436 NTSTATUS status;
437 int num_srvs = 0;
439 if ((sitename != NULL) && (strlen(sitename) != 0)) {
440 name = talloc_asprintf(ctx, "%s._tcp.%s._sites.%s._msdcs.%s",
441 servicename, sitename,
442 dc_pdc_gc_domains, realm);
443 if (name == NULL) {
444 return NT_STATUS_NO_MEMORY;
447 status = ads_dns_lookup_srv(ctx, name, dclist, &num_srvs);
449 TALLOC_FREE(name);
451 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
452 NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
453 return status;
456 if (NT_STATUS_IS_OK(status) && (num_srvs != 0)) {
457 goto done;
461 name = talloc_asprintf(ctx, "%s._tcp.%s._msdcs.%s",
462 servicename, dc_pdc_gc_domains, realm);
463 if (name == NULL) {
464 return NT_STATUS_NO_MEMORY;
466 status = ads_dns_lookup_srv(ctx, name, dclist, &num_srvs);
468 done:
469 *numdcs = num_srvs; /* automatic conversion size_t->int */
470 return status;
473 /********************************************************************
474 Query for AD DC's.
475 ********************************************************************/
477 NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx,
478 const char *realm,
479 const char *sitename,
480 struct dns_rr_srv **dclist,
481 int *numdcs )
483 NTSTATUS status;
485 status = ads_dns_query_internal(ctx,
486 "_ldap",
487 "dc",
488 realm,
489 sitename,
490 dclist,
491 numdcs);
492 return status;
495 /********************************************************************
496 Query for AD GC's.
497 ********************************************************************/
499 NTSTATUS ads_dns_query_gcs(TALLOC_CTX *ctx,
500 const char *realm,
501 const char *sitename,
502 struct dns_rr_srv **dclist,
503 int *numdcs )
505 NTSTATUS status;
507 status = ads_dns_query_internal(ctx,
508 "_ldap",
509 "gc",
510 realm,
511 sitename,
512 dclist,
513 numdcs);
514 return status;
517 /********************************************************************
518 Query for AD KDC's.
519 Even if our underlying kerberos libraries are UDP only, this
520 is pretty safe as it's unlikely that a KDC supports TCP and not UDP.
521 ********************************************************************/
523 NTSTATUS ads_dns_query_kdcs(TALLOC_CTX *ctx,
524 const char *dns_forest_name,
525 const char *sitename,
526 struct dns_rr_srv **dclist,
527 int *numdcs )
529 NTSTATUS status;
531 status = ads_dns_query_internal(ctx,
532 "_kerberos",
533 "dc",
534 dns_forest_name,
535 sitename,
536 dclist,
537 numdcs);
538 return status;
541 /********************************************************************
542 Query for AD PDC. Sitename is obsolete here.
543 ********************************************************************/
545 NTSTATUS ads_dns_query_pdc(TALLOC_CTX *ctx,
546 const char *dns_domain_name,
547 struct dns_rr_srv **dclist,
548 int *numdcs )
550 return ads_dns_query_internal(ctx,
551 "_ldap",
552 "pdc",
553 dns_domain_name,
554 NULL,
555 dclist,
556 numdcs);
559 /********************************************************************
560 Query for AD DC by guid. Sitename is obsolete here.
561 ********************************************************************/
563 NTSTATUS ads_dns_query_dcs_guid(TALLOC_CTX *ctx,
564 const char *dns_forest_name,
565 const char *domain_guid,
566 struct dns_rr_srv **dclist,
567 int *numdcs )
569 /*_ldap._tcp.DomainGuid.domains._msdcs.DnsForestName */
571 const char *domains;
573 /* little hack */
574 domains = talloc_asprintf(ctx, "%s.domains", domain_guid);
575 if (!domains) {
576 return NT_STATUS_NO_MEMORY;
579 return ads_dns_query_internal(ctx,
580 "_ldap",
581 domains,
582 dns_forest_name,
583 NULL,
584 dclist,
585 numdcs);