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