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>
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)
{
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);
#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;
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);
#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)
{
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,
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
#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
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;
+}
#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,
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__ */