summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Nagy <mnagy@redhat.com>2009-04-06 11:06:18 +0200
committerMartin Nagy <mnagy@redhat.com>2009-04-24 14:53:49 +0200
commit0a46531f5615aa3bea269c5787babffea01358b5 (patch)
treef848722ee19f9c727d7400df4d34ab457f34583c /src
parent7f7a0c023fa83fcb7443bdee523464d4673de40c (diff)
downloadldap_driver-0a46531f5615aa3bea269c5787babffea01358b5.tar.gz
ldap_driver-0a46531f5615aa3bea269c5787babffea01358b5.tar.xz
ldap_driver-0a46531f5615aa3bea269c5787babffea01358b5.zip
Add update ACL capabilities.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am28
-rw-r--r--src/acl.c386
-rw-r--r--src/acl.h26
-rw-r--r--src/ldap_helper.c93
4 files changed, 505 insertions, 28 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ffa5499..f5cf9da 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,11 +3,31 @@ lib_LTLIBRARIES = libdnsldap.la
LIBMAJOR = 1
LIBMINOR = 0
-HDRS = cache.h ldap_convert.h ldap_helper.h log.h rdlist.h semaphore.h \
- settings.h str.h util.h zone_manager.h
+HDRS = \
+ acl.h \
+ cache.h \
+ ldap_convert.h \
+ ldap_helper.h \
+ log.h \
+ rdlist.h \
+ semaphore.h \
+ settings.h \
+ str.h \
+ util.h \
+ zone_manager.h
-libdnsldap_la_SOURCES = $(HDRS) cache.c ldap_convert.c ldap_driver.c \
- ldap_helper.c log.c rdlist.c semaphore.c settings.c str.c \
+libdnsldap_la_SOURCES = \
+ $(HDRS) \
+ acl.c \
+ cache.c \
+ ldap_convert.c \
+ ldap_driver.c \
+ ldap_helper.c \
+ log.c \
+ rdlist.c \
+ semaphore.c \
+ settings.c \
+ str.c \
zone_manager.c
libdnsldap_la_CFLAGS = -Wall -Wextra -pedantic -std=c99
diff --git a/src/acl.c b/src/acl.c
new file mode 100644
index 0000000..64f4060
--- /dev/null
+++ b/src/acl.c
@@ -0,0 +1,386 @@
+/* Authors: Martin Nagy <mnagy@redhat.com>
+ *
+ * Copyright (C) 2009 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * 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 the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * For portions of the code (see bellow):
+ *
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
+#include <isccfg/namedconf.h>
+#include <isccfg/grammar.h>
+
+#include <isc/buffer.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdatatype.h>
+#include <dns/ssu.h>
+#include <dns/zone.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include "str.h"
+#include "util.h"
+#include "log.h"
+
+static cfg_type_t *update_policy;
+
+static cfg_type_t *
+get_type_from_tuplefield(const cfg_type_t *cfg_type, const char *name)
+{
+ cfg_type_t *ret = NULL;
+ const cfg_tuplefielddef_t *field;
+
+ REQUIRE(cfg_type != NULL && cfg_type->of != NULL);
+ REQUIRE(name != NULL);
+
+ field = (cfg_tuplefielddef_t *)cfg_type->of;
+ for (int i = 0; field[i].name != NULL; i++) {
+ if (!strcmp(field[i].name, name)) {
+ ret = field[i].type;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static cfg_type_t *
+get_type_from_clause(const cfg_clausedef_t *clause, const char *name)
+{
+ cfg_type_t *ret = NULL;
+
+ REQUIRE(clause != NULL);
+ REQUIRE(name != NULL);
+
+ for (int i = 0; clause[i].name != NULL; i++) {
+ if (!strcmp(clause[i].name, name)) {
+ ret = clause[i].type;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static cfg_type_t *
+get_type_from_clause_array(const cfg_type_t *cfg_type, const char *name)
+{
+ cfg_type_t *ret = NULL;
+ const cfg_clausedef_t **clauses;
+
+ REQUIRE(cfg_type != NULL && cfg_type->of != NULL);
+ REQUIRE(name != NULL);
+
+ clauses = (const cfg_clausedef_t **)cfg_type->of;
+ for (int i = 0; clauses[i] != NULL; i++) {
+ ret = get_type_from_clause(clauses[i], name);
+ if (ret != NULL)
+ break;
+ }
+
+ return ret;
+}
+
+static cfg_type_t *
+get_update_policy_type(void)
+{
+ cfg_type_t *type;
+
+ type = &cfg_type_namedconf;
+ type = get_type_from_clause_array(type, "zone");
+ type = get_type_from_tuplefield(type, "options");
+ type = get_type_from_clause_array(type, "update-policy");
+ //type = (cfg_type_t *)type->of;
+
+ return type;
+}
+
+static isc_result_t
+parse(cfg_parser_t *parser, const char *string, cfg_obj_t **objp)
+{
+ isc_result_t result;
+ isc_buffer_t buffer;
+ size_t string_len;
+ cfg_obj_t *ret = NULL;
+
+ REQUIRE(parser != NULL);
+ REQUIRE(string != NULL);
+ REQUIRE(objp != NULL && *objp == NULL);
+
+ /* FIXME: Only do this once. */
+ update_policy = get_update_policy_type();
+
+ string_len = strlen(string);
+ isc_buffer_init(&buffer, string, string_len);
+ isc_buffer_add(&buffer, string_len);
+
+ result = cfg_parse_buffer(parser, &buffer, update_policy, &ret);
+
+ if (result == ISC_R_SUCCESS)
+ *objp = ret;
+
+ return result;
+}
+
+/*
+ * The rest of the code in this file is either copied from, or based on code
+ * from ISC BIND, file bin/named/config.c.
+ */
+
+#define MATCH(string_rep, return_val) \
+ do { \
+ if (!strcasecmp(str, string_rep)) { \
+ return return_val; \
+ } \
+ } while (0)
+
+static isc_boolean_t
+get_mode(const cfg_obj_t *obj)
+{
+ const char *str;
+
+ obj = cfg_tuple_get(obj, "mode");
+ str = cfg_obj_asstring(obj);
+
+ MATCH("grant", ISC_TRUE);
+ MATCH("deny", ISC_FALSE);
+
+ INSIST(0);
+ /* Not reached. */
+ return ISC_FALSE;
+}
+
+static unsigned int
+get_match_type(const cfg_obj_t *obj)
+{
+ const char *str;
+
+ obj = cfg_tuple_get(obj, "matchtype");
+ str = cfg_obj_asstring(obj);
+
+ MATCH("name", DNS_SSUMATCHTYPE_NAME);
+ MATCH("subdomain", DNS_SSUMATCHTYPE_SUBDOMAIN);
+ MATCH("wildcard", DNS_SSUMATCHTYPE_WILDCARD);
+ MATCH("self", DNS_SSUMATCHTYPE_SELF);
+ MATCH("selfsub", DNS_SSUMATCHTYPE_SELFSUB);
+ MATCH("selfwild", DNS_SSUMATCHTYPE_SELFWILD);
+ MATCH("ms-self", DNS_SSUMATCHTYPE_SELFMS);
+ MATCH("krb5-self", DNS_SSUMATCHTYPE_SELFKRB5);
+ MATCH("ms-subdomain", DNS_SSUMATCHTYPE_SUBDOMAINMS);
+ MATCH("krb5-subdomain", DNS_SSUMATCHTYPE_SUBDOMAINKRB5);
+ MATCH("tcp-self", DNS_SSUMATCHTYPE_TCPSELF);
+ MATCH("6to4-self", DNS_SSUMATCHTYPE_6TO4SELF);
+
+ INSIST(0);
+ /* Not reached. */
+ return DNS_SSUMATCHTYPE_NAME;
+}
+
+static isc_result_t
+get_fixed_name(const cfg_obj_t *obj, const char *name, dns_fixedname_t *fname)
+{
+ isc_result_t result;
+ isc_buffer_t buf;
+ const char *str;
+
+ REQUIRE(fname != NULL);
+
+ obj = cfg_tuple_get(obj, name);
+ str = cfg_obj_asstring(obj);
+
+ isc_buffer_init(&buf, str, strlen(str));
+ isc_buffer_add(&buf, strlen(str));
+
+ dns_fixedname_init(fname);
+
+ result = dns_name_fromtext(dns_fixedname_name(fname), &buf,
+ dns_rootname, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ log_error("'%s' is not a valid name", str);
+
+ return result;
+}
+
+static unsigned int
+count_list_elements(const cfg_obj_t *list)
+{
+ const cfg_listelt_t *el;
+ unsigned int ret = 0;
+
+ for (el = cfg_list_first(list); el != NULL; el = cfg_list_next(el))
+ ret++;
+
+ return ret;
+}
+
+static isc_result_t
+get_types(isc_mem_t *mctx, const cfg_obj_t *obj, dns_rdatatype_t **typesp,
+ unsigned int *np)
+{
+ isc_result_t result;
+ unsigned int i;
+ unsigned int n = 0;
+ const cfg_listelt_t *el;
+ dns_rdatatype_t *types = NULL;
+
+ REQUIRE(obj != NULL);
+ REQUIRE(typesp != NULL && *typesp == NULL);
+ REQUIRE(np != NULL);
+
+ obj = cfg_tuple_get(obj, "types");
+
+ n = count_list_elements(obj);
+ if (n > 0)
+ CHECKED_MEM_GET(mctx, types, n * sizeof(dns_rdatatype_t));
+
+ i = 0;
+ for (el = cfg_list_first(obj); el != NULL; el = cfg_list_next(el)) {
+ const cfg_obj_t *typeobj;
+ const char *str;
+ isc_textregion_t r;
+
+ INSIST(i < n);
+
+ typeobj = cfg_listelt_value(el);
+ str = cfg_obj_asstring(typeobj);
+ DE_CONST(str, r.base);
+ r.length = strlen(str);
+
+ result = dns_rdatatype_fromtext(&types[i++], &r);
+ if (result != ISC_R_SUCCESS) {
+ log_error("'%s' is not a valid type", str);
+ goto cleanup;
+ }
+ }
+ INSIST(i == n);
+
+ *typesp = types;
+ *np = n;
+ return result;
+
+cleanup:
+ SAFE_MEM_PUT(mctx, types, n * sizeof(dns_rdatatype_t));
+
+ return result;
+}
+
+isc_result_t
+acl_configure_zone_ssutable(const char *policy_str, dns_zone_t *zone)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ cfg_parser_t *parser = NULL;
+ const cfg_listelt_t *el;
+ cfg_obj_t *policy = NULL;
+ dns_ssutable_t *table = NULL;
+ ld_string_t *new_policy_str = NULL;
+ isc_mem_t *mctx;
+
+ REQUIRE(zone != NULL);
+
+ log_func_enter();
+
+ mctx = dns_zone_getmctx(zone);
+
+ if (policy_str == NULL)
+ goto cleanup;
+
+ CHECK(str_new(mctx, &new_policy_str));
+ CHECK(str_sprintf(new_policy_str, "{ %s }", policy_str));
+
+ CHECK(cfg_parser_create(mctx, dns_lctx, &parser));
+ result = parse(parser, str_buf(new_policy_str), &policy);
+
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "failed to parse policy string");
+ goto cleanup;
+ }
+
+ CHECK(dns_ssutable_create(mctx, &table));
+
+ for (el = cfg_list_first(policy); el != NULL; el = cfg_list_next(el)) {
+ const cfg_obj_t *stmt;
+ isc_boolean_t grant;
+ unsigned int match_type;
+ dns_fixedname_t fname, fident;
+ dns_rdatatype_t *types;
+ unsigned int n;
+
+ types = NULL;
+
+ stmt = cfg_listelt_value(el);
+ grant = get_mode(stmt);
+ match_type = get_match_type(stmt);
+
+ CHECK(get_fixed_name(stmt, "identity", &fident));
+ CHECK(get_fixed_name(stmt, "name", &fname));
+ CHECK(get_types(mctx, stmt, &types, &n));
+
+ result = dns_ssutable_addrule(table, grant,
+ dns_fixedname_name(&fident),
+ match_type,
+ dns_fixedname_name(&fname),
+ n, types);
+
+ SAFE_MEM_PUT(mctx, types, n * sizeof(dns_rdatatype_t));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ }
+
+ cleanup:
+ if (result == ISC_R_SUCCESS)
+ dns_zone_setssutable(zone, table);
+
+ str_destroy(&new_policy_str);
+ if (policy != NULL)
+ cfg_obj_destroy(parser, &policy);
+ if (parser != NULL)
+ cfg_parser_destroy(&parser);
+ if (table != NULL)
+ dns_ssutable_detach(&table);
+
+ log_func_exit_result(result);
+
+ return result;
+}
diff --git a/src/acl.h b/src/acl.h
new file mode 100644
index 0000000..3b3e8ea
--- /dev/null
+++ b/src/acl.h
@@ -0,0 +1,26 @@
+/* Authors: Martin Nagy <mnagy@redhat.com>
+ *
+ * Copyright (C) 2009 Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * 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 the Free Software Foundation; version 2 only
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LD_ACL_H_
+#define _LD_ACL_H_
+
+isc_result_t
+acl_configure_zone_ssutable(const char *policy_str, dns_zone_t *zone);
+
+#endif /* !_LD_ACL_H_ */
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index 60b2675..99a8fab 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -43,6 +43,7 @@
#include <string.h>
#include <strings.h>
+#include "acl.h"
#include "ldap_convert.h"
#include "ldap_helper.h"
#include "log.h"
@@ -144,6 +145,7 @@ struct ldap_instance {
struct ldap_entry {
LDAPMessage *entry;
+ char *dn;
ldap_attribute_t *last_attr;
ldap_attribute_list_t attributes;
LINK(ldap_entry_t) link;
@@ -186,7 +188,8 @@ static isc_result_t new_ldap_instance(ldap_db_t *ldap_db,
ldap_instance_t **ldap_instp);
static void destroy_ldap_instance(ldap_instance_t **ldap_instp);
static isc_result_t add_or_modify_zone(ldap_db_t *ldap_db, const char *dn,
- const char *db_name, dns_zonemgr_t *zmgr);
+ const char *db_name, const char *update_str,
+ dns_zonemgr_t *zmgr);
static isc_result_t findrdatatype_or_create(isc_mem_t *mctx,
ldapdb_rdatalist_t *rdatalist, ldap_entry_t *entry,
@@ -222,9 +225,12 @@ static void free_query_cache(ldap_instance_t *inst);
static void free_ldap_attributes(isc_mem_t *mctx, ldap_entry_t *entry);
static void free_ldap_values(isc_mem_t *mctx, ldap_attribute_t *attr);
+static const char * get_dn(ldap_instance_t *ldap_inst, ldap_entry_t *entry);
+#if 0
static const LDAPMessage *next_entry(ldap_instance_t *inst);
static const char *get_dn(ldap_instance_t *inst);
+#endif
static ldap_instance_t * get_connection(ldap_db_t *ldap_db);
static void put_connection(ldap_instance_t *ldap_inst);
@@ -459,8 +465,9 @@ refresh_zones_from_ldap(ldap_db_t *ldap_db, const char *name,
{
isc_result_t result = ISC_R_SUCCESS;
ldap_instance_t *ldap_inst;
+ ldap_entry_t *entry;
char *attrs[] = {
- "idnsName", NULL
+ "idnsName", "idnsUpdatePolicy", NULL
};
REQUIRE(ldap_db != NULL);
@@ -471,10 +478,30 @@ refresh_zones_from_ldap(ldap_db_t *ldap_db, const char *name,
ldap_inst = get_connection(ldap_db);
ldap_query(ldap_inst, str_buf(ldap_db->base), LDAP_SCOPE_SUBTREE,
- attrs, 0, "(objectClass=idnsZone)");
+ attrs, 0, "(&(objectClass=idnsZone)(idnsZoneActive=True))");
+ CHECK(cache_query_results(ldap_inst));
- while (next_entry(ldap_inst))
- CHECK(add_or_modify_zone(ldap_db, get_dn(ldap_inst), name, zmgr));
+ for (entry = HEAD(ldap_inst->ldap_entries);
+ entry != NULL;
+ entry = NEXT(entry, link)) {
+ const char *dn;
+ const char *update_str = NULL;
+ ldap_value_list_t values;
+
+ dn = get_dn(ldap_inst, entry);
+
+ /* Look if there's an update policy. */
+ result = get_values(entry, "idnsUpdatePolicy", &values);
+ if (result == ISC_R_SUCCESS)
+ update_str = HEAD(values)->value;
+
+ result = add_or_modify_zone(ldap_db, dn, name, update_str,
+ zmgr);
+
+ /* TODO: move this to the add_or_modify_zone() */
+ if (result != ISC_R_SUCCESS)
+ log_error("failed to add/modify zone %s", dn);
+ }
cleanup:
put_connection(ldap_inst);
@@ -485,6 +512,20 @@ cleanup:
}
static const char *
+get_dn(ldap_instance_t *ldap_inst, ldap_entry_t *entry)
+{
+ if (entry->dn) {
+ ldap_memfree(entry->dn);
+ entry->dn = NULL;
+ }
+ if (ldap_inst->handle)
+ entry->dn = ldap_get_dn(ldap_inst->handle, entry->entry);
+
+ return entry->dn;
+}
+
+#if 0
+static const char *
get_dn(ldap_instance_t *inst)
{
if (inst->dn) {
@@ -498,7 +539,7 @@ get_dn(ldap_instance_t *inst)
return inst->dn;
}
-
+#endif
void
string_deleter(void *arg1, void *arg2)
@@ -568,14 +609,10 @@ add_zone_dn(ldap_db_t *ldap_db, dns_name_t *name, const char *dn)
/* Now add it. */
CHECK(dns_rbt_addname(rbt, name, (void *)new_dn));
- RWUNLOCK(&ldap_db->zone_rwlock, isc_rwlocktype_write);
-
- return ISC_R_SUCCESS;
-
cleanup:
RWUNLOCK(&ldap_db->zone_rwlock, isc_rwlocktype_write);
- if (new_dn)
+ if (result != ISC_R_SUCCESS && new_dn != NULL)
isc_mem_free(ldap_db->mctx, new_dn);
return result;
@@ -584,12 +621,11 @@ cleanup:
/* FIXME: Better error handling. */
static isc_result_t
add_or_modify_zone(ldap_db_t *ldap_db, const char *dn, const char *db_name,
- dns_zonemgr_t *zmgr)
+ const char *update_str, dns_zonemgr_t *zmgr)
{
isc_result_t result;
dns_zone_t *zone;
dns_name_t name;
- dns_acl_t *updateacl = NULL;
const char *argv[2];
REQUIRE(ldap_db != NULL);
@@ -613,12 +649,6 @@ add_or_modify_zone(ldap_db_t *ldap_db, const char *dn, const char *db_name,
dns_zone_setclass(zone, dns_rdataclass_in);
dns_zone_settype(zone, dns_zone_master);
CHECK(dns_zone_setdbtype(zone, 2, argv));
-
- /* XXX Temporary set update ACLs to any */
- CHECK(dns_acl_any(ldap_db->mctx, &updateacl));
- dns_zone_setupdateacl(zone, updateacl);
- dns_acl_detach(&updateacl);
-
CHECK(dns_zonemgr_managezone(zmgr, zone));
CHECK(dns_view_addzone(ldap_db->view, zone));
CHECK(add_zone_dn(ldap_db, &name, dn));
@@ -626,6 +656,9 @@ add_or_modify_zone(ldap_db_t *ldap_db, const char *dn, const char *db_name,
goto cleanup;
}
+ /* Set simple update table. */
+ CHECK(acl_configure_zone_ssutable(update_str, zone));
+
/*
* ACLs:
* dns_zone_setqueryacl()
@@ -1322,6 +1355,8 @@ free_query_cache(ldap_instance_t *inst)
next = NEXT(entry, link);
UNLINK(inst->ldap_entries, entry, link);
free_ldap_attributes(inst->database->mctx, entry);
+ if (entry->dn != NULL)
+ ldap_memfree(entry->dn);
isc_mem_put(inst->database->mctx, entry, sizeof(*entry));
entry = next;
}
@@ -1360,6 +1395,7 @@ free_ldap_values(isc_mem_t *mctx, ldap_attribute_t *attr)
}
}
+#if 0
/* FIXME: this function is obsolete, remove. */
static const LDAPMessage *
next_entry(ldap_instance_t *inst)
@@ -1378,6 +1414,7 @@ next_entry(ldap_instance_t *inst)
return inst->entry;
}
+#endif
#if 0
/* FIXME: Not tested. */
@@ -1536,11 +1573,16 @@ ldap_modify_do(ldap_instance_t *ldap_inst, const char *dn, LDAPMod **mods)
REQUIRE(dn != NULL);
REQUIRE(mods != NULL);
- log_debug(2, "writing to to '%s'", dn);
+ log_debug(2, "writing to '%s'", dn);
ret = ldap_modify_ext_s(ldap_inst->handle, dn, mods, NULL, NULL);
if (ret != LDAP_SUCCESS) {
- log_error("error writing to ldap: %s", ldap_err2string(ret));
+ int err_code;
+
+ ldap_get_option(ldap_inst->handle, LDAP_OPT_RESULT_CODE,
+ &err_code);
+ log_error("error writing to ldap: %s",
+ ldap_err2string(err_code));
return ISC_R_FAILURE;
}
@@ -1678,11 +1720,14 @@ modify_ldap_common(dns_name_t *owner, ldap_db_t *ldap_db,
{
isc_result_t result;
isc_mem_t *mctx;
- ldap_instance_t *ldap_inst;
+ ldap_instance_t *ldap_inst = NULL;
ld_string_t *owner_dn = NULL;
- LDAPMod *change[2];
+ LDAPMod *change[2] = { NULL, NULL };
- change[0] = change[1] = NULL;
+ if (rdlist->type == dns_rdatatype_soa) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
mctx = ldap_db->mctx;
ldap_inst = get_connection(ldap_db);