Merge branch 'master' of ctdb into 'master' of samba
[sfrench/samba-autobuild/.git] / source4 / dns_server / dns_update.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    DNS server handler for update requests
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 "libcli/util/ntstatus.h"
24 #include "librpc/ndr/libndr.h"
25 #include "librpc/gen_ndr/ndr_dns.h"
26 #include "librpc/gen_ndr/ndr_dnsp.h"
27 #include <ldb.h>
28 #include "param/param.h"
29 #include "param/loadparm.h"
30 #include "dsdb/samdb/samdb.h"
31 #include "dsdb/common/util.h"
32 #include "smbd/service_task.h"
33 #include "dns_server/dns_server.h"
34 #include "auth/auth.h"
35
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_DNS
38
39 static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
40                              const struct dns_res_rec *rrec,
41                              struct dnsp_DnssrvRpcRecord *r);
42
43 static WERROR check_one_prerequisite(struct dns_server *dns,
44                                      TALLOC_CTX *mem_ctx,
45                                      const struct dns_name_question *zone,
46                                      const struct dns_res_rec *pr,
47                                      bool *final_result)
48 {
49         bool match;
50         WERROR werror;
51         struct ldb_dn *dn;
52         uint16_t i;
53         bool found = false;
54         struct dnsp_DnssrvRpcRecord *rec = NULL;
55         struct dnsp_DnssrvRpcRecord *ans;
56         uint16_t acount;
57
58         size_t host_part_len = 0;
59
60         *final_result = true;
61
62         if (pr->ttl != 0) {
63                 return DNS_ERR(FORMAT_ERROR);
64         }
65
66         match = dns_name_match(zone->name, pr->name, &host_part_len);
67         if (!match) {
68                 return DNS_ERR(NOTZONE);
69         }
70
71         werror = dns_name2dn(dns, mem_ctx, pr->name, &dn);
72         W_ERROR_NOT_OK_RETURN(werror);
73
74         if (pr->rr_class == DNS_QCLASS_ANY) {
75
76                 if (pr->length != 0) {
77                         return DNS_ERR(FORMAT_ERROR);
78                 }
79
80
81                 if (pr->rr_type == DNS_QTYPE_ALL) {
82                         /*
83                          */
84                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
85                         W_ERROR_NOT_OK_RETURN(werror);
86
87                         if (acount == 0) {
88                                 return DNS_ERR(NAME_ERROR);
89                         }
90                 } else {
91                         /*
92                          */
93                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
94                         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
95                                 return DNS_ERR(NXRRSET);
96                         }
97                         W_ERROR_NOT_OK_RETURN(werror);
98
99                         for (i = 0; i < acount; i++) {
100                                 if (ans[i].wType == pr->rr_type) {
101                                         found = true;
102                                         break;
103                                 }
104                         }
105                         if (!found) {
106                                 return DNS_ERR(NXRRSET);
107                         }
108                 }
109
110                 /*
111                  * RFC2136 3.2.5 doesn't actually mention the need to return
112                  * OK here, but otherwise we'd always return a FORMAT_ERROR
113                  * later on. This also matches Microsoft DNS behavior.
114                  */
115                 return WERR_OK;
116         }
117
118         if (pr->rr_class == DNS_QCLASS_NONE) {
119                 if (pr->length != 0) {
120                         return DNS_ERR(FORMAT_ERROR);
121                 }
122
123                 if (pr->rr_type == DNS_QTYPE_ALL) {
124                         /*
125                          */
126                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
127                         if (W_ERROR_EQUAL(werror, WERR_OK)) {
128                                 return DNS_ERR(YXDOMAIN);
129                         }
130                 } else {
131                         /*
132                          */
133                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
134                         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
135                                 werror = WERR_OK;
136                                 ans = NULL;
137                                 acount = 0;
138                         }
139
140                         for (i = 0; i < acount; i++) {
141                                 if (ans[i].wType == pr->rr_type) {
142                                         found = true;
143                                         break;
144                                 }
145                         }
146                         if (found) {
147                                 return DNS_ERR(YXRRSET);
148                         }
149                 }
150
151                 /*
152                  * RFC2136 3.2.5 doesn't actually mention the need to return
153                  * OK here, but otherwise we'd always return a FORMAT_ERROR
154                  * later on. This also matches Microsoft DNS behavior.
155                  */
156                 return WERR_OK;
157         }
158
159         if (pr->rr_class != zone->question_class) {
160                 return DNS_ERR(FORMAT_ERROR);
161         }
162
163         *final_result = false;
164
165         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
166         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
167                 return DNS_ERR(NXRRSET);
168         }
169         W_ERROR_NOT_OK_RETURN(werror);
170
171         rec = talloc_zero(mem_ctx, struct dnsp_DnssrvRpcRecord);
172         W_ERROR_HAVE_NO_MEMORY(rec);
173
174         werror = dns_rr_to_dnsp(rec, pr, rec);
175         W_ERROR_NOT_OK_RETURN(werror);
176
177         for (i = 0; i < acount; i++) {
178                 if (dns_records_match(rec, &ans[i])) {
179                         found = true;
180                         break;
181                 }
182         }
183
184         if (!found) {
185                 return DNS_ERR(NXRRSET);
186         }
187
188         return WERR_OK;
189 }
190
191 static WERROR check_prerequisites(struct dns_server *dns,
192                                   TALLOC_CTX *mem_ctx,
193                                   const struct dns_name_question *zone,
194                                   const struct dns_res_rec *prereqs, uint16_t count)
195 {
196         uint16_t i;
197         WERROR final_error = WERR_OK;
198
199         for (i = 0; i < count; i++) {
200                 bool final;
201                 WERROR werror;
202
203                 werror = check_one_prerequisite(dns, mem_ctx, zone,
204                                                 &prereqs[i], &final);
205                 if (!W_ERROR_IS_OK(werror)) {
206                         if (final) {
207                                 return werror;
208                         }
209                         if (W_ERROR_IS_OK(final_error)) {
210                                 final_error = werror;
211                         }
212                 }
213         }
214
215         if (!W_ERROR_IS_OK(final_error)) {
216                 return final_error;
217         }
218
219         return WERR_OK;
220 }
221
222 static WERROR update_prescan(const struct dns_name_question *zone,
223                              const struct dns_res_rec *updates, uint16_t count)
224 {
225         const struct dns_res_rec *r;
226         uint16_t i;
227         size_t host_part_len;
228         bool match;
229
230         for (i = 0; i < count; i++) {
231                 r = &updates[i];
232                 match = dns_name_match(zone->name, r->name, &host_part_len);
233                 if (!match) {
234                         return DNS_ERR(NOTZONE);
235                 }
236                 if (zone->question_class == r->rr_class) {
237                         if (r->rr_type == DNS_QTYPE_ALL) {
238                                 return DNS_ERR(FORMAT_ERROR);
239                         }
240                         if (r->rr_type == DNS_QTYPE_AXFR) {
241                                 return DNS_ERR(FORMAT_ERROR);
242                         }
243                         if (r->rr_type == DNS_QTYPE_MAILB) {
244                                 return DNS_ERR(FORMAT_ERROR);
245                         }
246                         if (r->rr_type == DNS_QTYPE_MAILA) {
247                                 return DNS_ERR(FORMAT_ERROR);
248                         }
249                 } else if (r->rr_class == DNS_QCLASS_ANY) {
250                         if (r->ttl != 0) {
251                                 return DNS_ERR(FORMAT_ERROR);
252                         }
253                         if (r->length != 0) {
254                                 return DNS_ERR(FORMAT_ERROR);
255                         }
256                         if (r->rr_type == DNS_QTYPE_AXFR) {
257                                 return DNS_ERR(FORMAT_ERROR);
258                         }
259                         if (r->rr_type == DNS_QTYPE_MAILB) {
260                                 return DNS_ERR(FORMAT_ERROR);
261                         }
262                         if (r->rr_type == DNS_QTYPE_MAILA) {
263                                 return DNS_ERR(FORMAT_ERROR);
264                         }
265                 } else if (r->rr_class == DNS_QCLASS_NONE) {
266                         if (r->ttl != 0) {
267                                 return DNS_ERR(FORMAT_ERROR);
268                         }
269                         if (r->rr_type == DNS_QTYPE_ALL) {
270                                 return DNS_ERR(FORMAT_ERROR);
271                         }
272                         if (r->rr_type == DNS_QTYPE_AXFR) {
273                                 return DNS_ERR(FORMAT_ERROR);
274                         }
275                         if (r->rr_type == DNS_QTYPE_MAILB) {
276                                 return DNS_ERR(FORMAT_ERROR);
277                         }
278                         if (r->rr_type == DNS_QTYPE_MAILA) {
279                                 return DNS_ERR(FORMAT_ERROR);
280                         }
281                 } else {
282                         return DNS_ERR(FORMAT_ERROR);
283                 }
284         }
285         return WERR_OK;
286 }
287
288 static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
289                              const struct dns_res_rec *rrec,
290                              struct dnsp_DnssrvRpcRecord *r)
291 {
292         char *tmp;
293         char *txt_record_txt;
294         char *saveptr = NULL;
295
296         if (rrec->rr_type == DNS_QTYPE_ALL) {
297                 return DNS_ERR(FORMAT_ERROR);
298         }
299
300         ZERO_STRUCTP(r);
301
302         r->wType = rrec->rr_type;
303         r->dwTtlSeconds = rrec->ttl;
304         r->rank = DNS_RANK_ZONE;
305         /* TODO: Autogenerate this somehow */
306         r->dwSerial = 110;
307
308         /* If we get QCLASS_ANY, we're done here */
309         if (rrec->rr_class == DNS_QCLASS_ANY) {
310                 goto done;
311         }
312
313         switch(rrec->rr_type) {
314         case DNS_QTYPE_A:
315                 r->data.ipv4 = talloc_strdup(mem_ctx, rrec->rdata.ipv4_record);
316                 W_ERROR_HAVE_NO_MEMORY(r->data.ipv4);
317                 break;
318         case DNS_QTYPE_AAAA:
319                 r->data.ipv6 = talloc_strdup(mem_ctx, rrec->rdata.ipv6_record);
320                 W_ERROR_HAVE_NO_MEMORY(r->data.ipv6);
321                 break;
322         case DNS_QTYPE_NS:
323                 r->data.ns = talloc_strdup(mem_ctx, rrec->rdata.ns_record);
324                 W_ERROR_HAVE_NO_MEMORY(r->data.ns);
325                 break;
326         case DNS_QTYPE_CNAME:
327                 r->data.cname = talloc_strdup(mem_ctx, rrec->rdata.cname_record);
328                 W_ERROR_HAVE_NO_MEMORY(r->data.cname);
329                 break;
330         case DNS_QTYPE_SRV:
331                 r->data.srv.wPriority = rrec->rdata.srv_record.priority;
332                 r->data.srv.wWeight = rrec->rdata.srv_record.weight;
333                 r->data.srv.wPort = rrec->rdata.srv_record.port;
334                 r->data.srv.nameTarget = talloc_strdup(mem_ctx,
335                                 rrec->rdata.srv_record.target);
336                 W_ERROR_HAVE_NO_MEMORY(r->data.srv.nameTarget);
337                 break;
338         case DNS_QTYPE_PTR:
339                 r->data.ptr = talloc_strdup(mem_ctx, rrec->rdata.ptr_record);
340                 W_ERROR_HAVE_NO_MEMORY(r->data.ptr);
341                 break;
342         case DNS_QTYPE_MX:
343                 r->data.mx.wPriority = rrec->rdata.mx_record.preference;
344                 r->data.mx.nameTarget = talloc_strdup(mem_ctx,
345                                 rrec->rdata.mx_record.exchange);
346                 W_ERROR_HAVE_NO_MEMORY(r->data.mx.nameTarget);
347                 break;
348         case DNS_QTYPE_TXT:
349                 r->data.txt.count = 0;
350                 r->data.txt.str = talloc_array(mem_ctx, const char *,
351                                                r->data.txt.count);
352                 W_ERROR_HAVE_NO_MEMORY(r->data.txt.str);
353
354                 txt_record_txt = talloc_strdup(r->data.txt.str,
355                                                rrec->rdata.txt_record.txt);
356                 W_ERROR_HAVE_NO_MEMORY(txt_record_txt);
357
358                 tmp = strtok_r(txt_record_txt, "\"", &saveptr);
359                 while (tmp) {
360                         if (strcmp(tmp, " ") == 0) {
361                                 tmp = strtok_r(NULL, "\"", &saveptr);
362                                 continue;
363                         }
364                         r->data.txt.str = talloc_realloc(mem_ctx, r->data.txt.str, const char *,
365                                                         r->data.txt.count+1);
366                         r->data.txt.str[r->data.txt.count] = talloc_strdup(r->data.txt.str, tmp);
367                         W_ERROR_HAVE_NO_MEMORY(r->data.txt.str[r->data.txt.count]);
368
369                         r->data.txt.count++;
370                         tmp = strtok_r(NULL, "\"", &saveptr);
371                 }
372
373                 break;
374         default:
375                 DEBUG(0, ("Got a qytpe of %d\n", rrec->rr_type));
376                 return DNS_ERR(NOT_IMPLEMENTED);
377         }
378
379 done:
380
381         return WERR_OK;
382 }
383
384
385 static WERROR handle_one_update(struct dns_server *dns,
386                                 TALLOC_CTX *mem_ctx,
387                                 const struct dns_name_question *zone,
388                                 const struct dns_res_rec *update,
389                                 const struct dns_server_tkey *tkey)
390 {
391         struct dnsp_DnssrvRpcRecord *recs = NULL;
392         uint16_t rcount = 0;
393         struct ldb_dn *dn;
394         uint16_t i;
395         WERROR werror;
396         bool needs_add = false;
397
398         DEBUG(2, ("Looking at record: \n"));
399         if (DEBUGLVL(2)) {
400                 NDR_PRINT_DEBUG(dns_res_rec, discard_const(update));
401         }
402
403         switch (update->rr_type) {
404         case DNS_QTYPE_A:
405         case DNS_QTYPE_NS:
406         case DNS_QTYPE_CNAME:
407         case DNS_QTYPE_SOA:
408         case DNS_QTYPE_PTR:
409         case DNS_QTYPE_MX:
410         case DNS_QTYPE_AAAA:
411         case DNS_QTYPE_SRV:
412         case DNS_QTYPE_TXT:
413                 break;
414         default:
415                 DEBUG(0, ("Can't handle updates of type %u yet\n",
416                           update->rr_type));
417                 return DNS_ERR(NOT_IMPLEMENTED);
418         }
419
420         werror = dns_name2dn(dns, mem_ctx, update->name, &dn);
421         W_ERROR_NOT_OK_RETURN(werror);
422
423         werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rcount);
424         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
425                 recs = NULL;
426                 rcount = 0;
427                 needs_add = true;
428                 werror = WERR_OK;
429         }
430         W_ERROR_NOT_OK_RETURN(werror);
431
432         if (update->rr_class == zone->question_class) {
433                 if (update->rr_type == DNS_QTYPE_CNAME) {
434                         /*
435                          * If there is a record in the directory
436                          * that's not a CNAME, ignore update
437                          */
438                         for (i = 0; i < rcount; i++) {
439                                 if (recs[i].wType != DNS_TYPE_CNAME) {
440                                         DEBUG(5, ("Skipping update\n"));
441                                         return WERR_OK;
442                                 }
443                                 break;
444                         }
445
446                         /*
447                          * There should be no entries besides one CNAME record
448                          * per name, so replace everything with the new CNAME
449                          */
450
451                         rcount = 1;
452                         recs = talloc_realloc(mem_ctx, recs,
453                                         struct dnsp_DnssrvRpcRecord, rcount);
454                         W_ERROR_HAVE_NO_MEMORY(recs);
455
456                         werror = dns_rr_to_dnsp(recs, update, &recs[0]);
457                         W_ERROR_NOT_OK_RETURN(werror);
458
459                         werror = dns_replace_records(dns, mem_ctx, dn,
460                                                      needs_add, recs, rcount);
461                         W_ERROR_NOT_OK_RETURN(werror);
462
463                         return WERR_OK;
464                 } else {
465                         /*
466                          * If there is a CNAME record for this name,
467                          * ignore update
468                          */
469                         for (i = 0; i < rcount; i++) {
470                                 if (recs[i].wType == DNS_TYPE_CNAME) {
471                                         DEBUG(5, ("Skipping update\n"));
472                                         return WERR_OK;
473                                 }
474                         }
475                 }
476                 if (update->rr_type == DNS_QTYPE_SOA) {
477                         bool found = false;
478
479                         /*
480                          * If the zone has no SOA record?? or update's
481                          * serial number is smaller than existing SOA's,
482                          * ignore update
483                          */
484                         for (i = 0; i < rcount; i++) {
485                                 if (recs[i].wType == DNS_TYPE_SOA) {
486                                         uint16_t n, o;
487
488                                         n = update->rdata.soa_record.serial;
489                                         o = recs[i].data.soa.serial;
490                                         /*
491                                          * TODO: Implement RFC 1982 comparison
492                                          * logic for RFC2136
493                                          */
494                                         if (n <= o) {
495                                                 DEBUG(5, ("Skipping update\n"));
496                                                 return WERR_OK;
497                                         }
498                                         found = true;
499                                         break;
500                                 }
501                         }
502                         if (!found) {
503                                 DEBUG(5, ("Skipping update\n"));
504                                 return WERR_OK;
505                         }
506
507                         werror = dns_rr_to_dnsp(mem_ctx, update, &recs[i]);
508                         W_ERROR_NOT_OK_RETURN(werror);
509
510                         for (i++; i < rcount; i++) {
511                                 if (recs[i].wType != DNS_TYPE_SOA) {
512                                         continue;
513                                 }
514
515                                 ZERO_STRUCT(recs[i]);
516                         }
517
518                         werror = dns_replace_records(dns, mem_ctx, dn,
519                                                      needs_add, recs, rcount);
520                         W_ERROR_NOT_OK_RETURN(werror);
521
522                         return WERR_OK;
523                 }
524
525                 recs = talloc_realloc(mem_ctx, recs,
526                                 struct dnsp_DnssrvRpcRecord, rcount+1);
527                 W_ERROR_HAVE_NO_MEMORY(recs);
528
529                 werror = dns_rr_to_dnsp(recs, update, &recs[rcount]);
530                 W_ERROR_NOT_OK_RETURN(werror);
531
532                 for (i = 0; i < rcount; i++) {
533                         if (!dns_records_match(&recs[i], &recs[rcount])) {
534                                 continue;
535                         }
536
537                         recs[i] = recs[rcount];
538
539                         werror = dns_replace_records(dns, mem_ctx, dn,
540                                                      needs_add, recs, rcount);
541                         W_ERROR_NOT_OK_RETURN(werror);
542
543                         return WERR_OK;
544                 }
545
546                 werror = dns_replace_records(dns, mem_ctx, dn,
547                                              needs_add, recs, rcount+1);
548                 W_ERROR_NOT_OK_RETURN(werror);
549
550                 return WERR_OK;
551         } else if (update->rr_class == DNS_QCLASS_ANY) {
552                 if (update->rr_type == DNS_QTYPE_ALL) {
553                         if (dns_name_equal(update->name, zone->name)) {
554                                 for (i = 0; i < rcount; i++) {
555
556                                         if (recs[i].wType == DNS_TYPE_SOA) {
557                                                 continue;
558                                         }
559
560                                         if (recs[i].wType == DNS_TYPE_NS) {
561                                                 continue;
562                                         }
563
564                                         ZERO_STRUCT(recs[i]);
565                                 }
566
567                         } else {
568                                 for (i = 0; i < rcount; i++) {
569                                         ZERO_STRUCT(recs[i]);
570                                 }
571                         }
572
573                 } else if (dns_name_equal(update->name, zone->name)) {
574
575                         if (update->rr_type == DNS_QTYPE_SOA) {
576                                 return WERR_OK;
577                         }
578
579                         if (update->rr_type == DNS_QTYPE_NS) {
580                                 return WERR_OK;
581                         }
582                 }
583                 for (i = 0; i < rcount; i++) {
584                         if (recs[i].wType == update->rr_type) {
585                                 ZERO_STRUCT(recs[i]);
586                         }
587                 }
588
589                 werror = dns_replace_records(dns, mem_ctx, dn,
590                                              needs_add, recs, rcount);
591                 W_ERROR_NOT_OK_RETURN(werror);
592
593                 return WERR_OK;
594         } else if (update->rr_class == DNS_QCLASS_NONE) {
595                 struct dnsp_DnssrvRpcRecord *del_rec;
596
597                 if (update->rr_type == DNS_QTYPE_SOA) {
598                         return WERR_OK;
599                 }
600                 if (update->rr_type == DNS_QTYPE_NS) {
601                         bool found = false;
602                         struct dnsp_DnssrvRpcRecord *ns_rec = talloc(mem_ctx,
603                                                 struct dnsp_DnssrvRpcRecord);
604                         W_ERROR_HAVE_NO_MEMORY(ns_rec);
605
606
607                         werror = dns_rr_to_dnsp(ns_rec, update, ns_rec);
608                         W_ERROR_NOT_OK_RETURN(werror);
609
610                         for (i = 0; i < rcount; i++) {
611                                 if (dns_records_match(ns_rec, &recs[i])) {
612                                         found = true;
613                                         break;
614                                 }
615                         }
616                         if (found) {
617                                 return WERR_OK;
618                         }
619                 }
620
621                 del_rec = talloc(mem_ctx, struct dnsp_DnssrvRpcRecord);
622                 W_ERROR_HAVE_NO_MEMORY(del_rec);
623
624                 werror = dns_rr_to_dnsp(del_rec, update, del_rec);
625                 W_ERROR_NOT_OK_RETURN(werror);
626
627                 for (i = 0; i < rcount; i++) {
628                         if (dns_records_match(del_rec, &recs[i])) {
629                                 ZERO_STRUCT(recs[i]);
630                         }
631                 }
632
633                 werror = dns_replace_records(dns, mem_ctx, dn,
634                                              needs_add, recs, rcount);
635                 W_ERROR_NOT_OK_RETURN(werror);
636         }
637
638         return WERR_OK;
639 }
640
641 static WERROR handle_updates(struct dns_server *dns,
642                              TALLOC_CTX *mem_ctx,
643                              const struct dns_name_question *zone,
644                              const struct dns_res_rec *prereqs, uint16_t pcount,
645                              struct dns_res_rec *updates, uint16_t upd_count,
646                              struct dns_server_tkey *tkey)
647 {
648         struct ldb_dn *zone_dn = NULL;
649         WERROR werror = WERR_OK;
650         int ret;
651         uint16_t ri;
652         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
653
654         if (tkey != NULL) {
655                 ret = ldb_set_opaque(dns->samdb, "sessionInfo", tkey->session_info);
656                 if (ret != LDB_SUCCESS) {
657                         DEBUG(1, ("unable to set session info\n"));
658                         werror = DNS_ERR(SERVER_FAILURE);
659                         goto failed;
660                 }
661         }
662
663         werror = dns_name2dn(dns, tmp_ctx, zone->name, &zone_dn);
664         W_ERROR_NOT_OK_GOTO(werror, failed);
665
666         ret = ldb_transaction_start(dns->samdb);
667         if (ret != LDB_SUCCESS) {
668                 werror = DNS_ERR(SERVER_FAILURE);
669                 goto failed;
670         }
671
672         werror = check_prerequisites(dns, tmp_ctx, zone, prereqs, pcount);
673         W_ERROR_NOT_OK_GOTO(werror, failed);
674
675         DEBUG(1, ("update count is %u\n", upd_count));
676
677         for (ri = 0; ri < upd_count; ri++) {
678                 werror = handle_one_update(dns, tmp_ctx, zone,
679                                            &updates[ri], tkey);
680                 W_ERROR_NOT_OK_GOTO(werror, failed);
681         }
682
683         ldb_transaction_commit(dns->samdb);
684         TALLOC_FREE(tmp_ctx);
685
686         if (tkey != NULL) {
687                 ldb_set_opaque(dns->samdb, "sessionInfo",
688                                system_session(dns->task->lp_ctx));
689         }
690
691         return WERR_OK;
692
693 failed:
694         ldb_transaction_cancel(dns->samdb);
695
696         if (tkey != NULL) {
697                 ldb_set_opaque(dns->samdb, "sessionInfo",
698                                system_session(dns->task->lp_ctx));
699         }
700
701         TALLOC_FREE(tmp_ctx);
702         return werror;
703
704 }
705
706 static WERROR dns_update_allowed(struct dns_server *dns,
707                                  struct dns_request_state *state,
708                                  struct dns_server_tkey **tkey)
709 {
710         if (lpcfg_allow_dns_updates(dns->task->lp_ctx) == DNS_UPDATE_ON) {
711                 DEBUG(2, ("All updates allowed.\n"));
712                 return WERR_OK;
713         }
714
715         if (lpcfg_allow_dns_updates(dns->task->lp_ctx) == DNS_UPDATE_OFF) {
716                 DEBUG(2, ("Updates disabled.\n"));
717                 return DNS_ERR(REFUSED);
718         }
719
720         if (state->authenticated == false ) {
721                 DEBUG(2, ("Update not allowed for unsigned packet.\n"));
722                 return DNS_ERR(REFUSED);
723         }
724
725         *tkey = dns_find_tkey(dns->tkeys, state->key_name);
726         if (*tkey == NULL) {
727                 DEBUG(0, ("Authenticated, but key not found. Something is wrong.\n"));
728                 return DNS_ERR(REFUSED);
729         }
730
731         return WERR_OK;
732 }
733
734
735 WERROR dns_server_process_update(struct dns_server *dns,
736                                  struct dns_request_state *state,
737                                  TALLOC_CTX *mem_ctx,
738                                  struct dns_name_packet *in,
739                                  struct dns_res_rec **prereqs,    uint16_t *prereq_count,
740                                  struct dns_res_rec **updates,    uint16_t *update_count,
741                                  struct dns_res_rec **additional, uint16_t *arcount)
742 {
743         struct dns_name_question *zone;
744         const struct dns_server_zone *z;
745         size_t host_part_len = 0;
746         WERROR werror = DNS_ERR(NOT_IMPLEMENTED);
747         struct dns_server_tkey *tkey = NULL;
748
749         if (in->qdcount != 1) {
750                 return DNS_ERR(FORMAT_ERROR);
751         }
752
753         zone = &in->questions[0];
754
755         if (zone->question_class != DNS_QCLASS_IN &&
756             zone->question_class != DNS_QCLASS_ANY) {
757                 return DNS_ERR(NOT_IMPLEMENTED);
758         }
759
760         if (zone->question_type != DNS_QTYPE_SOA) {
761                 return DNS_ERR(FORMAT_ERROR);
762         }
763
764         DEBUG(2, ("Got a dns update request.\n"));
765
766         for (z = dns->zones; z != NULL; z = z->next) {
767                 bool match;
768
769                 match = dns_name_match(z->name, zone->name, &host_part_len);
770                 if (match) {
771                         break;
772                 }
773         }
774
775         if (z == NULL) {
776                 DEBUG(1, ("We're not authoritative for this zone\n"));
777                 return DNS_ERR(NOTAUTH);
778         }
779
780         if (host_part_len != 0) {
781                 /* TODO: We need to delegate this one */
782                 DEBUG(1, ("Would have to delegate zone '%s'.\n", zone->name));
783                 return DNS_ERR(NOT_IMPLEMENTED);
784         }
785
786         *prereq_count = in->ancount;
787         *prereqs = in->answers;
788         werror = check_prerequisites(dns, mem_ctx, in->questions, *prereqs,
789                                      *prereq_count);
790         W_ERROR_NOT_OK_RETURN(werror);
791
792         werror = dns_update_allowed(dns, state, &tkey);
793         if (!W_ERROR_IS_OK(werror)) {
794                 return werror;
795         }
796
797         *update_count = in->nscount;
798         *updates = in->nsrecs;
799         werror = update_prescan(in->questions, *updates, *update_count);
800         W_ERROR_NOT_OK_RETURN(werror);
801
802         werror = handle_updates(dns, mem_ctx, in->questions, *prereqs,
803                                 *prereq_count, *updates, *update_count, tkey);
804         W_ERROR_NOT_OK_RETURN(werror);
805
806         return werror;
807 }