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:
parent
ace6fff229
commit
adf16bbdb6
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user