Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : DNS server handler for queries
5 :
6 : Copyright (C) 2010 Kai Blin <kai@samba.org>
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "samba/service_task.h"
24 : #include "libcli/util/werror.h"
25 : #include "librpc/ndr/libndr.h"
26 : #include "librpc/gen_ndr/ndr_dns.h"
27 : #include "librpc/gen_ndr/ndr_dnsp.h"
28 : #include <ldb.h>
29 : #include "param/param.h"
30 : #include "dsdb/samdb/samdb.h"
31 : #include "dsdb/common/util.h"
32 : #include "dns_server/dns_server.h"
33 : #include "libcli/dns/libdns.h"
34 : #include "lib/util/dlinklist.h"
35 : #include "lib/util/util_net.h"
36 : #include "lib/util/tevent_werror.h"
37 : #include "auth/auth.h"
38 : #include "auth/credentials/credentials.h"
39 : #include "auth/gensec/gensec.h"
40 :
41 : #undef DBGC_CLASS
42 : #define DBGC_CLASS DBGC_DNS
43 : #define MAX_Q_RECURSION_DEPTH 20
44 :
45 : struct forwarder_string {
46 : const char *forwarder;
47 : struct forwarder_string *prev, *next;
48 : };
49 :
50 49633 : static WERROR add_response_rr(const char *name,
51 : const struct dnsp_DnssrvRpcRecord *rec,
52 : struct dns_res_rec **answers)
53 : {
54 49633 : struct dns_res_rec *ans = *answers;
55 49633 : uint16_t ai = talloc_array_length(ans);
56 : enum ndr_err_code ndr_err;
57 :
58 49633 : if (ai == UINT16_MAX) {
59 0 : return WERR_BUFFER_OVERFLOW;
60 : }
61 :
62 : /*
63 : * "ans" is always non-NULL and thus its own talloc context
64 : */
65 49633 : ans = talloc_realloc(ans, ans, struct dns_res_rec, ai+1);
66 49633 : if (ans == NULL) {
67 0 : return WERR_NOT_ENOUGH_MEMORY;
68 : }
69 :
70 49633 : ZERO_STRUCT(ans[ai]);
71 :
72 49633 : switch (rec->wType) {
73 6504 : case DNS_QTYPE_CNAME:
74 6504 : ans[ai].rdata.cname_record = talloc_strdup(ans, rec->data.cname);
75 6504 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.cname_record);
76 6504 : break;
77 4299 : case DNS_QTYPE_A:
78 4299 : ans[ai].rdata.ipv4_record = talloc_strdup(ans, rec->data.ipv4);
79 4299 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ipv4_record);
80 4299 : break;
81 3898 : case DNS_QTYPE_AAAA:
82 3898 : ans[ai].rdata.ipv6_record = talloc_strdup(ans, rec->data.ipv6);
83 3898 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ipv6_record);
84 3898 : break;
85 477 : case DNS_TYPE_NS:
86 477 : ans[ai].rdata.ns_record = talloc_strdup(ans, rec->data.ns);
87 477 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ns_record);
88 477 : break;
89 2408 : case DNS_QTYPE_SRV:
90 2408 : ans[ai].rdata.srv_record.priority = rec->data.srv.wPriority;
91 2408 : ans[ai].rdata.srv_record.weight = rec->data.srv.wWeight;
92 2408 : ans[ai].rdata.srv_record.port = rec->data.srv.wPort;
93 2497 : ans[ai].rdata.srv_record.target = talloc_strdup(
94 89 : ans, rec->data.srv.nameTarget);
95 2408 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.srv_record.target);
96 2408 : break;
97 31752 : case DNS_QTYPE_SOA:
98 32062 : ans[ai].rdata.soa_record.mname = talloc_strdup(
99 310 : ans, rec->data.soa.mname);
100 31752 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.soa_record.mname);
101 32062 : ans[ai].rdata.soa_record.rname = talloc_strdup(
102 310 : ans, rec->data.soa.rname);
103 31752 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.soa_record.rname);
104 31752 : ans[ai].rdata.soa_record.serial = rec->data.soa.serial;
105 31752 : ans[ai].rdata.soa_record.refresh = rec->data.soa.refresh;
106 31752 : ans[ai].rdata.soa_record.retry = rec->data.soa.retry;
107 31752 : ans[ai].rdata.soa_record.expire = rec->data.soa.expire;
108 31752 : ans[ai].rdata.soa_record.minimum = rec->data.soa.minimum;
109 31752 : break;
110 0 : case DNS_QTYPE_PTR:
111 0 : ans[ai].rdata.ptr_record = talloc_strdup(ans, rec->data.ptr);
112 0 : W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ptr_record);
113 0 : break;
114 2 : case DNS_QTYPE_MX:
115 2 : ans[ai].rdata.mx_record.preference = rec->data.mx.wPriority;
116 3 : ans[ai].rdata.mx_record.exchange = talloc_strdup(
117 1 : ans, rec->data.mx.nameTarget);
118 2 : if (ans[ai].rdata.mx_record.exchange == NULL) {
119 0 : return WERR_NOT_ENOUGH_MEMORY;
120 : }
121 2 : break;
122 293 : case DNS_QTYPE_TXT:
123 293 : ndr_err = ndr_dnsp_string_list_copy(ans,
124 : &rec->data.txt,
125 293 : &ans[ai].rdata.txt_record.txt);
126 293 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
127 0 : return WERR_NOT_ENOUGH_MEMORY;
128 : }
129 293 : break;
130 0 : default:
131 0 : DEBUG(0, ("Got unhandled type %u query.\n", rec->wType));
132 0 : return DNS_ERR(NOT_IMPLEMENTED);
133 : }
134 :
135 49633 : ans[ai].name = talloc_strdup(ans, name);
136 49633 : W_ERROR_HAVE_NO_MEMORY(ans[ai].name);
137 49633 : ans[ai].rr_type = (enum dns_qtype)rec->wType;
138 49633 : ans[ai].rr_class = DNS_QCLASS_IN;
139 49633 : ans[ai].ttl = rec->dwTtlSeconds;
140 49633 : ans[ai].length = UINT16_MAX;
141 :
142 49633 : *answers = ans;
143 :
144 49633 : return WERR_OK;
145 : }
146 :
147 8 : static WERROR add_dns_res_rec(struct dns_res_rec **pdst,
148 : const struct dns_res_rec *src)
149 : {
150 8 : struct dns_res_rec *dst = *pdst;
151 8 : uint16_t di = talloc_array_length(dst);
152 : enum ndr_err_code ndr_err;
153 :
154 8 : if (di == UINT16_MAX) {
155 0 : return WERR_BUFFER_OVERFLOW;
156 : }
157 :
158 8 : dst = talloc_realloc(dst, dst, struct dns_res_rec, di+1);
159 8 : if (dst == NULL) {
160 0 : return WERR_NOT_ENOUGH_MEMORY;
161 : }
162 :
163 8 : ZERO_STRUCT(dst[di]);
164 :
165 16 : dst[di] = (struct dns_res_rec) {
166 8 : .name = talloc_strdup(dst, src->name),
167 8 : .rr_type = src->rr_type,
168 8 : .rr_class = src->rr_class,
169 8 : .ttl = src->ttl,
170 8 : .length = src->length
171 : };
172 :
173 8 : if (dst[di].name == NULL) {
174 0 : return WERR_NOT_ENOUGH_MEMORY;
175 : }
176 :
177 8 : switch (src->rr_type) {
178 8 : case DNS_QTYPE_CNAME:
179 12 : dst[di].rdata.cname_record = talloc_strdup(
180 4 : dst, src->rdata.cname_record);
181 8 : if (dst[di].rdata.cname_record == NULL) {
182 0 : return WERR_NOT_ENOUGH_MEMORY;
183 : }
184 8 : break;
185 0 : case DNS_QTYPE_A:
186 0 : dst[di].rdata.ipv4_record = talloc_strdup(
187 0 : dst, src->rdata.ipv4_record);
188 0 : if (dst[di].rdata.ipv4_record == NULL) {
189 0 : return WERR_NOT_ENOUGH_MEMORY;
190 : }
191 0 : break;
192 0 : case DNS_QTYPE_AAAA:
193 0 : dst[di].rdata.ipv6_record = talloc_strdup(
194 0 : dst, src->rdata.ipv6_record);
195 0 : if (dst[di].rdata.ipv6_record == NULL) {
196 0 : return WERR_NOT_ENOUGH_MEMORY;
197 : }
198 0 : break;
199 0 : case DNS_TYPE_NS:
200 0 : dst[di].rdata.ns_record = talloc_strdup(
201 0 : dst, src->rdata.ns_record);
202 0 : if (dst[di].rdata.ns_record == NULL) {
203 0 : return WERR_NOT_ENOUGH_MEMORY;
204 : }
205 0 : break;
206 0 : case DNS_QTYPE_SRV:
207 0 : dst[di].rdata.srv_record = (struct dns_srv_record) {
208 0 : .priority = src->rdata.srv_record.priority,
209 0 : .weight = src->rdata.srv_record.weight,
210 0 : .port = src->rdata.srv_record.port,
211 0 : .target = talloc_strdup(
212 0 : dst, src->rdata.srv_record.target)
213 : };
214 0 : if (dst[di].rdata.srv_record.target == NULL) {
215 0 : return WERR_NOT_ENOUGH_MEMORY;
216 : }
217 0 : break;
218 0 : case DNS_QTYPE_SOA:
219 0 : dst[di].rdata.soa_record = (struct dns_soa_record) {
220 0 : .mname = talloc_strdup(
221 0 : dst, src->rdata.soa_record.mname),
222 0 : .rname = talloc_strdup(
223 0 : dst, src->rdata.soa_record.rname),
224 0 : .serial = src->rdata.soa_record.serial,
225 0 : .refresh = src->rdata.soa_record.refresh,
226 0 : .retry = src->rdata.soa_record.retry,
227 0 : .expire = src->rdata.soa_record.expire,
228 0 : .minimum = src->rdata.soa_record.minimum
229 : };
230 :
231 0 : if ((dst[di].rdata.soa_record.mname == NULL) ||
232 0 : (dst[di].rdata.soa_record.rname == NULL)) {
233 0 : return WERR_NOT_ENOUGH_MEMORY;
234 : }
235 :
236 0 : break;
237 0 : case DNS_QTYPE_PTR:
238 0 : dst[di].rdata.ptr_record = talloc_strdup(
239 0 : dst, src->rdata.ptr_record);
240 0 : if (dst[di].rdata.ptr_record == NULL) {
241 0 : return WERR_NOT_ENOUGH_MEMORY;
242 : }
243 0 : break;
244 0 : case DNS_QTYPE_MX:
245 0 : dst[di].rdata.mx_record = (struct dns_mx_record) {
246 0 : .preference = src->rdata.mx_record.preference,
247 0 : .exchange = talloc_strdup(
248 0 : src, src->rdata.mx_record.exchange)
249 : };
250 :
251 0 : if (dst[di].rdata.mx_record.exchange == NULL) {
252 0 : return WERR_NOT_ENOUGH_MEMORY;
253 : }
254 0 : break;
255 0 : case DNS_QTYPE_TXT:
256 0 : ndr_err = ndr_dnsp_string_list_copy(dst,
257 : &src->rdata.txt_record.txt,
258 0 : &dst[di].rdata.txt_record.txt);
259 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
260 0 : return WERR_NOT_ENOUGH_MEMORY;
261 : }
262 0 : break;
263 0 : default:
264 0 : DBG_WARNING("Got unhandled type %u query.\n", src->rr_type);
265 0 : return DNS_ERR(NOT_IMPLEMENTED);
266 : }
267 :
268 8 : *pdst = dst;
269 :
270 8 : return WERR_OK;
271 : }
272 :
273 : struct ask_forwarder_state {
274 : struct dns_name_packet *reply;
275 : };
276 :
277 : static void ask_forwarder_done(struct tevent_req *subreq);
278 :
279 38 : static struct tevent_req *ask_forwarder_send(
280 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
281 : const char *forwarder, struct dns_name_question *question)
282 : {
283 : struct tevent_req *req, *subreq;
284 : struct ask_forwarder_state *state;
285 :
286 38 : req = tevent_req_create(mem_ctx, &state, struct ask_forwarder_state);
287 38 : if (req == NULL) {
288 0 : return NULL;
289 : }
290 :
291 38 : subreq = dns_cli_request_send(state, ev, forwarder,
292 : question->name, question->question_class,
293 : question->question_type);
294 38 : if (tevent_req_nomem(subreq, req)) {
295 0 : return tevent_req_post(req, ev);
296 : }
297 38 : tevent_req_set_callback(subreq, ask_forwarder_done, req);
298 38 : return req;
299 : }
300 :
301 38 : static void ask_forwarder_done(struct tevent_req *subreq)
302 : {
303 38 : struct tevent_req *req = tevent_req_callback_data(
304 : subreq, struct tevent_req);
305 38 : struct ask_forwarder_state *state = tevent_req_data(
306 : req, struct ask_forwarder_state);
307 : int ret;
308 :
309 38 : ret = dns_cli_request_recv(subreq, state, &state->reply);
310 38 : TALLOC_FREE(subreq);
311 :
312 38 : if (ret != 0) {
313 20 : tevent_req_werror(req, unix_to_werror(ret));
314 20 : return;
315 : }
316 :
317 18 : tevent_req_done(req);
318 : }
319 :
320 38 : static WERROR ask_forwarder_recv(
321 : struct tevent_req *req, TALLOC_CTX *mem_ctx,
322 : struct dns_res_rec **answers, uint16_t *ancount,
323 : struct dns_res_rec **nsrecs, uint16_t *nscount,
324 : struct dns_res_rec **additional, uint16_t *arcount)
325 : {
326 38 : struct ask_forwarder_state *state = tevent_req_data(
327 : req, struct ask_forwarder_state);
328 38 : struct dns_name_packet *in_packet = state->reply;
329 : WERROR err;
330 :
331 38 : if (tevent_req_is_werror(req, &err)) {
332 20 : return err;
333 : }
334 :
335 18 : *ancount = in_packet->ancount;
336 18 : *answers = talloc_move(mem_ctx, &in_packet->answers);
337 :
338 18 : *nscount = in_packet->nscount;
339 18 : *nsrecs = talloc_move(mem_ctx, &in_packet->nsrecs);
340 :
341 18 : *arcount = in_packet->arcount;
342 18 : *additional = talloc_move(mem_ctx, &in_packet->additional);
343 :
344 18 : return WERR_OK;
345 : }
346 :
347 31391 : static WERROR add_zone_authority_record(struct dns_server *dns,
348 : TALLOC_CTX *mem_ctx,
349 : const struct dns_name_question *question,
350 : struct dns_res_rec **nsrecs)
351 : {
352 31391 : const char *zone = NULL;
353 : struct dnsp_DnssrvRpcRecord *recs;
354 31391 : struct dns_res_rec *ns = *nsrecs;
355 : uint16_t rec_count;
356 31391 : struct ldb_dn *dn = NULL;
357 : unsigned int ri;
358 : WERROR werror;
359 :
360 31391 : zone = dns_get_authoritative_zone(dns, question->name);
361 31391 : DEBUG(10, ("Creating zone authority record for '%s'\n", zone));
362 :
363 31391 : werror = dns_name2dn(dns, mem_ctx, zone, &dn);
364 31391 : if (!W_ERROR_IS_OK(werror)) {
365 0 : return werror;
366 : }
367 :
368 31391 : werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rec_count);
369 31391 : if (!W_ERROR_IS_OK(werror)) {
370 6 : return werror;
371 : }
372 :
373 117064 : for (ri = 0; ri < rec_count; ri++) {
374 85679 : if (recs[ri].wType == DNS_TYPE_SOA) {
375 31385 : werror = add_response_rr(zone, &recs[ri], &ns);
376 31385 : if (!W_ERROR_IS_OK(werror)) {
377 0 : return werror;
378 : }
379 : }
380 : }
381 :
382 31385 : *nsrecs = ns;
383 :
384 31385 : return WERR_OK;
385 : }
386 :
387 : static struct tevent_req *handle_authoritative_send(
388 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
389 : struct dns_server *dns, const char *forwarder,
390 : struct dns_name_question *question,
391 : struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
392 : size_t cname_depth);
393 : static WERROR handle_authoritative_recv(struct tevent_req *req);
394 :
395 : struct handle_dnsrpcrec_state {
396 : struct dns_res_rec **answers;
397 : struct dns_res_rec **nsrecs;
398 : };
399 :
400 : static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq);
401 : static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq);
402 :
403 29901 : static struct tevent_req *handle_dnsrpcrec_send(
404 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
405 : struct dns_server *dns, const char *forwarder,
406 : const struct dns_name_question *question,
407 : struct dnsp_DnssrvRpcRecord *rec,
408 : struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
409 : size_t cname_depth)
410 : {
411 : struct tevent_req *req, *subreq;
412 : struct handle_dnsrpcrec_state *state;
413 : struct dns_name_question *new_q;
414 : bool resolve_cname;
415 : WERROR werr;
416 :
417 29901 : req = tevent_req_create(mem_ctx, &state,
418 : struct handle_dnsrpcrec_state);
419 29901 : if (req == NULL) {
420 0 : return NULL;
421 : }
422 29901 : state->answers = answers;
423 29901 : state->nsrecs = nsrecs;
424 :
425 29901 : if (cname_depth >= MAX_Q_RECURSION_DEPTH) {
426 2 : tevent_req_done(req);
427 2 : return tevent_req_post(req, ev);
428 : }
429 :
430 42789 : resolve_cname = ((rec->wType == DNS_TYPE_CNAME) &&
431 9767 : ((question->question_type == DNS_QTYPE_A) ||
432 3263 : (question->question_type == DNS_QTYPE_AAAA)));
433 :
434 29899 : if (!resolve_cname) {
435 46309 : if ((question->question_type != DNS_QTYPE_ALL) &&
436 23471 : (rec->wType !=
437 23471 : (enum dns_record_type) question->question_type)) {
438 11651 : tevent_req_done(req);
439 11651 : return tevent_req_post(req, ev);
440 : }
441 :
442 11830 : werr = add_response_rr(question->name, rec, state->answers);
443 11830 : if (tevent_req_werror(req, werr)) {
444 0 : return tevent_req_post(req, ev);
445 : }
446 :
447 11830 : tevent_req_done(req);
448 11830 : return tevent_req_post(req, ev);
449 : }
450 :
451 6418 : werr = add_response_rr(question->name, rec, state->answers);
452 6418 : if (tevent_req_werror(req, werr)) {
453 0 : return tevent_req_post(req, ev);
454 : }
455 :
456 6418 : new_q = talloc(state, struct dns_name_question);
457 6418 : if (tevent_req_nomem(new_q, req)) {
458 0 : return tevent_req_post(req, ev);
459 : }
460 :
461 6418 : *new_q = (struct dns_name_question) {
462 6418 : .question_type = question->question_type,
463 6418 : .question_class = question->question_class,
464 6418 : .name = rec->data.cname
465 : };
466 :
467 6418 : if (dns_authoritative_for_zone(dns, new_q->name)) {
468 19162 : subreq = handle_authoritative_send(
469 : state, ev, dns, forwarder, new_q,
470 12784 : state->answers, state->nsrecs,
471 : cname_depth + 1);
472 6406 : if (tevent_req_nomem(subreq, req)) {
473 0 : return tevent_req_post(req, ev);
474 : }
475 6406 : tevent_req_set_callback(subreq, handle_dnsrpcrec_gotauth, req);
476 6406 : return req;
477 : }
478 :
479 12 : subreq = ask_forwarder_send(state, ev, forwarder, new_q);
480 12 : if (tevent_req_nomem(subreq, req)) {
481 0 : return tevent_req_post(req, ev);
482 : }
483 12 : tevent_req_set_callback(subreq, handle_dnsrpcrec_gotforwarded, req);
484 :
485 12 : return req;
486 : }
487 :
488 6406 : static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq)
489 : {
490 6406 : struct tevent_req *req = tevent_req_callback_data(
491 : subreq, struct tevent_req);
492 : WERROR werr;
493 :
494 6406 : werr = handle_authoritative_recv(subreq);
495 6406 : TALLOC_FREE(subreq);
496 6406 : if (tevent_req_werror(req, werr)) {
497 7 : return;
498 : }
499 6399 : tevent_req_done(req);
500 : }
501 :
502 12 : static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq)
503 : {
504 12 : struct tevent_req *req = tevent_req_callback_data(
505 : subreq, struct tevent_req);
506 12 : struct handle_dnsrpcrec_state *state = tevent_req_data(
507 : req, struct handle_dnsrpcrec_state);
508 : struct dns_res_rec *answers, *nsrecs, *additional;
509 12 : uint16_t ancount = 0;
510 12 : uint16_t nscount = 0;
511 12 : uint16_t arcount = 0;
512 : uint16_t i;
513 : WERROR werr;
514 :
515 12 : werr = ask_forwarder_recv(subreq, state, &answers, &ancount,
516 : &nsrecs, &nscount, &additional, &arcount);
517 12 : if (tevent_req_werror(req, werr)) {
518 6 : return;
519 : }
520 :
521 16 : for (i=0; i<ancount; i++) {
522 8 : werr = add_dns_res_rec(state->answers, &answers[i]);
523 8 : if (tevent_req_werror(req, werr)) {
524 0 : return;
525 : }
526 : }
527 :
528 8 : for (i=0; i<nscount; i++) {
529 0 : werr = add_dns_res_rec(state->nsrecs, &nsrecs[i]);
530 0 : if (tevent_req_werror(req, werr)) {
531 0 : return;
532 : }
533 : }
534 :
535 8 : tevent_req_done(req);
536 : }
537 :
538 29901 : static WERROR handle_dnsrpcrec_recv(struct tevent_req *req)
539 : {
540 29901 : return tevent_req_simple_recv_werror(req);
541 : }
542 :
543 : struct handle_authoritative_state {
544 : struct tevent_context *ev;
545 : struct dns_server *dns;
546 : struct dns_name_question *question;
547 : const char *forwarder;
548 :
549 : struct dnsp_DnssrvRpcRecord *recs;
550 : uint16_t rec_count;
551 : uint16_t recs_done;
552 :
553 : struct dns_res_rec **answers;
554 : struct dns_res_rec **nsrecs;
555 :
556 : size_t cname_depth;
557 : };
558 :
559 : static void handle_authoritative_done(struct tevent_req *subreq);
560 :
561 37835 : static struct tevent_req *handle_authoritative_send(
562 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
563 : struct dns_server *dns, const char *forwarder,
564 : struct dns_name_question *question,
565 : struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
566 : size_t cname_depth)
567 : {
568 : struct tevent_req *req, *subreq;
569 : struct handle_authoritative_state *state;
570 37835 : struct ldb_dn *dn = NULL;
571 : WERROR werr;
572 :
573 37835 : req = tevent_req_create(mem_ctx, &state,
574 : struct handle_authoritative_state);
575 37835 : if (req == NULL) {
576 0 : return NULL;
577 : }
578 37835 : state->ev = ev;
579 37835 : state->dns = dns;
580 37835 : state->question = question;
581 37835 : state->forwarder = forwarder;
582 37835 : state->answers = answers;
583 37835 : state->nsrecs = nsrecs;
584 37835 : state->cname_depth = cname_depth;
585 :
586 37835 : werr = dns_name2dn(dns, state, question->name, &dn);
587 37835 : if (tevent_req_werror(req, werr)) {
588 0 : return tevent_req_post(req, ev);
589 : }
590 37835 : werr = dns_lookup_records_wildcard(dns, state, dn, &state->recs,
591 37835 : &state->rec_count);
592 37835 : TALLOC_FREE(dn);
593 37835 : if (tevent_req_werror(req, werr)) {
594 20452 : return tevent_req_post(req, ev);
595 : }
596 :
597 17383 : if (state->rec_count == 0) {
598 0 : tevent_req_werror(req, DNS_ERR(NAME_ERROR));
599 0 : return tevent_req_post(req, ev);
600 : }
601 :
602 119821 : subreq = handle_dnsrpcrec_send(
603 51529 : state, state->ev, state->dns, state->forwarder,
604 34456 : state->question, &state->recs[state->recs_done],
605 34456 : state->answers, state->nsrecs,
606 17383 : state->cname_depth);
607 17383 : if (tevent_req_nomem(subreq, req)) {
608 0 : return tevent_req_post(req, ev);
609 : }
610 17383 : tevent_req_set_callback(subreq, handle_authoritative_done, req);
611 17383 : return req;
612 : }
613 :
614 29901 : static void handle_authoritative_done(struct tevent_req *subreq)
615 : {
616 29901 : struct tevent_req *req = tevent_req_callback_data(
617 : subreq, struct tevent_req);
618 29901 : struct handle_authoritative_state *state = tevent_req_data(
619 : req, struct handle_authoritative_state);
620 : WERROR werr;
621 :
622 29901 : werr = handle_dnsrpcrec_recv(subreq);
623 29901 : TALLOC_FREE(subreq);
624 29901 : if (tevent_req_werror(req, werr)) {
625 17391 : return;
626 : }
627 :
628 29890 : state->recs_done += 1;
629 :
630 29890 : if (state->recs_done == state->rec_count) {
631 17372 : tevent_req_done(req);
632 17372 : return;
633 : }
634 :
635 36812 : subreq = handle_dnsrpcrec_send(
636 : state, state->ev, state->dns, state->forwarder,
637 24665 : state->question, &state->recs[state->recs_done],
638 : state->answers, state->nsrecs,
639 : state->cname_depth);
640 12518 : if (tevent_req_nomem(subreq, req)) {
641 0 : return;
642 : }
643 12518 : tevent_req_set_callback(subreq, handle_authoritative_done, req);
644 : }
645 :
646 37835 : static WERROR handle_authoritative_recv(struct tevent_req *req)
647 : {
648 : WERROR werr;
649 :
650 37835 : if (tevent_req_is_werror(req, &werr)) {
651 20463 : return werr;
652 : }
653 :
654 17372 : return WERR_OK;
655 : }
656 :
657 205 : static NTSTATUS create_tkey(TALLOC_CTX *mem_ctx,
658 : struct dns_server *dns,
659 : const char* name,
660 : const char* algorithm,
661 : const struct tsocket_address *remote_address,
662 : const struct tsocket_address *local_address,
663 : struct dns_server_tkey **tkey)
664 : {
665 : NTSTATUS status;
666 205 : struct dns_server_tkey *k = NULL;
667 :
668 205 : k = talloc_zero(mem_ctx, struct dns_server_tkey);
669 205 : if (k == NULL) {
670 0 : goto nomem;
671 : }
672 :
673 205 : k->name = talloc_strdup(k, name);
674 :
675 205 : if (k->name == NULL) {
676 0 : goto nomem;
677 : }
678 :
679 205 : k->algorithm = talloc_strdup(k, algorithm);
680 205 : if (k->algorithm == NULL) {
681 0 : goto nomem;
682 : }
683 :
684 : /*
685 : * We only allow SPNEGO/KRB5 currently
686 : * and rely on the backend to be RPC/IPC free.
687 : *
688 : * It allows gensec_update() not to block.
689 : */
690 754 : status = samba_server_gensec_krb5_start(k,
691 205 : dns->task->event_ctx,
692 205 : dns->task->msg_ctx,
693 205 : dns->task->lp_ctx,
694 : dns->server_credentials,
695 : "dns",
696 : &k->gensec);
697 205 : if (!NT_STATUS_IS_OK(status)) {
698 0 : DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
699 0 : goto fail;
700 : }
701 :
702 205 : gensec_want_feature(k->gensec, GENSEC_FEATURE_SIGN);
703 :
704 205 : status = gensec_set_remote_address(k->gensec,
705 : remote_address);
706 205 : if (!NT_STATUS_IS_OK(status)) {
707 0 : DEBUG(1, ("Failed to set remote address into GENSEC: %s\n",
708 : nt_errstr(status)));
709 0 : goto fail;
710 : }
711 :
712 205 : status = gensec_set_local_address(k->gensec,
713 : local_address);
714 205 : if (!NT_STATUS_IS_OK(status)) {
715 0 : DEBUG(1, ("Failed to set local address into GENSEC: %s\n",
716 : nt_errstr(status)));
717 0 : goto fail;
718 : }
719 :
720 205 : status = gensec_start_mech_by_oid(k->gensec, GENSEC_OID_SPNEGO);
721 :
722 205 : if (!NT_STATUS_IS_OK(status)) {
723 0 : DEBUG(1, ("Failed to start GENSEC server code: %s\n",
724 : nt_errstr(status)));
725 0 : goto fail;
726 : }
727 :
728 205 : *tkey = k;
729 205 : return NT_STATUS_OK;
730 :
731 0 : nomem:
732 0 : status = NT_STATUS_NO_MEMORY;
733 0 : fail:
734 0 : TALLOC_FREE(k);
735 0 : *tkey = NULL;
736 0 : return status;
737 : }
738 :
739 205 : static void add_tkey(struct dns_server_tkey_store *store,
740 : struct dns_server_tkey **tkey)
741 : {
742 205 : TALLOC_FREE(store->tkeys[store->next_idx]);
743 :
744 205 : store->tkeys[store->next_idx] = talloc_move(store->tkeys, tkey);
745 :
746 205 : (store->next_idx)++;
747 205 : store->next_idx %= store->size;
748 205 : }
749 :
750 205 : static NTSTATUS accept_gss_ticket(TALLOC_CTX *mem_ctx,
751 : struct dns_server *dns,
752 : struct dns_server_tkey *tkey,
753 : const DATA_BLOB *key,
754 : DATA_BLOB *reply,
755 : uint16_t *dns_auth_error)
756 : {
757 : NTSTATUS status;
758 :
759 : /*
760 : * We use samba_server_gensec_krb5_start(),
761 : * which only allows SPNEGO/KRB5 currently
762 : * and makes sure the backend to be RPC/IPC free.
763 : *
764 : * See gensec_gssapi_update_internal() as
765 : * GENSEC_SERVER.
766 : *
767 : * It allows gensec_update() not to block.
768 : *
769 : * If that changes in future we need to use
770 : * gensec_update_send/recv here!
771 : */
772 205 : status = gensec_update(tkey->gensec, mem_ctx,
773 : *key, reply);
774 :
775 205 : if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
776 0 : *dns_auth_error = DNS_RCODE_OK;
777 0 : return status;
778 : }
779 :
780 205 : if (NT_STATUS_IS_OK(status)) {
781 :
782 205 : status = gensec_session_info(tkey->gensec, tkey, &tkey->session_info);
783 205 : if (!NT_STATUS_IS_OK(status)) {
784 0 : *dns_auth_error = DNS_RCODE_BADKEY;
785 0 : return status;
786 : }
787 205 : *dns_auth_error = DNS_RCODE_OK;
788 : }
789 :
790 205 : return status;
791 : }
792 :
793 205 : static WERROR handle_tkey(struct dns_server *dns,
794 : TALLOC_CTX *mem_ctx,
795 : const struct dns_name_packet *in,
796 : struct dns_request_state *state,
797 : struct dns_res_rec **answers,
798 : uint16_t *ancount)
799 : {
800 205 : struct dns_res_rec *in_tkey = NULL;
801 : struct dns_res_rec *ret_tkey;
802 : uint16_t i;
803 :
804 205 : for (i = 0; i < in->arcount; i++) {
805 205 : if (in->additional[i].rr_type == DNS_QTYPE_TKEY) {
806 205 : in_tkey = &in->additional[i];
807 205 : break;
808 : }
809 : }
810 :
811 : /* If this is a TKEY query, it should have a TKEY RR.
812 : * Behaviour is not really specified in RFC 2930 or RFC 3645, but
813 : * FORMAT_ERROR seems to be what BIND uses .*/
814 205 : if (in_tkey == NULL) {
815 0 : return DNS_ERR(FORMAT_ERROR);
816 : }
817 :
818 205 : ret_tkey = talloc_zero(mem_ctx, struct dns_res_rec);
819 205 : if (ret_tkey == NULL) {
820 0 : return WERR_NOT_ENOUGH_MEMORY;
821 : }
822 :
823 205 : ret_tkey->name = talloc_strdup(ret_tkey, in_tkey->name);
824 205 : if (ret_tkey->name == NULL) {
825 0 : return WERR_NOT_ENOUGH_MEMORY;
826 : }
827 :
828 205 : ret_tkey->rr_type = DNS_QTYPE_TKEY;
829 205 : ret_tkey->rr_class = DNS_QCLASS_ANY;
830 205 : ret_tkey->length = UINT16_MAX;
831 :
832 205 : ret_tkey->rdata.tkey_record.algorithm = talloc_strdup(ret_tkey,
833 : in_tkey->rdata.tkey_record.algorithm);
834 205 : if (ret_tkey->rdata.tkey_record.algorithm == NULL) {
835 0 : return WERR_NOT_ENOUGH_MEMORY;
836 : }
837 :
838 205 : ret_tkey->rdata.tkey_record.inception = in_tkey->rdata.tkey_record.inception;
839 205 : ret_tkey->rdata.tkey_record.expiration = in_tkey->rdata.tkey_record.expiration;
840 205 : ret_tkey->rdata.tkey_record.mode = in_tkey->rdata.tkey_record.mode;
841 :
842 205 : switch (in_tkey->rdata.tkey_record.mode) {
843 0 : case DNS_TKEY_MODE_DH:
844 : /* FIXME: According to RFC 2930, we MUST support this, but we don't.
845 : * Still, claim it's a bad key instead of a bad mode */
846 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
847 0 : break;
848 205 : case DNS_TKEY_MODE_GSSAPI: {
849 : NTSTATUS status;
850 : struct dns_server_tkey *tkey;
851 : DATA_BLOB key;
852 : DATA_BLOB reply;
853 205 : bool created = false;
854 :
855 205 : tkey = dns_find_tkey(dns->tkeys, in->questions[0].name);
856 205 : if (tkey != NULL && tkey->complete) {
857 : /* TODO: check if the key is still valid */
858 0 : DEBUG(1, ("Rejecting tkey negotiation for already established key\n"));
859 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADNAME;
860 205 : break;
861 : }
862 :
863 205 : if (tkey == NULL) {
864 388 : status = create_tkey(
865 : mem_ctx,
866 : dns,
867 205 : in->questions[0].name,
868 : in_tkey->rdata.tkey_record.algorithm,
869 : state->remote_address,
870 : state->local_address,
871 : &tkey);
872 205 : if (!NT_STATUS_IS_OK(status)) {
873 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
874 0 : return ntstatus_to_werror(status);
875 : }
876 205 : created = true;
877 : }
878 :
879 205 : key.data = in_tkey->rdata.tkey_record.key_data;
880 205 : key.length = in_tkey->rdata.tkey_record.key_size;
881 :
882 205 : status = accept_gss_ticket(ret_tkey, dns, tkey, &key, &reply,
883 : &ret_tkey->rdata.tkey_record.error);
884 205 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
885 0 : DEBUG(1, ("More processing required\n"));
886 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
887 205 : } else if (NT_STATUS_IS_OK(status)) {
888 205 : DBG_DEBUG("Tkey handshake completed\n");
889 205 : ret_tkey->rdata.tkey_record.key_size = reply.length;
890 205 : ret_tkey->rdata.tkey_record.key_data = talloc_memdup(ret_tkey,
891 : reply.data,
892 : reply.length);
893 205 : if (ret_tkey->rdata.tkey_record.key_data == NULL) {
894 0 : return WERR_NOT_ENOUGH_MEMORY;
895 : }
896 205 : state->sign = true;
897 205 : state->key_name = talloc_strdup(state->mem_ctx, tkey->name);
898 205 : if (state->key_name == NULL) {
899 0 : return WERR_NOT_ENOUGH_MEMORY;
900 : }
901 205 : if (created) {
902 205 : add_tkey(dns->tkeys, &tkey);
903 : }
904 : } else {
905 0 : DEBUG(1, ("GSS key negotiation returned %s\n", nt_errstr(status)));
906 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
907 : }
908 :
909 205 : break;
910 : }
911 0 : case DNS_TKEY_MODE_DELETE:
912 : /* TODO: implement me */
913 0 : DEBUG(1, ("Should delete tkey here\n"));
914 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_OK;
915 0 : break;
916 0 : case DNS_TKEY_MODE_NULL:
917 : case DNS_TKEY_MODE_SERVER:
918 : case DNS_TKEY_MODE_CLIENT:
919 : case DNS_TKEY_MODE_LAST:
920 : /* We don't have to implement these, return a mode error */
921 0 : ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADMODE;
922 0 : break;
923 0 : default:
924 0 : DEBUG(1, ("Unsupported TKEY mode %d\n",
925 : in_tkey->rdata.tkey_record.mode));
926 : }
927 :
928 205 : *answers = ret_tkey;
929 205 : *ancount = 1;
930 :
931 205 : return WERR_OK;
932 : }
933 :
934 : struct dns_server_process_query_state {
935 : struct tevent_context *ev;
936 : struct dns_server *dns;
937 : struct dns_name_question *question;
938 :
939 : struct dns_res_rec *answers;
940 : uint16_t ancount;
941 : struct dns_res_rec *nsrecs;
942 : uint16_t nscount;
943 : struct dns_res_rec *additional;
944 : uint16_t arcount;
945 : struct forwarder_string *forwarders;
946 : };
947 :
948 : static void dns_server_process_query_got_auth(struct tevent_req *subreq);
949 : static void dns_server_process_query_got_response(struct tevent_req *subreq);
950 :
951 31623 : struct tevent_req *dns_server_process_query_send(
952 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
953 : struct dns_server *dns, struct dns_request_state *req_state,
954 : const struct dns_name_packet *in)
955 : {
956 : struct tevent_req *req, *subreq;
957 : struct dns_server_process_query_state *state;
958 31623 : const char **forwarders = NULL;
959 : unsigned int i;
960 :
961 31623 : req = tevent_req_create(mem_ctx, &state,
962 : struct dns_server_process_query_state);
963 31623 : if (req == NULL) {
964 0 : return NULL;
965 : }
966 31623 : if (in->qdcount != 1) {
967 4 : tevent_req_werror(req, DNS_ERR(FORMAT_ERROR));
968 4 : return tevent_req_post(req, ev);
969 : }
970 :
971 : /* Windows returns NOT_IMPLEMENTED on this as well */
972 31619 : if (in->questions[0].question_class == DNS_QCLASS_NONE) {
973 4 : tevent_req_werror(req, DNS_ERR(NOT_IMPLEMENTED));
974 4 : return tevent_req_post(req, ev);
975 : }
976 :
977 31615 : if (in->questions[0].question_type == DNS_QTYPE_TKEY) {
978 : WERROR err;
979 :
980 388 : err = handle_tkey(dns, state, in, req_state,
981 388 : &state->answers, &state->ancount);
982 205 : if (tevent_req_werror(req, err)) {
983 0 : return tevent_req_post(req, ev);
984 : }
985 205 : tevent_req_done(req);
986 205 : return tevent_req_post(req, ev);
987 : }
988 :
989 31410 : state->dns = dns;
990 31410 : state->ev = ev;
991 31410 : state->question = &in->questions[0];
992 :
993 31410 : forwarders = lpcfg_dns_forwarder(dns->task->lp_ctx);
994 32270 : for (i = 0; forwarders != NULL && forwarders[i] != NULL; i++) {
995 860 : struct forwarder_string *f = talloc_zero(state,
996 : struct forwarder_string);
997 860 : f->forwarder = forwarders[i];
998 860 : DLIST_ADD_END(state->forwarders, f);
999 : }
1000 :
1001 31410 : if (dns_authoritative_for_zone(dns, in->questions[0].name)) {
1002 :
1003 31391 : req_state->flags |= DNS_FLAG_AUTHORITATIVE;
1004 :
1005 : /*
1006 : * Initialize the response arrays, so that we can use
1007 : * them as their own talloc contexts when doing the
1008 : * realloc
1009 : */
1010 31391 : state->answers = talloc_array(state, struct dns_res_rec, 0);
1011 31391 : if (tevent_req_nomem(state->answers, req)) {
1012 0 : return tevent_req_post(req, ev);
1013 : }
1014 31391 : state->nsrecs = talloc_array(state, struct dns_res_rec, 0);
1015 31391 : if (tevent_req_nomem(state->nsrecs, req)) {
1016 0 : return tevent_req_post(req, ev);
1017 : }
1018 :
1019 62473 : subreq = handle_authoritative_send(
1020 : state, ev, dns, (forwarders == NULL ? NULL : forwarders[0]),
1021 62473 : &in->questions[0], &state->answers, &state->nsrecs,
1022 : 0); /* cname_depth */
1023 31391 : if (tevent_req_nomem(subreq, req)) {
1024 0 : return tevent_req_post(req, ev);
1025 : }
1026 31391 : tevent_req_set_callback(
1027 : subreq, dns_server_process_query_got_auth, req);
1028 31391 : return req;
1029 : }
1030 :
1031 27 : if ((req_state->flags & DNS_FLAG_RECURSION_DESIRED) &&
1032 16 : (req_state->flags & DNS_FLAG_RECURSION_AVAIL)) {
1033 16 : DEBUG(5, ("Not authoritative for '%s', forwarding\n",
1034 : in->questions[0].name));
1035 :
1036 16 : subreq = ask_forwarder_send(state, ev,
1037 : (forwarders == NULL ? NULL : forwarders[0]),
1038 8 : &in->questions[0]);
1039 16 : if (tevent_req_nomem(subreq, req)) {
1040 0 : return tevent_req_post(req, ev);
1041 : }
1042 16 : tevent_req_set_callback(
1043 : subreq, dns_server_process_query_got_response, req);
1044 16 : return req;
1045 : }
1046 :
1047 3 : tevent_req_werror(req, DNS_ERR(NAME_ERROR));
1048 3 : return tevent_req_post(req, ev);
1049 : }
1050 :
1051 26 : static void dns_server_process_query_got_response(struct tevent_req *subreq)
1052 : {
1053 26 : struct tevent_req *req = tevent_req_callback_data(
1054 : subreq, struct tevent_req);
1055 26 : struct dns_server_process_query_state *state = tevent_req_data(
1056 : req, struct dns_server_process_query_state);
1057 : WERROR werr;
1058 :
1059 26 : werr = ask_forwarder_recv(subreq, state,
1060 : &state->answers, &state->ancount,
1061 : &state->nsrecs, &state->nscount,
1062 : &state->additional, &state->arcount);
1063 26 : TALLOC_FREE(subreq);
1064 :
1065 : /* If you get an error, attempt a different forwarder */
1066 26 : if (!W_ERROR_IS_OK(werr)) {
1067 16 : if (state->forwarders != NULL) {
1068 16 : DLIST_REMOVE(state->forwarders, state->forwarders);
1069 : }
1070 :
1071 : /* If you have run out of forwarders, simply finish */
1072 16 : if (state->forwarders == NULL) {
1073 6 : tevent_req_werror(req, werr);
1074 11 : return;
1075 : }
1076 :
1077 10 : DEBUG(5, ("DNS query returned %s, trying another forwarder.\n",
1078 : win_errstr(werr)));
1079 15 : subreq = ask_forwarder_send(state, state->ev,
1080 10 : state->forwarders->forwarder,
1081 : state->question);
1082 :
1083 10 : if (tevent_req_nomem(subreq, req)) {
1084 0 : return;
1085 : }
1086 :
1087 10 : tevent_req_set_callback(subreq,
1088 : dns_server_process_query_got_response,
1089 : req);
1090 10 : return;
1091 : }
1092 :
1093 10 : tevent_req_done(req);
1094 : }
1095 :
1096 31429 : static void dns_server_process_query_got_auth(struct tevent_req *subreq)
1097 : {
1098 31429 : struct tevent_req *req = tevent_req_callback_data(
1099 : subreq, struct tevent_req);
1100 31429 : struct dns_server_process_query_state *state = tevent_req_data(
1101 : req, struct dns_server_process_query_state);
1102 : WERROR werr;
1103 : WERROR werr2;
1104 :
1105 31429 : werr = handle_authoritative_recv(subreq);
1106 31429 : TALLOC_FREE(subreq);
1107 :
1108 : /* If you get an error, attempt a different forwarder */
1109 31429 : if (!W_ERROR_IS_OK(werr)) {
1110 20456 : if (state->forwarders != NULL) {
1111 72 : DLIST_REMOVE(state->forwarders, state->forwarders);
1112 : }
1113 :
1114 : /* If you have run out of forwarders, simply finish */
1115 20456 : if (state->forwarders == NULL) {
1116 40807 : werr2 = add_zone_authority_record(state->dns,
1117 : state,
1118 20418 : state->question,
1119 : &state->nsrecs);
1120 20418 : if (tevent_req_werror(req, werr2)) {
1121 6 : DBG_WARNING("Failed to add SOA record: %s\n",
1122 : win_errstr(werr2));
1123 20460 : return;
1124 : }
1125 :
1126 20412 : state->ancount = talloc_array_length(state->answers);
1127 20412 : state->nscount = talloc_array_length(state->nsrecs);
1128 20412 : state->arcount = talloc_array_length(state->additional);
1129 :
1130 20412 : tevent_req_werror(req, werr);
1131 20412 : return;
1132 : }
1133 :
1134 38 : DEBUG(5, ("Error: %s, trying a different forwarder.\n",
1135 : win_errstr(werr)));
1136 57 : subreq = handle_authoritative_send(state, state->ev, state->dns,
1137 38 : state->forwarders->forwarder,
1138 : state->question, &state->answers,
1139 : &state->nsrecs,
1140 : 0); /* cname_depth */
1141 :
1142 38 : if (tevent_req_nomem(subreq, req)) {
1143 0 : return;
1144 : }
1145 :
1146 38 : tevent_req_set_callback(subreq,
1147 : dns_server_process_query_got_auth,
1148 : req);
1149 38 : return;
1150 : }
1151 :
1152 21666 : werr2 = add_zone_authority_record(state->dns,
1153 : state,
1154 10973 : state->question,
1155 : &state->nsrecs);
1156 10973 : if (tevent_req_werror(req, werr2)) {
1157 0 : DBG_WARNING("Failed to add SOA record: %s\n",
1158 : win_errstr(werr2));
1159 0 : return;
1160 : }
1161 :
1162 10973 : state->ancount = talloc_array_length(state->answers);
1163 10973 : state->nscount = talloc_array_length(state->nsrecs);
1164 10973 : state->arcount = talloc_array_length(state->additional);
1165 :
1166 10973 : tevent_req_done(req);
1167 : }
1168 :
1169 31623 : WERROR dns_server_process_query_recv(
1170 : struct tevent_req *req, TALLOC_CTX *mem_ctx,
1171 : struct dns_res_rec **answers, uint16_t *ancount,
1172 : struct dns_res_rec **nsrecs, uint16_t *nscount,
1173 : struct dns_res_rec **additional, uint16_t *arcount)
1174 : {
1175 31623 : struct dns_server_process_query_state *state = tevent_req_data(
1176 : req, struct dns_server_process_query_state);
1177 31623 : WERROR err = WERR_OK;
1178 :
1179 31623 : if (tevent_req_is_werror(req, &err)) {
1180 :
1181 20448 : if ((!W_ERROR_EQUAL(err, DNS_ERR(NAME_ERROR))) &&
1182 20 : (!W_ERROR_EQUAL(err, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST))) {
1183 14 : return err;
1184 : }
1185 : }
1186 31609 : *answers = talloc_move(mem_ctx, &state->answers);
1187 31609 : *ancount = state->ancount;
1188 31609 : *nsrecs = talloc_move(mem_ctx, &state->nsrecs);
1189 31609 : *nscount = state->nscount;
1190 31609 : *additional = talloc_move(mem_ctx, &state->additional);
1191 31609 : *arcount = state->arcount;
1192 31609 : return err;
1193 : }
|