2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-28 21:17:54 +00:00

update to newer version

This commit is contained in:
Brian Wellington 2001-05-30 22:02:09 +00:00
parent ace6fff229
commit adf16bbdb6
6 changed files with 520 additions and 186 deletions

View File

@ -1,4 +1,4 @@
This is the INSTALL file for 0.3. See
This is the INSTALL file for 0.4. See
http://www.venaas.no/ldap/bind-sdb/ for updates or other information.
BUILDING
@ -31,29 +31,25 @@ Before you do any configuring of LDAP stuff, please try to configure
and start bind as usual to see if things work.
To do anything useful, you need to store a zone in some LDAP server.
If you like, you could try to use my LDAP server as a test. To test,
add the following to your named.conf:
zone "ldap" {
type master;
database "ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 86400";
};
and then try to do for instance host www.ldap. localhost
The LDAP URL consists of a hostport part and the base (the node above
where the zone is stored). BIND will do a one-level search with this
base. Finally, the number 86400 is the TTL which will be used for all
entries that haven't got the dNSTTL attribute.
To store data in your own LDAP server you can use the Cosine dNSDomain
class, or even better dNSDomain2. Your LDAP server probably comes
with dNSDomain, you can find dNSDomain2 and further details on how
to store the data in your LDAP server at
From this release on, you must use a schema called dNSZone. Note that
it relies on some attribute definitions in the Cosine schema, so that
must be included as well. The Cosine schema probably comes with your
LDAP server. You can find dNSZone and further details on how to store
the data in your LDAP server at
http://www.venaas.no/ldap/bind-sdb/
You can also see how I did it by searching in my LDAP server, the
address and base is as in the LDAP URL above.
For an example, have a look at my venaas.com zone. Try a subtree search
for objectClass=* at
ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no
Stig Venaas <venaas@uninett.no> 2001-03-03
To use it with BIND, I've added the following to named.conf:
zone "venaas.com" {
type master;
database "ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 172800";
};
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.
Stig Venaas <venaas@uninett.no> 2001-04-12

View File

@ -1,9 +1,18 @@
This is an attempt at an LDAP back-end for BIND 9 using the new
simplified database interface "sdb". This is the third release
(0.3) and is not ready for production use yet. Bug reports,
fixes, comments, questions or whatever, please contact me. See
also http://www.venaas.no/ldap/bind-sdb/ for information.
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.
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-03-03
Stig Venaas <venaas@uninett.no> 2001-05-06

View File

@ -1,4 +1,4 @@
This is the INSTALL file for 0.3. See
This is the INSTALL file for 0.4. See
http://www.venaas.no/ldap/bind-sdb/ for updates or other information.
BUILDING
@ -31,29 +31,25 @@ Before you do any configuring of LDAP stuff, please try to configure
and start bind as usual to see if things work.
To do anything useful, you need to store a zone in some LDAP server.
If you like, you could try to use my LDAP server as a test. To test,
add the following to your named.conf:
zone "ldap" {
type master;
database "ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 86400";
};
and then try to do for instance host www.ldap. localhost
The LDAP URL consists of a hostport part and the base (the node above
where the zone is stored). BIND will do a one-level search with this
base. Finally, the number 86400 is the TTL which will be used for all
entries that haven't got the dNSTTL attribute.
To store data in your own LDAP server you can use the Cosine dNSDomain
class, or even better dNSDomain2. Your LDAP server probably comes
with dNSDomain, you can find dNSDomain2 and further details on how
to store the data in your LDAP server at
From this release on, you must use a schema called dNSZone. Note that
it relies on some attribute definitions in the Cosine schema, so that
must be included as well. The Cosine schema probably comes with your
LDAP server. You can find dNSZone and further details on how to store
the data in your LDAP server at
http://www.venaas.no/ldap/bind-sdb/
You can also see how I did it by searching in my LDAP server, the
address and base is as in the LDAP URL above.
For an example, have a look at my venaas.com zone. Try a subtree search
for objectClass=* at
ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no
Stig Venaas <venaas@uninett.no> 2001-03-03
To use it with BIND, I've added the following to named.conf:
zone "venaas.com" {
type master;
database "ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 172800";
};
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.
Stig Venaas <venaas@uninett.no> 2001-04-12

View File

