dns_server: Put more code in common
authorAndrew Bartlett <abartlet@samba.org>
Tue, 22 Sep 2015 00:10:00 +0000 (12:10 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 26 Oct 2015 04:11:21 +0000 (05:11 +0100)
This will allow a python module to be written to modify DNS entries in sam.ldb directly

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
source4/dns_server/dns_server.c
source4/dns_server/dns_server.h
source4/dns_server/dns_utils.c
source4/dns_server/dnsserver_common.c
source4/dns_server/dnsserver_common.h

index 66ab738eb43a96c23bac1443160440040beafea8..45d28a77e6bfe510cc190ad08d9c1133dba74cd3 100644 (file)
@@ -725,27 +725,6 @@ static NTSTATUS dns_startup_interfaces(struct dns_server *dns,
        return NT_STATUS_OK;
 }
 
-static int dns_server_sort_zones(struct ldb_message **m1, struct ldb_message **m2)
-{
-       const char *n1, *n2;
-       size_t l1, l2;
-
-       n1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
-       n2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
-
-       l1 = strlen(n1);
-       l2 = strlen(n2);
-
-       /* If the string lengths are not equal just sort by length */
-       if (l1 != l2) {
-               /* If m1 is the larger zone name, return it first */
-               return l2 - l1;
-       }
-
-       /*TODO: We need to compare DNs here, we want the DomainDNSZones first */
-       return 0;
-}
-
 static struct dns_server_tkey_store *tkey_store_init(TALLOC_CTX *mem_ctx,
                                                     uint16_t size)
 {
@@ -769,51 +748,14 @@ static struct dns_server_tkey_store *tkey_store_init(TALLOC_CTX *mem_ctx,
 
 static NTSTATUS dns_server_reload_zones(struct dns_server *dns)
 {
-       int ret;
-       static const char * const attrs[] = { "name", NULL};
-       struct ldb_result *res;
-       int i;
+       NTSTATUS status;
        struct dns_server_zone *new_list = NULL;
        struct dns_server_zone *old_list = NULL;
        struct dns_server_zone *old_zone;
-
-       // TODO: this search does not work against windows
-       ret = dsdb_search(dns->samdb, dns, &res, NULL, LDB_SCOPE_SUBTREE,
-                         attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS, "(objectClass=dnsZone)");
-       if (ret != LDB_SUCCESS) {
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-
-       TYPESAFE_QSORT(res->msgs, res->count, dns_server_sort_zones);
-
-       for (i=0; i < res->count; i++) {
-               struct dns_server_zone *z;
-
-               z = talloc_zero(dns, struct dns_server_zone);
-               if (z == NULL) {
-                       return NT_STATUS_NO_MEMORY;
-               }
-
-               z->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
-               z->dn = talloc_move(z, &res->msgs[i]->dn);
-               /*
-                * Ignore the RootDNSServers zone and zones that we don't support yet
-                * RootDNSServers should never be returned (Windows DNS server don't)
-                * ..TrustAnchors should never be returned as is, (Windows returns
-                * TrustAnchors) and for the moment we don't support DNSSEC so we'd better
-                * not return this zone.
-                */
-               if ((strcmp(z->name, "RootDNSServers") == 0) ||
-                   (strcmp(z->name, "..TrustAnchors") == 0))
-               {
-                       DEBUG(10, ("Ignoring zone %s\n", z->name));
-                       talloc_free(z);
-                       continue;
-               }
-               DLIST_ADD_END(new_list, z, NULL);
+       status = dns_common_zones(dns->samdb, dns, &new_list);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
-
-       old_list = dns->zones;
        dns->zones = new_list;
        while ((old_zone = DLIST_TAIL(old_list)) != NULL) {
                DLIST_REMOVE(old_list, old_zone);
index 64b716a2542e5cbf138038210af8cbfdc78dd351..e5c15ec1532287b38221db87a3d591743590b3b8 100644 (file)
 
 #include "librpc/gen_ndr/dns.h"
 #include "librpc/gen_ndr/ndr_dnsp.h"
+#include "dnsserver_common.h"
 
 struct tsocket_address;
-
-struct dns_server_zone {
-       struct dns_server_zone *prev, *next;
-       const char *name;
-       struct ldb_dn *dn;
-};
-
 struct dns_server_tkey {
        const char *name;
        enum dns_tkey_mode mode;
@@ -87,7 +81,6 @@ WERROR dns_server_process_update(struct dns_server *dns,
                                 struct dns_res_rec **updates,    uint16_t *update_count,
                                 struct dns_res_rec **additional, uint16_t *arcount);
 
-bool dns_name_match(const char *zone, const char *name, size_t *host_part_len);
 bool dns_name_equal(const char *name1, const char *name2);
 bool dns_records_match(struct dnsp_DnssrvRpcRecord *rec1,
                       struct dnsp_DnssrvRpcRecord *rec2);
index 28412eb76818d0d308e6fa6f0d65221bd33e0f03..3092633346e7060745f8872eb2c0bc15d5185bfb 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_DNS
 
-bool dns_name_match(const char *zone, const char *name, size_t *host_part_len)
-{
-       size_t zl = strlen(zone);
-       size_t nl = strlen(name);
-       ssize_t zi, ni;
-       static const size_t fixup = 'a' - 'A';
-
-       if (zl > nl) {
-               return false;
-       }
-
-       for (zi = zl, ni = nl; zi >= 0; zi--, ni--) {
-               char zc = zone[zi];
-               char nc = name[ni];
-
-               /* convert to lower case */
-               if (zc >= 'A' && zc <= 'Z') {
-                       zc += fixup;
-               }
-               if (nc >= 'A' && nc <= 'Z') {
-                       nc += fixup;
-               }
-
-               if (zc != nc) {
-                       return false;
-               }
-       }
-
-       if (ni >= 0) {
-               if (name[ni] != '.') {
-                       return false;
-               }
-
-               ni--;
-       }
-
-       *host_part_len = ni+1;
-
-       return true;
-}
-
 /* Names are equal if they match and there's nothing left over */
 bool dns_name_equal(const char *name1, const char *name2)
 {
@@ -218,51 +177,10 @@ const char *dns_get_authoritative_zone(struct dns_server *dns,
 WERROR dns_name2dn(struct dns_server *dns,
                   TALLOC_CTX *mem_ctx,
                   const char *name,
-                  struct ldb_dn **_dn)
+                  struct ldb_dn **dn)
 {
-       struct ldb_dn *base;
-       struct ldb_dn *dn;
-       const struct dns_server_zone *z;
-       size_t host_part_len = 0;
-
-       if (name == NULL) {
-               return DNS_ERR(FORMAT_ERROR);
-       }
-
-       /*TODO: Check if 'name' is a valid DNS name */
-
-       if (strcmp(name, "") == 0) {
-               base = ldb_get_default_basedn(dns->samdb);
-               dn = ldb_dn_copy(mem_ctx, base);
-               ldb_dn_add_child_fmt(dn, "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
-               *_dn = dn;
-               return WERR_OK;
-       }
-
-       for (z = dns->zones; z != NULL; z = z->next) {
-               bool match;
-
-               match = dns_name_match(z->name, name, &host_part_len);
-               if (match) {
-                       break;
-               }
-       }
-
-       if (z == NULL) {
-               return DNS_ERR(NAME_ERROR);
-       }
-
-       if (host_part_len == 0) {
-               dn = ldb_dn_copy(mem_ctx, z->dn);
-               ldb_dn_add_child_fmt(dn, "DC=@");
-               *_dn = dn;
-               return WERR_OK;
-       }
-
-       dn = ldb_dn_copy(mem_ctx, z->dn);
-       ldb_dn_add_child_fmt(dn, "DC=%*.*s", (int)host_part_len, (int)host_part_len, name);
-       *_dn = dn;
-       return WERR_OK;
+       return dns_common_name2dn(dns->samdb, dns->zones,
+                                 mem_ctx, name, dn);
 }
 
 WERROR dns_generate_options(struct dns_server *dns,
index c49d6ec87a6862bc42694aeea21617a9725a4734..7199ef721d872e69b08ac569c7706b9cb261120f 100644 (file)
@@ -5,6 +5,7 @@
 
    Copyright (C) 2010 Kai Blin
    Copyright (C) 2014 Stefan Metzmacher
+   Copyright (C) 2015 Andrew Bartlett
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +31,7 @@
 #include "dsdb/samdb/samdb.h"
 #include "dsdb/common/util.h"
 #include "dns_server/dnsserver_common.h"
+#include "lib/util/dlinklist.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_DNS
@@ -340,3 +342,171 @@ WERROR dns_common_replace(struct ldb_context *samdb,
 
        return WERR_OK;
 }
+
+bool dns_name_match(const char *zone, const char *name, size_t *host_part_len)
+{
+       size_t zl = strlen(zone);
+       size_t nl = strlen(name);
+       ssize_t zi, ni;
+       static const size_t fixup = 'a' - 'A';
+
+       if (zl > nl) {
+               return false;
+       }
+
+       for (zi = zl, ni = nl; zi >= 0; zi--, ni--) {
+               char zc = zone[zi];
+               char nc = name[ni];
+
+               /* convert to lower case */
+               if (zc >= 'A' && zc <= 'Z') {
+                       zc += fixup;
+               }
+               if (nc >= 'A' && nc <= 'Z') {
+                       nc += fixup;
+               }
+
+               if (zc != nc) {
+                       return false;
+               }
+       }
+
+       if (ni >= 0) {
+               if (name[ni] != '.') {
+                       return false;
+               }
+
+               ni--;
+       }
+
+       *host_part_len = ni+1;
+
+       return true;
+}
+
+WERROR dns_common_name2dn(struct ldb_context *samdb,
+                         struct dns_server_zone *zones,
+                         TALLOC_CTX *mem_ctx,
+                         const char *name,
+                         struct ldb_dn **_dn)
+{
+       struct ldb_dn *base;
+       struct ldb_dn *dn;
+       const struct dns_server_zone *z;
+       size_t host_part_len = 0;
+
+       if (name == NULL) {
+               return DNS_ERR(FORMAT_ERROR);
+       }
+
+       /*TODO: Check if 'name' is a valid DNS name */
+
+       if (strcmp(name, "") == 0) {
+               base = ldb_get_default_basedn(samdb);
+               dn = ldb_dn_copy(mem_ctx, base);
+               ldb_dn_add_child_fmt(dn, "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
+               *_dn = dn;
+               return WERR_OK;
+       }
+
+       for (z = zones; z != NULL; z = z->next) {
+               bool match;
+
+               match = dns_name_match(z->name, name, &host_part_len);
+               if (match) {
+                       break;
+               }
+       }
+
+       if (z == NULL) {
+               return DNS_ERR(NAME_ERROR);
+       }
+
+       if (host_part_len == 0) {
+               dn = ldb_dn_copy(mem_ctx, z->dn);
+               ldb_dn_add_child_fmt(dn, "DC=@");
+               *_dn = dn;
+               return WERR_OK;
+       }
+
+       dn = ldb_dn_copy(mem_ctx, z->dn);
+       ldb_dn_add_child_fmt(dn, "DC=%*.*s", (int)host_part_len, (int)host_part_len, name);
+       *_dn = dn;
+       return WERR_OK;
+}
+
+static int dns_common_sort_zones(struct ldb_message **m1, struct ldb_message **m2)
+{
+       const char *n1, *n2;
+       size_t l1, l2;
+
+       n1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
+       n2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
+
+       l1 = strlen(n1);
+       l2 = strlen(n2);
+
+       /* If the string lengths are not equal just sort by length */
+       if (l1 != l2) {
+               /* If m1 is the larger zone name, return it first */
+               return l2 - l1;
+       }
+
+       /*TODO: We need to compare DNs here, we want the DomainDNSZones first */
+       return 0;
+}
+
+NTSTATUS dns_common_zones(struct ldb_context *samdb,
+                         TALLOC_CTX *mem_ctx,
+                         struct dns_server_zone **zones_ret)
+{
+       int ret;
+       static const char * const attrs[] = { "name", NULL};
+       struct ldb_result *res;
+       int i;
+       struct dns_server_zone *new_list = NULL;
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       // TODO: this search does not work against windows
+       ret = dsdb_search(samdb, frame, &res, NULL, LDB_SCOPE_SUBTREE,
+                         attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS, "(objectClass=dnsZone)");
+       if (ret != LDB_SUCCESS) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       TYPESAFE_QSORT(res->msgs, res->count, dns_common_sort_zones);
+
+       for (i=0; i < res->count; i++) {
+               struct dns_server_zone *z;
+
+               z = talloc_zero(mem_ctx, struct dns_server_zone);
+               if (z == NULL) {
+                       TALLOC_FREE(frame);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               z->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
+               talloc_steal(z, z->name);
+               z->dn = talloc_move(z, &res->msgs[i]->dn);
+               /*
+                * Ignore the RootDNSServers zone and zones that we don't support yet
+                * RootDNSServers should never be returned (Windows DNS server don't)
+                * ..TrustAnchors should never be returned as is, (Windows returns
+                * TrustAnchors) and for the moment we don't support DNSSEC so we'd better
+                * not return this zone.
+                */
+               if ((strcmp(z->name, "RootDNSServers") == 0) ||
+                   (strcmp(z->name, "..TrustAnchors") == 0))
+               {
+                       DEBUG(10, ("Ignoring zone %s\n", z->name));
+                       talloc_free(z);
+                       continue;
+               }
+               DLIST_ADD_END(new_list, z, NULL);
+       }
+
+       *zones_ret = new_list;
+       TALLOC_FREE(frame);
+       return NT_STATUS_OK;
+}
index becd243f6a9e244528f4b32ed805257baddb1197..ad91f617be7bb268901e07e011d2eb490ca6b8c3 100644 (file)
@@ -26,6 +26,14 @@ uint8_t werr_to_dns_err(WERROR werr);
 #define DNS_ERR(err_str) WERR_DNS_ERROR_RCODE_##err_str
 
 struct ldb_message_element;
+struct ldb_context;
+struct dnsp_DnssrvRpcRecord;
+
+struct dns_server_zone {
+       struct dns_server_zone *prev, *next;
+       const char *name;
+       struct ldb_dn *dn;
+};
 
 WERROR dns_common_extract(const struct ldb_message_element *el,
                          TALLOC_CTX *mem_ctx,
@@ -46,5 +54,13 @@ WERROR dns_common_replace(struct ldb_context *samdb,
                          uint32_t serial,
                          struct dnsp_DnssrvRpcRecord *records,
                          uint16_t rec_count);
-
+bool dns_name_match(const char *zone, const char *name, size_t *host_part_len);
+WERROR dns_common_name2dn(struct ldb_context *samdb,
+                         struct dns_server_zone *zones,
+                         TALLOC_CTX *mem_ctx,
+                         const char *name,
+                         struct ldb_dn **_dn);
+NTSTATUS dns_common_zones(struct ldb_context *samdb,
+                         TALLOC_CTX *mem_ctx,
+                         struct dns_server_zone **zones_ret);
 #endif /* __DNSSERVER_COMMON_H__ */