mirror of
https://github.com/isc-projects/bind9.git
synced 2026-03-03 05:50:39 -05:00
1353. [contrib] sdb/ldap to version 0.9.
This commit is contained in:
parent
4016d47cf3
commit
047210c74e
4 changed files with 352 additions and 238 deletions
2
CHANGES
2
CHANGES
|
|
@ -1,3 +1,5 @@
|
|||
1353. [contrib] sdb/ldap to version 0.9.
|
||||
|
||||
1350. [bug] dns_name_fromtext() failed to handle too many labels
|
||||
gracefully.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
This is the INSTALL file for 0.4. See
|
||||
This is the INSTALL file for 0.9. See
|
||||
http://www.venaas.no/ldap/bind-sdb/ for updates or other information.
|
||||
|
||||
BUILDING
|
||||
|
|
@ -22,7 +22,10 @@ Finally you need to edit bin/named/main.c. Below where it says
|
|||
it says "xxdb_init();" add the line "ldapdb_init();", and finally
|
||||
below where it says "xxdb_clear();", add "ldapdb_clear();".
|
||||
|
||||
Now you should hopefully be able to build it.
|
||||
Now you should hopefully be able to build it. If you get an error
|
||||
message about ldap_memfree() not being defined, you're probably
|
||||
using an LDAP library with the interface defined in RFC 1823. To
|
||||
build, uncomment the #define RFC1823API line near the top of ldapdb.c.
|
||||
|
||||
|
||||
CONFIGURING
|
||||
|
|
@ -50,6 +53,7 @@ zone "venaas.com" {
|
|||
|
||||
When doing lookups BIND will do a sub-tree search below the base in the
|
||||
URL. The number 172800 is the TTL which will be used for all entries that
|
||||
haven't got the dNSTTL attribute.
|
||||
haven't got the dNSTTL attribute. It is also possible to add an filter to
|
||||
the URL, say ldap://host/base???(o=internal)
|
||||
|
||||
Stig Venaas <venaas@uninett.no> 2001-04-12
|
||||
Stig Venaas <venaas@uninett.no> 2002-04-17
|
||||
|
|
|
|||
|
|
@ -1,18 +1,40 @@
|
|||
This is an attempt at an LDAP back-end for BIND 9 using the new simplified
|
||||
database interface "sdb". This is the fifth release (0.5) and is not ready
|
||||
for production use yet. Note that this version (and 0.4) uses a new schema
|
||||
and is not backwards compatible with versions before 0.4. The big changes in
|
||||
0.5 are thread support and improved connection handling. Multiple threads
|
||||
can now access the back-end simultaneously, and rather than having one
|
||||
connection per zone, there is now one connection per thread per LDAP server.
|
||||
This should help people with multiple CPUs and people with a huge number of
|
||||
zones. One final change is support for literal IPv6 addresses in LDAP URLs.
|
||||
At least OpenLDAP 2 has IPv6 support, so if you use OpenLDAP 2 libraries and
|
||||
server, you got all you need.
|
||||
database interface "sdb". This is the nineth release (0.9) and seems to
|
||||
be pretty stable. Note that since version 0.4 a new schema is used.
|
||||
It is not backwards compatible with versions before 0.4.
|
||||
|
||||
In 0.9 the code has been cleaned up a bit and should be slightly faster
|
||||
than previous versions. It also fixes an error with zone transfers (AXFR)
|
||||
and entries with multiple relativeDomainName values. The problem was
|
||||
that it would only use the first value in the result. There's no need
|
||||
to upgrade unless you use such entries.
|
||||
|
||||
0.8 uses asynchronous LDAP search which should give better performance.
|
||||
Thanks to Ashley Burston for providing patch. Another new feature is
|
||||
allowing filters in URLs. The syntax is as in RFC 2255. Few people will
|
||||
need this, but if you have say an internal and external version of the
|
||||
same zone, you could stick say o=internal and o=external into different
|
||||
entries, and specify for instance ldap://host/base???(o=internal)
|
||||
Some error logging has also been added.
|
||||
|
||||
0.7 allows space and other characters to be used in URLs by use of %-quoting.
|
||||
For instance space can be written as %20. It also fixes a problem with some
|
||||
servers and/or APIs that do not preserve attribute casing.
|
||||
|
||||
0.6 fixes some memory leaks present in older versions unless compiled with
|
||||
the RFC 1823 API.
|
||||
|
||||
The big changes in 0.5 are thread support and improved connection handling.
|
||||
Multiple threads can now access the back-end simultaneously, and rather than
|
||||
having one connection per zone, there is now one connection per thread per
|
||||
LDAP server. This should help people with multiple CPUs and people with a
|
||||
huge number of zones. One final change is support for literal IPv6 addresses
|
||||
in LDAP URLs. At least OpenLDAP 2 has IPv6 support, so if you use OpenLDAP 2
|
||||
libraries and server, you got all you need.
|
||||
|
||||
If you have bug reports, fixes, comments, questions or whatever, please
|
||||
contact me. See also http://www.venaas.no/ldap/bind-sdb/ for information.
|
||||
|
||||
See INSTALL for how to build, install and use.
|
||||
|
||||
Stig Venaas <venaas@uninett.no> 2001-05-06
|
||||
Stig Venaas <venaas@uninett.no> 2001-12-29
|
||||
|
|
|
|||
|
|
@ -1,11 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) 2001 Stig Venaas
|
||||
* ldapdb.c version 0.9
|
||||
*
|
||||
* Copyright (C) 2002 Stig Venaas
|
||||
*
|
||||
* Permission to use, copy, modify, and 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If you are using an old LDAP API uncomment the define below. Only do this
|
||||
* if you know what you're doing or get compilation errors on ldap_memfree().
|
||||
*/
|
||||
/* #define RFC1823API */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
|
|
@ -22,14 +30,18 @@
|
|||
#include <dns/sdb.h>
|
||||
|
||||
#include <named/globals.h>
|
||||
#include <named/log.h>
|
||||
|
||||
#include <ldap.h>
|
||||
#include "ldapdb.h"
|
||||
|
||||
/*
|
||||
* A simple database driver for LDAP. Not production quality yet
|
||||
* A simple database driver for LDAP
|
||||
*/
|
||||
|
||||
/* enough for name with 8 labels of max length */
|
||||
#define MAXNAMELEN 519
|
||||
|
||||
static dns_sdbimplementation_t *ldapdb = NULL;
|
||||
|
||||
struct ldapdb_data {
|
||||
|
|
@ -38,6 +50,11 @@ struct ldapdb_data {
|
|||
int portno;
|
||||
char *base;
|
||||
int defaultttl;
|
||||
char *filterall;
|
||||
int filteralllen;
|
||||
char *filterone;
|
||||
int filteronelen;
|
||||
char *filtername;
|
||||
};
|
||||
|
||||
/* used by ldapdb_getconn */
|
||||
|
|
@ -153,16 +170,232 @@ ldapdb_getconn(struct ldapdb_data *data)
|
|||
return (LDAP **)&conndata->data;
|
||||
}
|
||||
|
||||
static void
|
||||
ldapdb_bind(struct ldapdb_data *data, LDAP **ldp)
|
||||
{
|
||||
if (*ldp != NULL)
|
||||
ldap_unbind(*ldp);
|
||||
*ldp = ldap_open(data->hostname, data->portno);
|
||||
if (*ldp == NULL)
|
||||
return;
|
||||
if (ldap_simple_bind_s(*ldp, NULL, NULL) != LDAP_SUCCESS) {
|
||||
ldap_unbind(*ldp);
|
||||
*ldp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata)
|
||||
{
|
||||
struct ldapdb_data *data = dbdata;
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
LDAP **ldp;
|
||||
LDAPMessage *res, *e;
|
||||
char *fltr, *a, **vals, **names;
|
||||
char type[64];
|
||||
#ifdef RFC1823API
|
||||
void *ptr;
|
||||
#else
|
||||
BerElement *ptr;
|
||||
#endif
|
||||
int i, j, errno, msgid;
|
||||
|
||||
ldp = ldapdb_getconn(data);
|
||||
if (ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
if (*ldp == NULL) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp == NULL) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"LDAP sdb zone '%s': bind failed", zone);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (name == NULL) {
|
||||
fltr = data->filterall;
|
||||
} else {
|
||||
if (strlen(name) > MAXNAMELEN) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"LDAP sdb zone '%s': name %s too long", zone, name);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
sprintf(data->filtername, "%s))", name);
|
||||
fltr = data->filterone;
|
||||
}
|
||||
|
||||
msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0);
|
||||
if (msgid == -1) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp != NULL)
|
||||
msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0);
|
||||
}
|
||||
|
||||
if (*ldp == NULL || msgid == -1) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"LDAP sdb zone '%s': search failed, filter %s", zone, fltr);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/* Get the records one by one as they arrive and return them to bind */
|
||||
while ((errno = ldap_result(*ldp, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) {
|
||||
LDAP *ld = *ldp;
|
||||
int ttl = data->defaultttl;
|
||||
|
||||
/* not supporting continuation references at present */
|
||||
if (errno != LDAP_RES_SEARCH_ENTRY) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"LDAP sdb zone '%s': ldap_result returned %d", zone, errno);
|
||||
ldap_msgfree(res);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/* only one entry per result message */
|
||||
e = ldap_first_entry(ld, res);
|
||||
if (e == NULL) {
|
||||
ldap_msgfree(res);
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"LDAP sdb zone '%s': ldap_first_entry failed", zone);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (name == NULL) {
|
||||
names = ldap_get_values(ld, e, "relativeDomainName");
|
||||
if (names == NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
vals = ldap_get_values(ld, e, "dNSTTL");
|
||||
if (vals != NULL) {
|
||||
ttl = atoi(vals[0]);
|
||||
ldap_value_free(vals);
|
||||
}
|
||||
|
||||
for (a = ldap_first_attribute(ld, e, &ptr); a != NULL; a = ldap_next_attribute(ld, e, ptr)) {
|
||||
char *s;
|
||||
|
||||
for (s = a; *s; s++)
|
||||
*s = toupper(*s);
|
||||
s = strstr(a, "RECORD");
|
||||
if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) {
|
||||
#ifndef RFC1823API
|
||||
ldap_memfree(a);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
strncpy(type, a, s - a);
|
||||
type[s - a] = '\0';
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
if (vals != NULL) {
|
||||
for (i = 0; vals[i] != NULL; i++) {
|
||||
if (name != NULL) {
|
||||
result = dns_sdb_putrr(retdata, type, ttl, vals[i]);
|
||||
} else {
|
||||
for (j = 0; names[j] != NULL; j++) {
|
||||
result = dns_sdb_putnamedrr(retdata, names[j], type, ttl, vals[i]);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
; if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"LDAP sdb zone '%s': dns_sdb_put... failed for %s", zone, vals[i]);
|
||||
ldap_value_free(vals);
|
||||
#ifndef RFC1823API
|
||||
ldap_memfree(a);
|
||||
if (ptr != NULL)
|
||||
ber_free(ptr, 0);
|
||||
#endif
|
||||
if (name == NULL)
|
||||
ldap_value_free(names);
|
||||
ldap_msgfree(res);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
ldap_value_free(vals);
|
||||
}
|
||||
#ifndef RFC1823API
|
||||
ldap_memfree(a);
|
||||
#endif
|
||||
}
|
||||
#ifndef RFC1823API
|
||||
if (ptr != NULL)
|
||||
ber_free(ptr, 0);
|
||||
#endif
|
||||
if (name == NULL)
|
||||
ldap_value_free(names);
|
||||
|
||||
/* cleanup this result */
|
||||
ldap_msgfree(res);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/* callback routines */
|
||||
static isc_result_t
|
||||
ldapdb_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdblookup_t *lookup)
|
||||
{
|
||||
return ldapdb_search(zone, name, dbdata, lookup);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_allnodes(const char *zone, void *dbdata,
|
||||
dns_sdballnodes_t *allnodes)
|
||||
{
|
||||
return ldapdb_search(zone, NULL, dbdata, allnodes);
|
||||
}
|
||||
|
||||
static char *
|
||||
unhex(char *in)
|
||||
{
|
||||
static const char hexdigits[] = "0123456789abcdef";
|
||||
char *p, *s = in;
|
||||
int d1, d2;
|
||||
|
||||
while ((s = strchr(s, '%'))) {
|
||||
if (!(s[1] && s[2]))
|
||||
return NULL;
|
||||
if ((p = strchr(hexdigits, tolower(s[1]))) == NULL)
|
||||
return NULL;
|
||||
d1 = p - hexdigits;
|
||||
if ((p = strchr(hexdigits, tolower(s[2]))) == NULL)
|
||||
return NULL;
|
||||
d2 = p - hexdigits;
|
||||
*s++ = d1 << 4 | d2;
|
||||
memmove(s, s + 2, strlen(s) - 1);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
free_data(struct ldapdb_data *data)
|
||||
{
|
||||
if (data->hostport != NULL)
|
||||
isc_mem_free(ns_g_mctx, data->hostport);
|
||||
if (data->hostname != NULL)
|
||||
isc_mem_free(ns_g_mctx, data->hostname);
|
||||
if (data->filterall != NULL)
|
||||
isc_mem_put(ns_g_mctx, data->filterall, data->filteralllen);
|
||||
if (data->filterone != NULL)
|
||||
isc_mem_put(ns_g_mctx, data->filterone, data->filteronelen);
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
|
||||
}
|
||||
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_create(const char *zone, int argc, char **argv,
|
||||
void *driverdata, void **dbdata)
|
||||
{
|
||||
struct ldapdb_data *data;
|
||||
char *s;
|
||||
char *s, *filter = NULL;
|
||||
int defaultttl;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(driverdata);
|
||||
|
||||
/* we assume that only one thread will call create at a time */
|
||||
|
|
@ -175,24 +408,89 @@ ldapdb_create(const char *zone, int argc, char **argv,
|
|||
data = isc_mem_get(ns_g_mctx, sizeof(struct ldapdb_data));
|
||||
if (data == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
memset(data, 0, sizeof(struct ldapdb_data));
|
||||
data->hostport = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://"));
|
||||
if (data->hostport == NULL) {
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
|
||||
free_data(data);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
data->defaultttl = defaultttl;
|
||||
|
||||
s = strchr(data->hostport, '/');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
data->base = *s != '\0' ? s : NULL;
|
||||
data->base = s;
|
||||
/* attrs, scope, filter etc? */
|
||||
s = strchr(s, '?');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
/* ignore attributes */
|
||||
s = strchr(s, '?');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
/* ignore scope */
|
||||
s = strchr(s, '?');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
/* filter */
|
||||
filter = s;
|
||||
s = strchr(s, '?');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
}
|
||||
if (*filter == '\0') {
|
||||
filter = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*data->base == '\0') {
|
||||
data->base = NULL;
|
||||
}
|
||||
|
||||
if ((data->base != NULL && unhex(data->base) == NULL) || (filter != NULL && unhex(filter) == NULL)) {
|
||||
free_data(data);
|
||||
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"LDAP sdb zone '%s': bad hex values", zone);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* compute filterall and filterone once and for all */
|
||||
if (filter == NULL) {
|
||||
data->filteralllen = strlen(zone) + strlen("(zoneName=)") + 1;
|
||||
data->filteronelen = strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;
|
||||
} else {
|
||||
data->filteralllen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=))") + 1;
|
||||
data->filteronelen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;
|
||||
}
|
||||
|
||||
data->filterall = isc_mem_get(ns_g_mctx, data->filteralllen);
|
||||
if (data->filterall == NULL) {
|
||||
free_data(data);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
data->filterone = isc_mem_get(ns_g_mctx, data->filteronelen);
|
||||
if (data->filterone == NULL) {
|
||||
free_data(data);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
if (filter == NULL) {
|
||||
sprintf(data->filterall, "(zoneName=%s)", zone);
|
||||
sprintf(data->filterone, "(&(zoneName=%s)(relativeDomainName=", zone);
|
||||
} else {
|
||||
sprintf(data->filterall, "(&%s(zoneName=%s))", filter, zone);
|
||||
sprintf(data->filterone, "(&%s(zoneName=%s)(relativeDomainName=", filter, zone);
|
||||
}
|
||||
data->filtername = data->filterone + strlen(data->filterone);
|
||||
|
||||
/* support URLs with literal IPv6 addresses */
|
||||
data->hostname = isc_mem_strdup(ns_g_mctx, data->hostport +
|
||||
(*data->hostport == '[' ? 1 : 0));
|
||||
data->hostname = isc_mem_strdup(ns_g_mctx, data->hostport + (*data->hostport == '[' ? 1 : 0));
|
||||
if (data->hostname == NULL) {
|
||||
isc_mem_free(ns_g_mctx, data->hostport);
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
|
||||
free_data(data);
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
|
|
@ -219,219 +517,7 @@ ldapdb_destroy(const char *zone, void *driverdata, void **dbdata) {
|
|||
UNUSED(zone);
|
||||
UNUSED(driverdata);
|
||||
|
||||
if (data->hostport != NULL)
|
||||
isc_mem_free(ns_g_mctx, data->hostport);
|
||||
if (data->hostname != NULL)
|
||||
isc_mem_free(ns_g_mctx, data->hostname);
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
|
||||
}
|
||||
|
||||
static void
|
||||
ldapdb_bind(struct ldapdb_data *data, LDAP **ldp)
|
||||
{
|
||||
if (*ldp != NULL)
|
||||
ldap_unbind(*ldp);
|
||||
*ldp = ldap_open(data->hostname, data->portno);
|
||||
if (*ldp == NULL)
|
||||
return;
|
||||
if (ldap_simple_bind_s(*ldp, NULL, NULL) != LDAP_SUCCESS) {
|
||||
ldap_unbind(*ldp);
|
||||
*ldp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdblookup_t *lookup)
|
||||
{
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
struct ldapdb_data *data = dbdata;
|
||||
LDAP **ldp;
|
||||
LDAPMessage *res, *e;
|
||||
char *fltr, *a, **vals;
|
||||
char type[64];
|
||||
BerElement *ptr;
|
||||
int i;
|
||||
|
||||
ldp = ldapdb_getconn(data);
|
||||
if (ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
if (*ldp == NULL) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
fltr = isc_mem_get(ns_g_mctx, strlen(zone) + strlen(name) +
|
||||
strlen("(&(zoneName=)(relativeDomainName=))") + 1);
|
||||
if (fltr == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
strcpy(fltr, "(&(zoneName=");
|
||||
strcat(fltr, zone);
|
||||
strcat(fltr, ")(relativeDomainName=");
|
||||
strcat(fltr, name);
|
||||
strcat(fltr, "))");
|
||||
|
||||
if (ldap_search_s(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0,
|
||||
&res) != LDAP_SUCCESS) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp != NULL)
|
||||
ldap_search_s(*ldp, data->base, LDAP_SCOPE_SUBTREE,
|
||||
fltr, NULL, 0, &res);
|
||||
}
|
||||
|
||||
isc_mem_put(ns_g_mctx, fltr, strlen(fltr) + 1);
|
||||
|
||||
if (*ldp == NULL)
|
||||
goto exit;
|
||||
|
||||
for (e = ldap_first_entry(*ldp, res); e != NULL;
|
||||
e = ldap_next_entry(*ldp, e)) {
|
||||
LDAP *ld = *ldp;
|
||||
int ttl = data->defaultttl;
|
||||
|
||||
for (a = ldap_first_attribute(ld, e, &ptr); a != NULL;
|
||||
a = ldap_next_attribute(ld, e, ptr)) {
|
||||
if (!strcmp(a, "dNSTTL")) {
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
ttl = atoi(vals[0]);
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
break;
|
||||
}
|
||||
ldap_memfree(a);
|
||||
}
|
||||
for (a = ldap_first_attribute(ld, e, &ptr); a != NULL;
|
||||
a = ldap_next_attribute(ld, e, ptr)) {
|
||||
char *s;
|
||||
|
||||
for (s = a; *s; s++)
|
||||
*s = toupper(*s);
|
||||
s = strstr(a, "RECORD");
|
||||
if ((s == NULL) || (s == a)
|
||||
|| (s - a >= (signed int)sizeof(type))) {
|
||||
ldap_memfree(a);
|
||||
continue;
|
||||
}
|
||||
strncpy(type, a, s - a);
|
||||
type[s - a] = '\0';
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
for (i=0; vals[i] != NULL; i++) {
|
||||
result = dns_sdb_putrr(lookup, type, ttl,
|
||||
vals[i]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
result = ISC_R_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
}
|
||||
}
|
||||
exit:
|
||||
ldap_msgfree(res);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_allnodes(const char *zone, void *dbdata,
|
||||
dns_sdballnodes_t *allnodes) {
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
struct ldapdb_data *data = dbdata;
|
||||
LDAP **ldp;
|
||||
LDAPMessage *res, *e;
|
||||
char type[64];
|
||||
char *fltr, *a, **vals;
|
||||
BerElement *ptr;
|
||||
int i;
|
||||
|
||||
ldp = ldapdb_getconn(data);
|
||||
if (ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
if (*ldp == NULL) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
fltr = isc_mem_get(ns_g_mctx, strlen(zone) + strlen("(zoneName=)") + 1);
|
||||
if (fltr == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
strcpy(fltr, "(zoneName=");
|
||||
strcat(fltr, zone);
|
||||
strcat(fltr, ")");
|
||||
|
||||
if (ldap_search_s(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0,
|
||||
&res) != LDAP_SUCCESS) {
|
||||
ldapdb_bind(data, ldp);
|
||||
if (*ldp != NULL)
|
||||
ldap_search_s(*ldp, data->base, LDAP_SCOPE_SUBTREE,
|
||||
fltr, NULL, 0, &res);
|
||||
}
|
||||
|
||||
isc_mem_put(ns_g_mctx, fltr, strlen(fltr) + 1);
|
||||
|
||||
for (e = ldap_first_entry(*ldp, res); e != NULL;
|
||||
e = ldap_next_entry(*ldp, e)) {
|
||||
LDAP *ld = *ldp;
|
||||
char *name = NULL;
|
||||
int ttl = data->defaultttl;
|
||||
|
||||
for (a = ldap_first_attribute(ld, e, &ptr); a != NULL;
|
||||
a = ldap_next_attribute(ld, e, ptr)) {
|
||||
if (!strcmp(a, "dNSTTL")) {
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
ttl = atoi(vals[0]);
|
||||
ldap_value_free(vals);
|
||||
} else if (!strcmp(a, "relativeDomainName")) {
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
name = isc_mem_strdup(ns_g_mctx, vals[0]);
|
||||
ldap_value_free(vals);
|
||||
}
|
||||
ldap_memfree(a);
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
continue;
|
||||
|
||||
for (a = ldap_first_attribute(ld, e, &ptr); a != NULL;
|
||||
a = ldap_next_attribute(ld, e, ptr)) {
|
||||
char *s;
|
||||
|
||||
for (s = a; *s; s++)
|
||||
*s = toupper(*s);
|
||||
s = strstr(a, "RECORD");
|
||||
if ((s == NULL) || (s == a)
|
||||
|| (s - a >= (signed int)sizeof(type))) {
|
||||
ldap_memfree(a);
|
||||
continue;
|
||||
}
|
||||
strncpy(type, a, s - a);
|
||||
type[s - a] = '\0';
|
||||
vals = ldap_get_values(ld, e, a);
|
||||
for (i=0; vals[i] != NULL; i++) {
|
||||
result = dns_sdb_putnamedrr(allnodes, name,
|
||||
type, ttl, vals[i]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
isc_mem_free(ns_g_mctx, name);
|
||||
result = ISC_R_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
ldap_value_free(vals);
|
||||
ldap_memfree(a);
|
||||
}
|
||||
isc_mem_free(ns_g_mctx, name);
|
||||
}
|
||||
|
||||
exit:
|
||||
ldap_msgfree(res);
|
||||
return (result);
|
||||
free_data(data);
|
||||
}
|
||||
|
||||
static dns_sdbmethods_t ldapdb_methods = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue