LCOV - code coverage report
Current view: top level - source4/dns_server - dns_query.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 419 567 73.9 %
Date: 2021-08-25 13:27:56 Functions: 21 22 95.5 %

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

Generated by: LCOV version 1.13