summaryrefslogtreecommitdiffstats
path: root/src/ldap_convert.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ldap_convert.c')
-rw-r--r--src/ldap_convert.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/src/ldap_convert.c b/src/ldap_convert.c
new file mode 100644
index 0000000..24da32f
--- /dev/null
+++ b/src/ldap_convert.c
@@ -0,0 +1,278 @@
+/* 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
+ */
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/name.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+#define LDAP_DEPRECATED 1
+#include <ldap.h>
+
+#include <errno.h>
+#include <strings.h>
+
+#include "str.h"
+#include "ldap_convert.h"
+#include "ldap_helper.h"
+#include "log.h"
+#include "util.h"
+
+/*
+ * Consistency must be preserved in these tables.
+ * ldap_dns_records[i] must always corespond to dns_records[i]
+ */
+const char *ldap_dns_records[] = {
+ "ARecord", "AAAARecord", "A6Record", "NSRecord",
+ "CNAMERecord", "PTRRecord", "SRVRecord", "TXTRecord", "MXRecord",
+ "MDRecord", "HINFORecord", "MINFORecord", "AFSDBRecord", "SIGRecord",
+ "KEYRecord", "LOCRecord", "NXTRecord", "NAPTRRecord", "KXRecord",
+ "CERTRecord", "DNAMERecord", "DSRecord", "SSHFPRecord",
+ "RRSIGRecord", "NSECRecord", NULL
+};
+
+const char *dns_records[] = {
+ "A", "AAAA", "A6", "NS",
+ "CNAME", "PTR", "SRV", "TXT", "MX",
+ "MD", "HINFO", "MINFO", "AFSDB", "SIG",
+ "KEY", "LOC", "NXT", "NAPTR", "KX",
+ "CERT", "DNAME", "DS", "SSHFP",
+ "RRSIG", "NSEC", NULL
+};
+
+static isc_result_t dn_to_text(const char *dn, ld_string_t *target);
+static isc_result_t explode_dn(const char *dn, char ***explodedp, int notypes);
+static isc_result_t explode_rdn(const char *rdn, char ***explodedp,
+ int notypes);
+
+
+isc_result_t
+dn_to_dnsname(isc_mem_t *mctx, const char *dn, dns_name_t *target)
+{
+ isc_result_t result;
+ DECLARE_BUFFERED_NAME(name);
+ ld_string_t *str = NULL;
+ isc_buffer_t buffer;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(dn != NULL);
+
+ INIT_BUFFERED_NAME(name);
+ CHECK(str_new(mctx, &str));
+
+ CHECK(dn_to_text(dn, str));
+ str_to_isc_buffer(str, &buffer);
+ CHECK(dns_name_fromtext(&name, &buffer, dns_rootname, 0, NULL));
+
+cleanup:
+ if (result != ISC_R_FAILURE)
+ result = dns_name_dupwithoffsets(&name, mctx, target);
+
+ str_destroy(&str);
+
+ return result;
+}
+
+/*
+ * Convert LDAP dn to DNS name.
+ *
+ * Example:
+ * dn = "idnsName=foo, idnsName=bar, idnsName=example.org, cn=dns,"
+ * "dc=example, dc=org"
+ *
+ * The resulting string will be "foo.bar.example.org."
+ */
+static isc_result_t
+dn_to_text(const char *dn, ld_string_t *target)
+{
+ isc_result_t result;
+ char **exploded_dn = NULL;
+ char **exploded_rdn = NULL;
+
+ REQUIRE(dn != NULL);
+ REQUIRE(target != NULL);
+
+ result = ISC_R_SUCCESS;
+
+ CHECK(explode_dn(dn, &exploded_dn, 0));
+ str_clear(target);
+ for (unsigned int i = 0; exploded_dn[i] != NULL; i++) {
+ if (strncasecmp(exploded_dn[i], "idnsName", 8) != 0)
+ break;
+ CHECK(explode_rdn(exploded_dn[i], &exploded_rdn, 1));
+ CHECK(str_cat_char(target, exploded_rdn[0]));
+ CHECK(str_cat_char(target, "."));
+
+ ldap_value_free(exploded_rdn);
+ exploded_rdn = NULL;
+ }
+
+ if (str_len(target) == 0)
+ CHECK(str_init_char(target, "."));
+
+cleanup:
+ if (exploded_dn != NULL)
+ ldap_value_free(exploded_dn);
+ if (exploded_rdn != NULL)
+ ldap_value_free(exploded_rdn);
+
+ log_error("converted: %s", str_buf(target));
+ return result;
+}
+
+static isc_result_t
+explode_dn(const char *dn, char ***explodedp, int notypes)
+{
+ char **exploded;
+
+ REQUIRE(dn != NULL);
+ REQUIRE(explodedp != NULL && *explodedp == NULL);
+
+ exploded = ldap_explode_dn(dn, notypes);
+ if (exploded == NULL) {
+ if (errno == ENOMEM) {
+ return ISC_R_NOMEMORY;
+ } else {
+ log_error("ldap_explode_dn(\"%s\") failed, "
+ "error code %d", dn, errno);
+ return ISC_R_FAILURE;
+ }
+ }
+
+ *explodedp = exploded;
+
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+explode_rdn(const char *rdn, char ***explodedp, int notypes)
+{
+ char **exploded;
+
+ REQUIRE(rdn != NULL);
+ REQUIRE(explodedp != NULL && *explodedp == NULL);
+
+ exploded = ldap_explode_rdn(rdn, notypes);
+ if (exploded == NULL) {
+ if (errno == ENOMEM) {
+ return ISC_R_NOMEMORY;
+ } else {
+ log_error("ldap_explode_rdn(\"%s\") failed, "
+ "error code %d", rdn, errno);
+ return ISC_R_FAILURE;
+ }
+ }
+
+ *explodedp = exploded;
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t
+dnsname_to_dn(ldap_db_t *ldap_db, dns_name_t *name, ld_string_t *target)
+{
+ isc_result_t result;
+ int label_count;
+ const char *zone_dn = NULL;
+
+ REQUIRE(ldap_db != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(target != NULL);
+
+ /* Find the DN of the zone we belong to. */
+ {
+ DECLARE_BUFFERED_NAME(zone);
+ int dummy;
+ unsigned int common_labels;
+
+ INIT_BUFFERED_NAME(zone);
+
+ CHECK(get_zone_dn(ldap_db, name, &zone_dn, &zone));
+
+ dns_name_fullcompare(name, &zone, &dummy, &common_labels);
+ label_count = dns_name_countlabels(name) - common_labels;
+ }
+
+ str_clear(target);
+ if (label_count > 0) {
+ DECLARE_BUFFER(buffer, DNS_NAME_MAXTEXT);
+ dns_name_t labels;
+
+ INIT_BUFFER(buffer);
+ dns_name_init(&labels, NULL);
+
+ dns_name_getlabelsequence(name, 0, label_count, &labels);
+ CHECK(dns_name_totext(&labels, ISC_TRUE, &buffer));
+
+ CHECK(str_cat_char(target, "idnsName="));
+ CHECK(str_cat_isc_buffer(target, &buffer));
+ CHECK(str_cat_char(target, ", "));
+ }
+ CHECK(str_cat_char(target, zone_dn));
+
+cleanup:
+ return result;
+}
+
+isc_result_t
+ldap_record_to_rdatatype(const char *ldap_record, dns_rdatatype_t *rdtype)
+{
+ isc_result_t result;
+ unsigned i;
+ isc_consttextregion_t region;
+
+ for (i = 0; ldap_dns_records[i] != NULL; i++) {
+ if (!strcasecmp(ldap_record, ldap_dns_records[i]))
+ break;
+ }
+ if (dns_records[i] == NULL)
+ return ISC_R_NOTFOUND;
+
+ region.base = dns_records[i];
+ region.length = strlen(region.base);
+ result = dns_rdatatype_fromtext(rdtype, (isc_textregion_t *)&region);
+ if (result != ISC_R_SUCCESS) {
+ log_error("dns_rdatatype_fromtext() failed");
+ }
+
+ return result;
+}
+
+isc_result_t
+rdatatype_to_ldap_attribute(dns_rdatatype_t rdtype, const char **target)
+{
+ unsigned i;
+ char rdtype_str[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_rdatatype_format(rdtype, rdtype_str, DNS_RDATATYPE_FORMATSIZE);
+ for (i = 0; dns_records[i] != NULL; i++) {
+ if (!strcmp(rdtype_str, dns_records[i]))
+ break;
+ }
+ if (ldap_dns_records[i] == NULL)
+ return ISC_R_NOTFOUND;
+
+ *target = ldap_dns_records[i];
+
+ return ISC_R_SUCCESS;
+}