@ -1,9 +1,18 @@
This is an attempt at an LDAP back-end for BIND 9 using the new
simplified database interface "sdb". This is the third release
(0.3) and is not ready for production use yet. Bug reports,
fixes, comments, questions or whatever, please contact me. See
also http://www.venaas.no/ldap/bind-sdb/ for information.
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.
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-03-03
Stig Venaas <venaas@uninett.no> 2001-05-06

View File

@ -17,6 +17,7 @@
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <isc/thread.h>
#include <dns/sdb.h>
@ -26,19 +27,133 @@
#include "ldapdb.h"
/*
* A simple database driver for LDAP. Not production quality yet.
* A simple database driver for LDAP. Not production quality yet
*/
static dns_sdbimplementation_t *ldapdb = NULL;
struct ldapdb_data {
char *hostport;
char *hostname;
int portno;
char *base;
int defaultttl;
LDAP *ld;
};
/* used by ldapdb_getconn */
struct ldapdb_entry {
void *index;
size_t size;
void *data;
struct ldapdb_entry *next;
};
static struct ldapdb_entry *ldapdb_find(struct ldapdb_entry *stack,
const void *index, size_t size) {
while (stack != NULL) {
if (stack->size == size && !memcmp(stack->index, index, size))
return stack;
stack = stack->next;
}
return NULL;
}
static void ldapdb_insert(struct ldapdb_entry **stack,
struct ldapdb_entry *item) {
item->next = *stack;
*stack = item;
}
static void ldapdb_lock(int what) {
static isc_mutex_t lock;
switch (what) {
case 0:
isc_mutex_init(&lock);
break;
case 1:
LOCK(&lock);
break;
case -1:
UNLOCK(&lock);
break;
}
}
/* data == NULL means cleanup */
static LDAP **
ldapdb_getconn(struct ldapdb_data *data)
{
static struct ldapdb_entry *allthreadsdata = NULL;
struct ldapdb_entry *threaddata, *conndata;
unsigned long threadid;
if (data == NULL) {
/* cleanup */
/* lock out other threads */
ldapdb_lock(1);
while (allthreadsdata != NULL) {
threaddata = allthreadsdata;
free(threaddata->index);
while (threaddata->data != NULL) {
conndata = threaddata->data;
free(conndata->index);
if (conndata->data != NULL)
ldap_unbind((LDAP *)conndata->data);
threaddata->data = conndata->next;
free(conndata);
}
allthreadsdata = threaddata->next;
free(threaddata);
}
ldapdb_lock(-1);
return (NULL);
}
/* look for connection data for current thread */
threadid = isc_thread_self();
threaddata = ldapdb_find(allthreadsdata, &threadid, sizeof(threadid));
if (threaddata == NULL) {
/* no data for this thread, create empty connection list */
threaddata = malloc(sizeof(*threaddata));
if (threaddata == NULL)
return (NULL);
threaddata->index = malloc(sizeof(threadid));
if (threaddata->index == NULL) {
free(threaddata);
return (NULL);
}
*(unsigned long *)threaddata->index = threadid;
threaddata->size = sizeof(threadid);
threaddata->data = NULL;
/* need to lock out other threads here */
ldapdb_lock(1);
ldapdb_insert(&allthreadsdata, threaddata);
ldapdb_lock(-1);
}
/* threaddata points at the connection list for current thread */
/* look for existing connection to our server */
conndata = ldapdb_find((struct ldapdb_entry *)threaddata->data,
data->hostport, strlen(data->hostport));
if (conndata == NULL) {
/* no connection data structure for this server, create one */
conndata = malloc(sizeof(*conndata));
if (conndata == NULL)
return (NULL);
(char *)conndata->index = data->hostport;
conndata->size = strlen(data->hostport);
conndata->data = NULL;
ldapdb_insert((struct ldapdb_entry **)&threaddata->data,
conndata);
}
return (LDAP **)&conndata->data;
}
/* callback routines */
static isc_result_t
ldapdb_create(const char *zone, int argc, char **argv,
void *driverdata, void **dbdata)
@ -46,10 +161,13 @@ ldapdb_create(const char *zone, int argc, char **argv,
struct ldapdb_data *data;
char *s;
int defaultttl;
UNUSED(zone);
UNUSED(driverdata);
/* we assume that only one thread will call create at a time */
/* want to do this only once for all instances */
if ((argc < 2)
|| (argv[0] != strstr( argv[0], "ldap://"))
|| ((defaultttl = atoi(argv[1])) < 1))
@ -57,24 +175,39 @@ 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);
data->hostname = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://"));
if (data->hostname == NULL) {
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));
return (ISC_R_NOMEMORY);
}
data->defaultttl = defaultttl;
s = strchr(data->hostname, '/');
s = strchr(data->hostport, '/');
if (s != NULL) {
*s++ = '\0';
data->base = *s != '\0' ? s : NULL;
}
s = strchr(data->hostname, ':');
/* support URLs with literal IPv6 addresses */
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));
return (ISC_R_NOMEMORY);
}
if (*data->hostport == '[' &&
(s = strchr(data->hostname, ']')) != NULL )
*s++ = '\0';
else
s = data->hostname;
s = strchr(s, ':');
if (s != NULL) {
*s++ = '\0';
data->portno = atoi(s);
} else
data->portno = LDAP_PORT;
data->ld = NULL;
*dbdata = data;
return (ISC_R_SUCCESS);
}
@ -86,26 +219,24 @@ ldapdb_destroy(const char *zone, void *driverdata, void **dbdata) {
UNUSED(zone);
UNUSED(driverdata);
if (data == NULL)
return;
if (data->ld != NULL)
ldap_unbind(data->ld);
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)
ldapdb_bind(struct ldapdb_data *data, LDAP **ldp)
{
if (data->ld != NULL)
ldap_unbind(data->ld);
data->ld = ldap_open(data->hostname, data->portno);
if (data->ld == NULL)
if (*ldp != NULL)
ldap_unbind(*ldp);
*ldp = ldap_open(data->hostname, data->portno);
if (*ldp == NULL)
return;
if (ldap_simple_bind_s(data->ld, NULL, NULL) != LDAP_SUCCESS) {
ldap_unbind(data->ld);
data->ld = NULL;
if (ldap_simple_bind_s(*ldp, NULL, NULL) != LDAP_SUCCESS) {
ldap_unbind(*ldp);
*ldp = NULL;
}
}
@ -115,37 +246,48 @@ ldapdb_lookup(const char *zone, const char *name, void *dbdata,
{
isc_result_t result = ISC_R_NOTFOUND;
struct ldapdb_data *data = dbdata;
LDAPMessage *res, *e;
LDAP **ldp;
LDAPMessage *res, *e;
char *fltr, *a, **vals;
char type[64];
BerElement *ptr;
int i;
UNUSED(zone);
if (data->ld == NULL) {
ldapdb_bind(data);
if (data->ld == NULL)
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(name) + strlen("(dc=)") + 1);
fltr = isc_mem_get(ns_g_mctx, strlen(zone) + strlen(name) +
strlen("(&(zoneName=)(relativeDomainName=))") + 1);
if (fltr == NULL)
return (ISC_R_NOMEMORY);
strcpy(fltr, "(dc=");
strcpy(fltr, "(&(zoneName=");
strcat(fltr, zone);
strcat(fltr, ")(relativeDomainName=");
strcat(fltr, name);
strcat(fltr, ")");
if (ldap_search_s(data->ld, data->base, LDAP_SCOPE_ONELEVEL, fltr, NULL, 0, &res) != LDAP_SUCCESS) {
ldapdb_bind(data);
if (data->ld != NULL)
ldap_search_s(data->ld, data->base, LDAP_SCOPE_ONELEVEL, fltr, NULL, 0, &res);
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 (data->ld == NULL)
if (*ldp == NULL)
goto exit;
for (e = ldap_first_entry(data->ld, res); e != NULL;
e = ldap_next_entry(data->ld, e)) {
LDAP *ld = data->ld;
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;
@ -175,7 +317,8 @@ ldapdb_lookup(const char *zone, const char *name, void *dbdata,
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]);
result = dns_sdb_putrr(lookup, type, ttl,
vals[i]);
if (result != ISC_R_SUCCESS) {
ldap_value_free(vals);
ldap_memfree(a);
@ -193,32 +336,47 @@ ldapdb_lookup(const char *zone, const char *name, void *dbdata,
}
static isc_result_t
ldapdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
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 *a, **vals;
char *fltr, *a, **vals;
BerElement *ptr;
int i;
UNUSED(zone);
if (data->ld == NULL) {
ldapdb_bind(data);
if (data->ld == NULL)
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);
}
if (ldap_search_s(data->ld, data->base, LDAP_SCOPE_ONELEVEL, "(objectclass=*)", NULL, 0, &res) != LDAP_SUCCESS) {
ldapdb_bind(data);
if (data->ld != NULL)
ldap_search_s(data->ld, data->base, LDAP_SCOPE_ONELEVEL, "(objectclass=*)", NULL, 0, &res);
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);
}
for (e = ldap_first_entry(data->ld, res); e != NULL;
e = ldap_next_entry(data->ld, e)) {
LDAP *ld = data->ld;
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;
@ -228,7 +386,7 @@ ldapdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
vals = ldap_get_values(ld, e, a);
ttl = atoi(vals[0]);
ldap_value_free(vals);
} else if (!strcmp(a, "dc")) {
} 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);
@ -255,7 +413,8 @@ ldapdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
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]);
result = dns_sdb_putnamedrr(allnodes, name,
type, ttl, vals[i]);
if (result != ISC_R_SUCCESS) {
ldap_value_free(vals);
ldap_memfree(a);
@ -283,22 +442,25 @@ static dns_sdbmethods_t ldapdb_methods = {
ldapdb_destroy
};
/*
* Wrapper around dns_sdb_register().
*/
/* Wrapper around dns_sdb_register() */
isc_result_t
ldapdb_init(void) {
unsigned int flags;
flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
unsigned int flags =
DNS_SDBFLAG_RELATIVEOWNER |
DNS_SDBFLAG_RELATIVERDATA |
DNS_SDBFLAG_THREADSAFE;
ldapdb_lock(0);
return (dns_sdb_register("ldap", &ldapdb_methods, NULL, flags,
ns_g_mctx, &ldapdb));
}
/*
* Wrapper around dns_sdb_unregister().
*/
/* Wrapper around dns_sdb_unregister() */
void
ldapdb_clear(void) {
if (ldapdb != NULL)
if (ldapdb != NULL) {
/* clean up thread data */
ldapdb_getconn(NULL);
dns_sdb_unregister(&ldapdb);
}
}

View File

@ -17,6 +17,7 @@
#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>
#include <isc/thread.h>
#include <dns/sdb.h>
@ -26,19 +27,133 @@
#include "ldapdb.h"
/*
* A simple database driver for LDAP. Not production quality yet.
* A simple database driver for LDAP. Not production quality yet
*/
static dns_sdbimplementation_t *ldapdb = NULL;
struct ldapdb_data {
char *hostport;
char *hostname;
int portno;
char *base;
int defaultttl;
LDAP *ld;
};
/* used by ldapdb_getconn */
struct ldapdb_entry {
void *index;
size_t size;
void *data;
struct ldapdb_entry *next;
};
static struct ldapdb_entry *ldapdb_find(struct ldapdb_entry *stack,
const void *index, size_t size) {
while (stack != NULL) {
if (stack->size == size && !memcmp(stack->index, index, size))
return stack;
stack = stack->next;
}
return NULL;
}
static void ldapdb_insert(struct ldapdb_entry **stack,
struct ldapdb_entry *item) {
item->next = *stack;
*stack = item;
}
static void ldapdb_lock(int what) {
static isc_mutex_t lock;
switch (what) {
case 0:
isc_mutex_init(&lock);
break;
case 1:
LOCK(&lock);
break;
case -1:
UNLOCK(&lock);
break;
}
}
/* data == NULL means cleanup */
static LDAP **
ldapdb_getconn(struct ldapdb_data *data)
{
static struct ldapdb_entry *allthreadsdata = NULL;
struct ldapdb_entry *threaddata, *conndata;
unsigned long threadid;
if (data == NULL) {
/* cleanup */
/* lock out other threads */
ldapdb_lock(1);
while (allthreadsdata != NULL) {
threaddata = allthreadsdata;
free(threaddata->index);
while (threaddata->data != NULL) {
conndata = threaddata->data;
free(conndata->index);
if (conndata->data != NULL)
ldap_unbind((LDAP *)conndata->data);
threaddata->data = conndata->next;
free(conndata);
}
allthreadsdata = threaddata->next;
free(threaddata);
}
ldapdb_lock(-1);
return (NULL);
}
/* look for connection data for current thread */
threadid = isc_thread_self();
threaddata = ldapdb_find(allthreadsdata, &threadid, sizeof(threadid));
if (threaddata == NULL) {
/* no data for this thread, create empty connection list */
threaddata = malloc(sizeof(*threaddata));
if (threaddata == NULL)
return (NULL);
threaddata->index = malloc(sizeof(threadid));
if (threaddata->index == NULL) {
free(threaddata);
return (NULL);
}
*(unsigned long *)threaddata->index = threadid;
threaddata->size = sizeof(threadid);
threaddata->data = NULL;
/* need to lock out other threads here */
ldapdb_lock(1);
ldapdb_insert(&allthreadsdata, threaddata);
ldapdb_lock(-1);
}
/* threaddata points at the connection list for current thread */
/* look for existing connection to our server */
conndata = ldapdb_find((struct ldapdb_entry *)threaddata->data,
data->hostport, strlen(data->hostport));
if (conndata == NULL) {
/* no connection data structure for this server, create one */
conndata = malloc(sizeof(*conndata));
if (conndata == NULL)
return (NULL);
(char *)conndata->index = data->hostport;
conndata->size = strlen(data->hostport);
conndata->data = NULL;
ldapdb_insert((struct ldapdb_entry **)&threaddata->data,
conndata);
}
return (LDAP **)&conndata->data;
}
/* callback routines */
static isc_result_t
ldapdb_create(const char *zone, int argc, char **argv,
void *driverdata, void **dbdata)
@ -46,10 +161,13 @@ ldapdb_create(const char *zone, int argc, char **argv,
struct ldapdb_data *data;
char *s;
int defaultttl;
UNUSED(zone);
UNUSED(driverdata);
/* we assume that only one thread will call create at a time */
/* want to do this only once for all instances */
if ((argc < 2)
|| (argv[0] != strstr( argv[0], "ldap://"))
|| ((defaultttl = atoi(argv[1])) < 1))
@ -57,24 +175,39 @@ 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);
data->hostname = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://"));
if (data->hostname == NULL) {
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));
return (ISC_R_NOMEMORY);
}
data->defaultttl = defaultttl;
s = strchr(data->hostname, '/');
s = strchr(data->hostport, '/');
if (s != NULL) {
*s++ = '\0';
data->base = *s != '\0' ? s : NULL;
}
s = strchr(data->hostname, ':');
/* support URLs with literal IPv6 addresses */
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));
return (ISC_R_NOMEMORY);
}
if (*data->hostport == '[' &&
(s = strchr(data->hostname, ']')) != NULL )
*s++ = '\0';
else
s = data->hostname;
s = strchr(s, ':');
if (s != NULL) {
*s++ = '\0';
data->portno = atoi(s);
} else
data->portno = LDAP_PORT;
data->ld = NULL;
*dbdata = data;
return (ISC_R_SUCCESS);
}
@ -86,26 +219,24 @@ ldapdb_destroy(const char *zone, void *driverdata, void **dbdata) {
UNUSED(zone);
UNUSED(driverdata);
if (data == NULL)
return;
if (data->ld != NULL)
ldap_unbind(data->ld);
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)
ldapdb_bind(struct ldapdb_data *data, LDAP **ldp)
{
if (data->ld != NULL)
ldap_unbind(data->ld);
data->ld = ldap_open(data->hostname, data->portno);
if (data->ld == NULL)
if (*ldp != NULL)
ldap_unbind(*ldp);
*ldp = ldap_open(data->hostname, data->portno);
if (*ldp == NULL)
return;
if (ldap_simple_bind_s(data->ld, NULL, NULL) != LDAP_SUCCESS) {
ldap_unbind(data->ld);
data->ld = NULL;
if (ldap_simple_bind_s(*ldp, NULL, NULL) != LDAP_SUCCESS) {
ldap_unbind(*ldp);
*ldp = NULL;
}
}
@ -115,37 +246,48 @@ ldapdb_lookup(const char *zone, const char *name, void *dbdata,
{
isc_result_t result = ISC_R_NOTFOUND;
struct ldapdb_data *data = dbdata;
LDAPMessage *res, *e;
LDAP **ldp;
LDAPMessage *res, *e;
char *fltr, *a, **vals;
char type[64];
BerElement *ptr;
int i;
UNUSED(zone);
if (data->ld == NULL) {
ldapdb_bind(data);
if (data->ld == NULL)
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(name) + strlen("(dc=)") + 1);
fltr = isc_mem_get(ns_g_mctx, strlen(zone) + strlen(name) +
strlen("(&(zoneName=)(relativeDomainName=))") + 1);
if (fltr == NULL)
return (ISC_R_NOMEMORY);
strcpy(fltr, "(dc=");
strcpy(fltr, "(&(zoneName=");
strcat(fltr, zone);
strcat(fltr, ")(relativeDomainName=");
strcat(fltr, name);
strcat(fltr, ")");
if (ldap_search_s(data->ld, data->base, LDAP_SCOPE_ONELEVEL, fltr, NULL, 0, &res) != LDAP_SUCCESS) {
ldapdb_bind(data);
if (data->ld != NULL)
ldap_search_s(data->ld, data->base, LDAP_SCOPE_ONELEVEL, fltr, NULL, 0, &res);
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 (data->ld == NULL)
if (*ldp == NULL)
goto exit;
for (e = ldap_first_entry(data->ld, res); e != NULL;
e = ldap_next_entry(data->ld, e)) {
LDAP *ld = data->ld;
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;
@ -175,7 +317,8 @@ ldapdb_lookup(const char *zone, const char *name, void *dbdata,
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]);
result = dns_sdb_putrr(lookup, type, ttl,
vals[i]);
if (result != ISC_R_SUCCESS) {
ldap_value_free(vals);
ldap_memfree(a);
@ -193,32 +336,47 @@ ldapdb_lookup(const char *zone, const char *name, void *dbdata,
}
static isc_result_t
ldapdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
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 *a, **vals;
char *fltr, *a, **vals;
BerElement *ptr;
int i;
UNUSED(zone);
if (data->ld == NULL) {
ldapdb_bind(data);
if (data->ld == NULL)
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);
}
if (ldap_search_s(data->ld, data->base, LDAP_SCOPE_ONELEVEL, "(objectclass=*)", NULL, 0, &res) != LDAP_SUCCESS) {
ldapdb_bind(data);
if (data->ld != NULL)
ldap_search_s(data->ld, data->base, LDAP_SCOPE_ONELEVEL, "(objectclass=*)", NULL, 0, &res);
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);
}
for (e = ldap_first_entry(data->ld, res); e != NULL;
e = ldap_next_entry(data->ld, e)) {
LDAP *ld = data->ld;
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;
@ -228,7 +386,7 @@ ldapdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
vals = ldap_get_values(ld, e, a);
ttl = atoi(vals[0]);
ldap_value_free(vals);
} else if (!strcmp(a, "dc")) {
} 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);
@ -255,7 +413,8 @@ ldapdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
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]);
result = dns_sdb_putnamedrr(allnodes, name,
type, ttl, vals[i]);
if (result != ISC_R_SUCCESS) {
ldap_value_free(vals);
ldap_memfree(a);
@ -283,22 +442,25 @@ static dns_sdbmethods_t ldapdb_methods = {
ldapdb_destroy
};
/*
* Wrapper around dns_sdb_register().
*/
/* Wrapper around dns_sdb_register() */
isc_result_t
ldapdb_init(void) {
unsigned int flags;
flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
unsigned int flags =
DNS_SDBFLAG_RELATIVEOWNER |
DNS_SDBFLAG_RELATIVERDATA |
DNS_SDBFLAG_THREADSAFE;
ldapdb_lock(0);
return (dns_sdb_register("ldap", &ldapdb_methods, NULL, flags,
ns_g_mctx, &ldapdb));
}
/*
* Wrapper around dns_sdb_unregister().
*/
/* Wrapper around dns_sdb_unregister() */
void
ldapdb_clear(void) {
if (ldapdb != NULL)
if (ldapdb != NULL) {
/* clean up thread data */
ldapdb_getconn(NULL);
dns_sdb_unregister(&ldapdb);
}
}