From 88096745d1ef1798854e0c8319b5ae015f045fe3 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 1 May 2019 09:24:24 +0300 Subject: [PATCH] Move recognition of a templated attribute to ldap_attribute_to_rdatatype When substitution of a templated entry attribute fails, we need to fall back to a static definition of the attribute from the same entry. This means, however, that ldap_attribute_to_rdatatype() will attempt to parse an attribute value anyway and will be confused by the templating prefix, thus reporting in named's logs: unsupported operation: object class in resource record template DN 'idnsname=$NAME,idnsname=$ZONE.,cn=dns,$BASEDN' changed: rndc reload might be necessary Move recognition of a template attribute name to ldap_attribute_to_rdatatype() so that a proper attribute class is correctly derived and ignore templated attribute in the fallback code if case that template expansion is failed. Resolves: rhbz#1705072 --- src/ldap_convert.c | 33 +++++++++++++++++++++++++-------- src/ldap_convert.h | 2 ++ src/ldap_helper.c | 21 ++++++++++++++------- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/ldap_convert.c b/src/ldap_convert.c index 002a679..6e24c81 100644 --- a/src/ldap_convert.c +++ b/src/ldap_convert.c @@ -372,23 +372,40 @@ ldap_attribute_to_rdatatype(const char *ldap_attribute, dns_rdatatype_t *rdtype) { isc_result_t result; unsigned len; + const char *attribute = NULL; isc_consttextregion_t region; len = strlen(ldap_attribute); if (len <= LDAP_RDATATYPE_SUFFIX_LEN) return ISC_R_UNEXPECTEDEND; + + /* Before looking up rdtype, we need to see if rdtype is + * an LDAP subtype (type;subtype) and if so, strip one of + * the known prefixes. We also need to remove 'record' suffix + * if it exists. The resulting rdtype text name should have no + * 'extra' details: A, AAAA, CNAME, etc. */ + attribute = ldap_attribute; + + /* Does attribute name start with with TEMPLATE_PREFIX? */ + if (strncasecmp(LDAP_RDATATYPE_TEMPLATE_PREFIX, + ldap_attribute, + LDAP_RDATATYPE_TEMPLATE_PREFIX_LEN) == 0) { + attribute = ldap_attribute + LDAP_RDATATYPE_TEMPLATE_PREFIX_LEN; + len -= LDAP_RDATATYPE_TEMPLATE_PREFIX_LEN; + /* Does attribute name start with with UNKNOWN_PREFIX? */ + } else if (strncasecmp(LDAP_RDATATYPE_UNKNOWN_PREFIX, + ldap_attribute, + LDAP_RDATATYPE_UNKNOWN_PREFIX_LEN) == 0) { + attribute = ldap_attribute + LDAP_RDATATYPE_UNKNOWN_PREFIX_LEN; + len -= LDAP_RDATATYPE_UNKNOWN_PREFIX_LEN; + } + /* Does attribute name end with RECORD_SUFFIX? */ - if (strcasecmp(ldap_attribute + len - LDAP_RDATATYPE_SUFFIX_LEN, + if (strcasecmp(attribute + len - LDAP_RDATATYPE_SUFFIX_LEN, LDAP_RDATATYPE_SUFFIX) == 0) { - region.base = ldap_attribute; + region.base = attribute; region.length = len - LDAP_RDATATYPE_SUFFIX_LEN; - /* Does attribute name start with with UNKNOWN_PREFIX? */ - } else if (strncasecmp(ldap_attribute, - LDAP_RDATATYPE_UNKNOWN_PREFIX, - LDAP_RDATATYPE_UNKNOWN_PREFIX_LEN) == 0) { - region.base = ldap_attribute + LDAP_RDATATYPE_UNKNOWN_PREFIX_LEN; - region.length = len - LDAP_RDATATYPE_UNKNOWN_PREFIX_LEN; } else return ISC_R_UNEXPECTED; diff --git a/src/ldap_convert.h b/src/ldap_convert.h index 47ac947..fcd575b 100644 --- a/src/ldap_convert.h +++ b/src/ldap_convert.h @@ -17,6 +17,8 @@ #define LDAP_RDATATYPE_SUFFIX_LEN (sizeof(LDAP_RDATATYPE_SUFFIX) - 1) #define LDAP_RDATATYPE_UNKNOWN_PREFIX "UnknownRecord;" #define LDAP_RDATATYPE_UNKNOWN_PREFIX_LEN (sizeof(LDAP_RDATATYPE_UNKNOWN_PREFIX) - 1) +#define LDAP_RDATATYPE_TEMPLATE_PREFIX "idnsTemplateAttribute;" +#define LDAP_RDATATYPE_TEMPLATE_PREFIX_LEN (sizeof(LDAP_RDATATYPE_TEMPLATE_PREFIX) - 1) /* * Convert LDAP DN 'dn', to dns_name_t 'target'. 'target' needs to be diff --git a/src/ldap_helper.c b/src/ldap_helper.c index 8b486ae..7f70ee3 100644 --- a/src/ldap_helper.c +++ b/src/ldap_helper.c @@ -2396,7 +2396,7 @@ ldap_substitute_rr_template(isc_mem_t *mctx, const settings_set_t * set, result = setting_find(setting_name, set, isc_boolean_true, isc_boolean_true, &setting); if (result != ISC_R_SUCCESS) { - log_debug(3, "setting '%s' is not defined so it " + log_debug(5, "setting '%s' is not defined so it " "cannot be substituted into template '%s'", setting_name, str_buf(orig_val)); CLEANUP_WITH(ISC_R_IGNORE); @@ -2459,23 +2459,22 @@ ldap_parse_rrentry_template(isc_mem_t *mctx, ldap_entry_t *entry, dns_rdatatype_t rdtype; dns_rdatalist_t *rdlist = NULL; isc_boolean_t did_something = ISC_FALSE; - static const char prefix[] = "idnsTemplateAttribute;"; - static const char prefix_len = sizeof(prefix) - 1; CHECK(str_new(mctx, &orig_val)); rdclass = ldap_entry_getrdclass(entry); ttl = ldap_entry_getttl(entry, settings); while ((attr = ldap_entry_nextattr(entry)) != NULL) { - if (strncasecmp(prefix, attr->name, prefix_len) != 0) + if (strncasecmp(LDAP_RDATATYPE_TEMPLATE_PREFIX, + attr->name, + LDAP_RDATATYPE_TEMPLATE_PREFIX_LEN) != 0) continue; - result = ldap_attribute_to_rdatatype(attr->name + prefix_len, - &rdtype); + result = ldap_attribute_to_rdatatype(attr->name, &rdtype); if (result != ISC_R_SUCCESS) { log_bug("%s: substitution into '%s' is not supported", ldap_entry_logname(entry), - attr->name + prefix_len); + attr->name + LDAP_RDATATYPE_TEMPLATE_PREFIX_LEN); continue; } @@ -2559,6 +2558,14 @@ ldap_parse_rrentry(isc_mem_t *mctx, ldap_entry_t *entry, dns_name_t *origin, for (result = ldap_entry_firstrdtype(entry, &attr, &rdtype); result == ISC_R_SUCCESS; result = ldap_entry_nextrdtype(entry, &attr, &rdtype)) { + /* If we reached this point and found a template attribute, + * skip it because it was not translated above due to missing + * defaults or some other errors. */ + if (((entry->class & LDAP_ENTRYCLASS_TEMPLATE) != 0) && + strncasecmp(LDAP_RDATATYPE_TEMPLATE_PREFIX, + attr->name, + LDAP_RDATATYPE_TEMPLATE_PREFIX_LEN) == 0) + continue; CHECK(findrdatatype_or_create(mctx, rdatalist, rdclass, rdtype, ttl, &rdlist)); -- 2.21.0