mirror of
https://github.com/samba-team/samba.git
synced 2025-02-23 09:57:40 +03:00
dns_server: Put more code in common
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>
This commit is contained in:
parent
2715805f4c
commit
0504065948
@ -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;
|
||||
status = dns_common_zones(dns->samdb, dns, &new_list);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
old_list = dns->zones;
|
||||
dns->zones = new_list;
|
||||
while ((old_zone = DLIST_TAIL(old_list)) != NULL) {
|
||||
DLIST_REMOVE(old_list, old_zone);
|
||||
|
@ -24,15 +24,9 @@
|
||||
|
||||
#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);
|
||||
|
@ -33,47 +33,6 @@
|
||||
#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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user