mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 20:19:59 -04:00
Added the contributed LDAP sdb driver and program to convert a zone into an
LDAP schema.
This commit is contained in:
parent
02a402afe5
commit
bf49a52178
13 changed files with 2244 additions and 0 deletions
59
contrib/sdb/INSTALL.ldap
Normal file
59
contrib/sdb/INSTALL.ldap
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
This is the INSTALL file for 0.3. See
|
||||
http://www.venaas.no/ldap/bind-sdb/ for updates or other information.
|
||||
|
||||
BUILDING
|
||||
|
||||
You need the source for BIND 9.1.0 or newer (for zone transfers you
|
||||
will need at least 9.1.1rc3 due to a bug). Basically you need to follow
|
||||
the instructions in doc/misc/sdb, if my instructions doesn't make sense,
|
||||
please have a look at that as well.
|
||||
|
||||
Copy ldapdb.c to bin/named and ldapdb.h to bin/named/include in the
|
||||
source tree.
|
||||
|
||||
Next alter bin/named/Makefile.in. Add ldapdb.@O@ to DBDRIVER_OBJS and
|
||||
ldapdb.c to DBDRIVER_SRCS. You also need to add something like
|
||||
-I/usr/local/include to DBDRIVER_INCLUDES and
|
||||
-L/usr/local/lib -lldap -llber -lresolv to DBDRIVER_LIBS
|
||||
depending on what LDAP library you have and where you installed it.
|
||||
|
||||
Finally you need to edit bin/named/main.c. Below where it says
|
||||
"#include "xxdb.h"", add the line "#include <ldapdb.h>". Below where
|
||||
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.
|
||||
|
||||
|
||||
CONFIGURING
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
Stig Venaas <venaas@uninett.no> 2001-03-03
|
||||
9
contrib/sdb/README.ldap
Normal file
9
contrib/sdb/README.ldap
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
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.
|
||||
|
||||
See INSTALL for how to build, install and use.
|
||||
|
||||
Stig Venaas <venaas@uninett.no> 2001-03-03
|
||||
59
contrib/sdb/ldap/INSTALL.ldap
Normal file
59
contrib/sdb/ldap/INSTALL.ldap
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
This is the INSTALL file for 0.3. See
|
||||
http://www.venaas.no/ldap/bind-sdb/ for updates or other information.
|
||||
|
||||
BUILDING
|
||||
|
||||
You need the source for BIND 9.1.0 or newer (for zone transfers you
|
||||
will need at least 9.1.1rc3 due to a bug). Basically you need to follow
|
||||
the instructions in doc/misc/sdb, if my instructions doesn't make sense,
|
||||
please have a look at that as well.
|
||||
|
||||
Copy ldapdb.c to bin/named and ldapdb.h to bin/named/include in the
|
||||
source tree.
|
||||
|
||||
Next alter bin/named/Makefile.in. Add ldapdb.@O@ to DBDRIVER_OBJS and
|
||||
ldapdb.c to DBDRIVER_SRCS. You also need to add something like
|
||||
-I/usr/local/include to DBDRIVER_INCLUDES and
|
||||
-L/usr/local/lib -lldap -llber -lresolv to DBDRIVER_LIBS
|
||||
depending on what LDAP library you have and where you installed it.
|
||||
|
||||
Finally you need to edit bin/named/main.c. Below where it says
|
||||
"#include "xxdb.h"", add the line "#include <ldapdb.h>". Below where
|
||||
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.
|
||||
|
||||
|
||||
CONFIGURING
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
Stig Venaas <venaas@uninett.no> 2001-03-03
|
||||
9
contrib/sdb/ldap/README.ldap
Normal file
9
contrib/sdb/ldap/README.ldap
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
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.
|
||||
|
||||
See INSTALL for how to build, install and use.
|
||||
|
||||
Stig Venaas <venaas@uninett.no> 2001-03-03
|
||||
304
contrib/sdb/ldap/ldapdb.c
Normal file
304
contrib/sdb/ldap/ldapdb.c
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* Copyright (C) 2001 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/sdb.h>
|
||||
|
||||
#include <named/globals.h>
|
||||
|
||||
#include <ldap.h>
|
||||
#include "ldapdb.h"
|
||||
|
||||
/*
|
||||
* A simple database driver for LDAP. Not production quality yet.
|
||||
*/
|
||||
|
||||
static dns_sdbimplementation_t *ldapdb = NULL;
|
||||
|
||||
struct ldapdb_data {
|
||||
char *hostname;
|
||||
int portno;
|
||||
char *base;
|
||||
int defaultttl;
|
||||
LDAP *ld;
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_create(const char *zone, int argc, char **argv,
|
||||
void *driverdata, void **dbdata)
|
||||
{
|
||||
struct ldapdb_data *data;
|
||||
char *s;
|
||||
int defaultttl;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(driverdata);
|
||||
|
||||
if ((argc < 2)
|
||||
|| (argv[0] != strstr( argv[0], "ldap://"))
|
||||
|| ((defaultttl = atoi(argv[1])) < 1))
|
||||
return (ISC_R_FAILURE);
|
||||
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) {
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
data->defaultttl = defaultttl;
|
||||
s = strchr(data->hostname, '/');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
data->base = *s != '\0' ? s : NULL;
|
||||
}
|
||||
s = strchr(data->hostname, ':');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
data->portno = atoi(s);
|
||||
} else
|
||||
data->portno = LDAP_PORT;
|
||||
data->ld = NULL;
|
||||
*dbdata = data;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
ldapdb_destroy(const char *zone, void *driverdata, void **dbdata) {
|
||||
struct ldapdb_data *data = *dbdata;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(driverdata);
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
if (data->ld != NULL)
|
||||
ldap_unbind(data->ld);
|
||||
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)
|
||||
{
|
||||
if (data->ld != NULL)
|
||||
ldap_unbind(data->ld);
|
||||
data->ld = ldap_open(data->hostname, data->portno);
|
||||
if (data->ld == NULL)
|
||||
return;
|
||||
if (ldap_simple_bind_s(data->ld, NULL, NULL) != LDAP_SUCCESS) {
|
||||
ldap_unbind(data->ld);
|
||||
data->ld = 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;
|
||||
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)
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
fltr = isc_mem_get(ns_g_mctx, strlen(name) + strlen("(dc=)") + 1);
|
||||
if (fltr == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
strcpy(fltr, "(dc=");
|
||||
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);
|
||||
}
|
||||
isc_mem_put(ns_g_mctx, fltr, strlen(fltr) + 1);
|
||||
if (data->ld == NULL)
|
||||
goto exit;
|
||||
|
||||
for (e = ldap_first_entry(data->ld, res); e != NULL;
|
||||
e = ldap_next_entry(data->ld, e)) {
|
||||
LDAP *ld = data->ld;
|
||||
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;
|
||||
LDAPMessage *res, *e;
|
||||
char type[64];
|
||||
char *a, **vals;
|
||||
BerElement *ptr;
|
||||
int i;
|
||||
|
||||
UNUSED(zone);
|
||||
|
||||
if (data->ld == NULL) {
|
||||
ldapdb_bind(data);
|
||||
if (data->ld == 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);
|
||||
}
|
||||
|
||||
for (e = ldap_first_entry(data->ld, res); e != NULL;
|
||||
e = ldap_next_entry(data->ld, e)) {
|
||||
LDAP *ld = data->ld;
|
||||
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, "dc")) {
|
||||
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);
|
||||
}
|
||||
|
||||
static dns_sdbmethods_t ldapdb_methods = {
|
||||
ldapdb_lookup,
|
||||
NULL, /* authority */
|
||||
ldapdb_allnodes,
|
||||
ldapdb_create,
|
||||
ldapdb_destroy
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapper around dns_sdb_register().
|
||||
*/
|
||||
isc_result_t
|
||||
ldapdb_init(void) {
|
||||
unsigned int flags;
|
||||
flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
|
||||
return (dns_sdb_register("ldap", &ldapdb_methods, NULL, flags,
|
||||
ns_g_mctx, &ldapdb));
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper around dns_sdb_unregister().
|
||||
*/
|
||||
void
|
||||
ldapdb_clear(void) {
|
||||
if (ldapdb != NULL)
|
||||
dns_sdb_unregister(&ldapdb);
|
||||
}
|
||||
6
contrib/sdb/ldap/ldapdb.h
Normal file
6
contrib/sdb/ldap/ldapdb.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include <isc/types.h>
|
||||
|
||||
isc_result_t ldapdb_init(void);
|
||||
|
||||
void ldapdb_clear(void);
|
||||
|
||||
64
contrib/sdb/ldap/zone2ldap.1
Normal file
64
contrib/sdb/ldap/zone2ldap.1
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
.TH zone2ldap 1 "8 March 2001"
|
||||
.SH NAME
|
||||
zone2ldap /- Load BIND 9 Zone files into LDAP Directory
|
||||
.SH SYNOPSIS
|
||||
zone2ldap [-D Bind DN] [-w Bind Password] [-b Base DN] [-z Zone] [-f Zone File ] [-h Ldap Host] [-cd] [-v]
|
||||
.SH DESCRIPTION
|
||||
zone2ldap will parse a complete BIND 9 format DNS zone file, and load
|
||||
the contents into an LDAP directory, for use with the LDAP sdb back-end.
|
||||
|
||||
If the zone already exists, zone2ldap will exit succesfully. If the zone does not exists, or
|
||||
partially exists, zone2ldap will attempt to add all/missing zone data.
|
||||
|
||||
.SS Options
|
||||
.TP
|
||||
-b
|
||||
LDAP Base DN. LDAP systems require a "base dn", which is generally considered the LDAP Directory root.
|
||||
If the zone you are loading is different from the base, then you will need to tell zone2ldap what your LDAP
|
||||
base is.
|
||||
.TP
|
||||
-v
|
||||
Print version information, and immediatly exit.
|
||||
.TP
|
||||
-f
|
||||
Zone file. Bind 9.1 compatible zone file, from which zone information will be read.
|
||||
.TP
|
||||
-d
|
||||
Dump debug information to standard out.
|
||||
.TP
|
||||
-w
|
||||
LDAP Bind password, corresponding the the value of "-b".
|
||||
.TP
|
||||
-h
|
||||
LDAP Directory host. This is the hostname of the LDAP system you wish to store zone information on.
|
||||
An LDAP server should be listening on port 389 of the target system. This may be ommited, and will default
|
||||
to "localhost".
|
||||
.TP
|
||||
-c
|
||||
This will create the zone portion of the DN you are importing. For instance, if you are creating a domain.com zone,
|
||||
zone2ldap should first create "dc=domain,dc=com". This is useful if you are creating multiple domains.
|
||||
.TP
|
||||
-z
|
||||
This is the name of the zone specified in the SOA record.
|
||||
.SH EXAMPLES
|
||||
Following are brief examples of how to import a zone file into your LDAP DIT.
|
||||
.SS Loading zone domain.com, with an LDAP Base DN of dc=domain,dc=com
|
||||
zone2ldap -D dc=root -w secret -h localhost -z domain.com -f domain.com.zone
|
||||
|
||||
This will add Resource Records into an ALREADY EXISTING dc=domain,dc=com. The final SOA DN in this case, will be
|
||||
dc=@,dc=domain,dc=com
|
||||
|
||||
.SS Loading customer.com, if your LDAP Base DN is dc=provider,dc=net.
|
||||
zone2ldap -D dc=root -w secret -h localhost -z customer.com -b dc=provider,dc=net -f customer.com.zone -c
|
||||
|
||||
This will create dc=customer,dc=com under dc=provider,dc=net, and add all necessary Resource Records. The final
|
||||
root DN to the SOA will be dc=@,dc=customer,dc=com,dc=provider,dc=net.
|
||||
|
||||
|
||||
.SH "SEE ALSO"
|
||||
named(8) ldap(3)
|
||||
.SH "BUGS"
|
||||
Send all bug reports to Jeff McNeil <jeffmcneil@mindspring.com>.
|
||||
.SH AUTHOR
|
||||
Jeff McNeil <jmcneil@interland.com>
|
||||
|
||||
677
contrib/sdb/ldap/zone2ldap.c
Normal file
677
contrib/sdb/ldap/zone2ldap.c
Normal file
|
|
@ -0,0 +1,677 @@
|
|||
/*
|
||||
* Copyright (C) 2001 Jeff McNeil <jeffmcneil@mindspring.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/result.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#include <dns/dbiterator.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdatasetiter.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/rdatatype.h>
|
||||
|
||||
#include <ldap.h>
|
||||
|
||||
#define DNS_OBJECT 5
|
||||
#define DNS_TOP 2
|
||||
|
||||
#define VERSION "0.2-ALPHA"
|
||||
|
||||
typedef struct LDAP_INFO
|
||||
{
|
||||
char *dn;
|
||||
LDAPMod **attrs;
|
||||
struct LDAP_INFO *next;
|
||||
int attrcnt;
|
||||
}
|
||||
ldap_info;
|
||||
|
||||
/* usage Info */
|
||||
void usage ();
|
||||
|
||||
/* Add to the ldap dit */
|
||||
void add_ldap_values (ldap_info * ldinfo);
|
||||
|
||||
/* Init an ldap connection */
|
||||
void init_ldap_conn ();
|
||||
|
||||
/* Ldap error checking */
|
||||
void ldap_result_check (char *msg, char *dn, int err);
|
||||
|
||||
/* Put a hostname into a char ** array */
|
||||
char **hostname_to_dn_list (char *hostname, char *zone, unsigned int flags);
|
||||
|
||||
/* Find out how many items are in a char ** array */
|
||||
int get_attr_list_size (char **tmp);
|
||||
|
||||
/* Get a DN */
|
||||
char *build_dn_from_dc_list (char **dc_list, unsigned int ttl);
|
||||
|
||||
/* Add to RR list */
|
||||
void add_to_rr_list (char *dn, char *name, char *type, char *data,
|
||||
unsigned int ttl, unsigned int flags);
|
||||
|
||||
/* Error checking */
|
||||
void isc_result_check (isc_result_t res, char *errorstr);
|
||||
|
||||
/* Generate LDIF Format files */
|
||||
void generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata,
|
||||
unsigned int ttl);
|
||||
|
||||
/* head pointer to the list */
|
||||
ldap_info *ldap_info_base = NULL;
|
||||
|
||||
char *argzone, *ldapbase, *binddn, *bindpw = NULL;
|
||||
char *ldapsystem = "localhost";
|
||||
static char *objectClasses[] =
|
||||
{ "top", "domain", "dNSDomain", "dNSDomain2", NULL };
|
||||
static char *topObjectClasses[] = { "top", NULL };
|
||||
LDAP *conn;
|
||||
unsigned int debug = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
debug = 1;
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int *argc, char **argv)
|
||||
{
|
||||
isc_mem_t *isc_ctx = NULL;
|
||||
isc_result_t result;
|
||||
char *basedn;
|
||||
ldap_info *tmp;
|
||||
LDAPMod *base_attrs[2];
|
||||
LDAPMod base;
|
||||
isc_buffer_t buff;
|
||||
char *zonefile;
|
||||
char fullbasedn[1024];
|
||||
char *ctmp;
|
||||
dns_fixedname_t fixedzone, fixedname;
|
||||
dns_rdataset_t rdataset;
|
||||
char **dc_list;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdatasetiter_t *riter;
|
||||
dns_name_t *zone, *name;
|
||||
dns_db_t *db = NULL;
|
||||
dns_dbiterator_t *dbit = NULL;
|
||||
dns_dbnode_t *node;
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
int create_base = 0;
|
||||
int topt;
|
||||
|
||||
if ((int) argc < 2)
|
||||
{
|
||||
usage ();
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
while ((topt = getopt ((int) argc, argv, "D:w:b:z:f:h:?dcv")) != -1)
|
||||
{
|
||||
switch (topt)
|
||||
{
|
||||
case 'v':
|
||||
printf("%s\n", VERSION);
|
||||
exit(0);
|
||||
case 'c':
|
||||
create_base++;
|
||||
break;
|
||||
case 'd':
|
||||
debug++;
|
||||
break;
|
||||
case 'D':
|
||||
binddn = strdup (optarg);
|
||||
break;
|
||||
case 'w':
|
||||
bindpw = strdup (optarg);
|
||||
break;
|
||||
case 'b':
|
||||
ldapbase = strdup (optarg);
|
||||
break;
|
||||
case 'z':
|
||||
argzone = strdup (optarg);
|
||||
break;
|
||||
case 'f':
|
||||
zonefile = strdup (optarg);
|
||||
break;
|
||||
case 'h':
|
||||
ldapsystem = strdup (optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage ();
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((argzone == NULL) || (zonefile == NULL))
|
||||
{
|
||||
usage ();
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
printf ("Initializing ISC Routines, parsing zone file\n");
|
||||
|
||||
result = isc_mem_create (0, 0, &isc_ctx);
|
||||
isc_result_check (result, "isc_mem_create");
|
||||
|
||||
isc_buffer_init (&buff, argzone, strlen (argzone));
|
||||
isc_buffer_add (&buff, strlen (argzone));
|
||||
dns_fixedname_init (&fixedzone);
|
||||
zone = dns_fixedname_name (&fixedzone);
|
||||
result = dns_name_fromtext (zone, &buff, dns_rootname, ISC_FALSE, NULL);
|
||||
isc_result_check (result, "dns_name_fromtext");
|
||||
|
||||
result =
|
||||
dns_db_create (isc_ctx, "rbt", zone, dns_dbtype_zone, dns_rdataclass_in,
|
||||
0, NULL, &db);
|
||||
isc_result_check (result, "dns_db_create");
|
||||
|
||||
result = dns_db_load (db, zonefile);
|
||||
isc_result_check (result, "Check Zone Syntax: dns_db_load");
|
||||
|
||||
result = dns_db_createiterator (db, ISC_FALSE, &dbit);
|
||||
isc_result_check (result, "dns_db_createiterator");
|
||||
|
||||
result = dns_dbiterator_first (dbit);
|
||||
isc_result_check (result, "dns_dbiterator_first");
|
||||
|
||||
dns_fixedname_init (&fixedname);
|
||||
name = dns_fixedname_name (&fixedname);
|
||||
dns_rdataset_init (&rdataset);
|
||||
dns_rdata_init (&rdata);
|
||||
|
||||
while (result == ISC_R_SUCCESS)
|
||||
{
|
||||
node = NULL;
|
||||
result = dns_dbiterator_current (dbit, &node, name);
|
||||
|
||||
if (result == ISC_R_NOMORE)
|
||||
break;
|
||||
|
||||
isc_result_check (result, "dns_dbiterator_current");
|
||||
|
||||
riter = NULL;
|
||||
result = dns_db_allrdatasets (db, node, NULL, 0, &riter);
|
||||
isc_result_check (result, "dns_db_allrdatasets");
|
||||
|
||||
result = dns_rdatasetiter_first (riter);
|
||||
//isc_result_check(result, "dns_rdatasetiter_first");
|
||||
|
||||
while (result == ISC_R_SUCCESS)
|
||||
{
|
||||
dns_rdatasetiter_current (riter, &rdataset);
|
||||
result = dns_rdataset_first (&rdataset);
|
||||
isc_result_check (result, "dns_rdatasetiter_current");
|
||||
|
||||
while (result == ISC_R_SUCCESS)
|
||||
{
|
||||
dns_rdataset_current (&rdataset, &rdata);
|
||||
generate_ldap (name, &rdata, rdataset.ttl);
|
||||
dns_rdata_reset (&rdata);
|
||||
result = dns_rdataset_next (&rdataset);
|
||||
}
|
||||
dns_rdataset_disassociate (&rdataset);
|
||||
result = dns_rdatasetiter_next (riter);
|
||||
|
||||
}
|
||||
dns_rdatasetiter_destroy (&riter);
|
||||
result = dns_dbiterator_next (dbit);
|
||||
|
||||
}
|
||||
|
||||
/* Initialize the LDAP Connection */
|
||||
if (debug)
|
||||
printf ("Initializing LDAP Connection to %s as %s\n", ldapsystem, binddn);
|
||||
|
||||
init_ldap_conn ();
|
||||
|
||||
if (create_base)
|
||||
{
|
||||
if (debug)
|
||||
printf ("Creating base zone DN %s\n", argzone);
|
||||
|
||||
dc_list = hostname_to_dn_list (argzone, argzone, DNS_TOP);
|
||||
basedn = build_dn_from_dc_list (dc_list, 0);
|
||||
for (ctmp = &basedn[strlen (basedn)]; ctmp >= &basedn[0]; ctmp--)
|
||||
{
|
||||
if ((*ctmp == ',') || (ctmp == &basedn[0]))
|
||||
{
|
||||
base.mod_op = LDAP_MOD_ADD;
|
||||
base.mod_type = "objectClass";
|
||||
base.mod_values = topObjectClasses;
|
||||
base_attrs[0] = &base;
|
||||
base_attrs[1] = NULL;
|
||||
|
||||
if (ldapbase)
|
||||
{
|
||||
if (ctmp != &basedn[0])
|
||||
sprintf (fullbasedn, "%s,%s", ctmp + 1, ldapbase);
|
||||
else
|
||||
sprintf (fullbasedn, "%s,%s", ctmp, ldapbase);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctmp != &basedn[0])
|
||||
sprintf (fullbasedn, "%s", ctmp + 1);
|
||||
else
|
||||
sprintf (fullbasedn, "%s", ctmp);
|
||||
}
|
||||
result = ldap_add_s (conn, fullbasedn, base_attrs);
|
||||
ldap_result_check ("intial ldap_add_s", fullbasedn, result);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
printf ("Skipping zone base dn creation for %s\n", argzone);
|
||||
}
|
||||
|
||||
for (tmp = ldap_info_base; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
|
||||
if (debug)
|
||||
printf ("Adding DN: %s\n", tmp->dn);
|
||||
|
||||
add_ldap_values (tmp);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
printf("Operation Complete.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check the status of an isc_result_t after any isc routines.
|
||||
* I should probably rename this function, as not to cause any
|
||||
* confusion with the isc* routines. Will exit on error. */
|
||||
void
|
||||
isc_result_check (isc_result_t res, char *errorstr)
|
||||
{
|
||||
if (res != ISC_R_SUCCESS)
|
||||
{
|
||||
fprintf (stderr, "%s: %s\n", errorstr, isc_result_totext (res));
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Takes DNS information, in bind data structure format, and adds textual
|
||||
* zone information to the LDAP run queue. */
|
||||
void
|
||||
generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, unsigned int ttl)
|
||||
{
|
||||
unsigned char name[DNS_NAME_MAXTEXT + 1];
|
||||
unsigned int len;
|
||||
unsigned char type[20];
|
||||
unsigned char data[2048];
|
||||
char **dc_list;
|
||||
char *dn;
|
||||
|
||||
isc_buffer_t buff;
|
||||
isc_result_t result;
|
||||
|
||||
isc_buffer_init (&buff, name, sizeof (name));
|
||||
result = dns_name_totext (dnsname, ISC_TRUE, &buff);
|
||||
isc_result_check (result, "dns_name_totext");
|
||||
name[isc_buffer_usedlength (&buff)] = 0;
|
||||
|
||||
isc_buffer_init (&buff, type, sizeof (type));
|
||||
result = dns_rdatatype_totext (rdata->type, &buff);
|
||||
isc_result_check (result, "dns_rdatatype_totext");
|
||||
type[isc_buffer_usedlength (&buff)] = 0;
|
||||
|
||||
isc_buffer_init (&buff, data, sizeof (data));
|
||||
result = dns_rdata_totext (rdata, NULL, &buff);
|
||||
isc_result_check (result, "dns_rdata_totext");
|
||||
data[isc_buffer_usedlength (&buff)] = 0;
|
||||
|
||||
dc_list = hostname_to_dn_list (name, argzone, DNS_OBJECT);
|
||||
len = (get_attr_list_size (dc_list) - 2);
|
||||
dn = build_dn_from_dc_list (dc_list, ttl);
|
||||
|
||||
if (debug)
|
||||
printf ("Adding %s (%s %s) to run queue list.\n", dn, type, data);
|
||||
|
||||
add_to_rr_list (dn, dc_list[len], type, data, ttl, DNS_OBJECT);
|
||||
}
|
||||
|
||||
|
||||
/* Locate an item in the Run queue linked list, by DN. Used by functions
|
||||
* which add items to the run queue.
|
||||
*/
|
||||
ldap_info *
|
||||
locate_by_dn (char *dn)
|
||||
{
|
||||
ldap_info *tmp;
|
||||
for (tmp = ldap_info_base; tmp != (ldap_info *) NULL; tmp = tmp->next)
|
||||
{
|
||||
if (!strncmp (tmp->dn, dn, strlen (dn)))
|
||||
return tmp;
|
||||
}
|
||||
return (ldap_info *) NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Take textual zone data, and add to the LDAP Run queue. This works like so:
|
||||
* If locate_by_dn does not return, alloc a new ldap_info structure, and then
|
||||
* calloc a LDAPMod array, fill in the default "everyone needs this" information,
|
||||
* including object classes and dc's. If it locate_by_dn does return, then we'll
|
||||
* realloc for more LDAPMod structs, and appened the new data. If an LDAPMod exists
|
||||
* for the parameter we're adding, then we'll realloc the mod_values array, and
|
||||
* add the new value to the existing LDAPMod. Finnaly, it assures linkage exists
|
||||
* within the Run queue linked ilst*/
|
||||
|
||||
void
|
||||
add_to_rr_list (char *dn, char *name, char *type,
|
||||
char *data, unsigned int ttl, unsigned int flags)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
ldap_info *tmp;
|
||||
int attrlist;
|
||||
char ldap_type_buffer[128];
|
||||
char charttl[64];
|
||||
|
||||
|
||||
if ((tmp = locate_by_dn (dn)) == NULL)
|
||||
{
|
||||
|
||||
/* There wasn't one already there, so we need to allocate a new one,
|
||||
* and stick it on the list */
|
||||
|
||||
tmp = (ldap_info *) malloc (sizeof (ldap_info));
|
||||
if (tmp == (ldap_info *) NULL)
|
||||
{
|
||||
fprintf (stderr, "malloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
tmp->dn = strdup (dn);
|
||||
tmp->attrs = (LDAPMod **) calloc (sizeof (LDAPMod *), flags);
|
||||
if (tmp->attrs == (LDAPMod **) NULL)
|
||||
{
|
||||
fprintf (stderr, "calloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < flags; i++)
|
||||
{
|
||||
tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod));
|
||||
if (tmp->attrs[i] == (LDAPMod *) NULL)
|
||||
{
|
||||
fprintf (stderr, "malloc: %s\n", strerror (errno));
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
tmp->attrs[0]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[0]->mod_type = "objectClass";
|
||||
|
||||
if (flags == DNS_OBJECT)
|
||||
tmp->attrs[0]->mod_values = objectClasses;
|
||||
else
|
||||
{
|
||||
tmp->attrs[0]->mod_values = topObjectClasses;
|
||||
tmp->attrs[1] = NULL;
|
||||
tmp->attrcnt = 2;
|
||||
tmp->next = ldap_info_base;
|
||||
ldap_info_base = tmp;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
tmp->attrs[1]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[1]->mod_type = "dc";
|
||||
tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 2);
|
||||
tmp->attrs[1]->mod_values[0] = strdup (name);
|
||||
tmp->attrs[1]->mod_values[2] = NULL;
|
||||
|
||||
sprintf (ldap_type_buffer, "%sRecord", type);
|
||||
|
||||
tmp->attrs[2]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[2]->mod_type = strdup (ldap_type_buffer);
|
||||
tmp->attrs[2]->mod_values = (char **) calloc (sizeof (char *), 2);
|
||||
tmp->attrs[2]->mod_values[0] = strdup (data);
|
||||
tmp->attrs[2]->mod_values[1] = NULL;
|
||||
|
||||
tmp->attrs[3]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[3]->mod_type = "dNSTTL";
|
||||
tmp->attrs[3]->mod_values = (char **) calloc (sizeof (char *), 2);
|
||||
sprintf (charttl, "%d", ttl);
|
||||
tmp->attrs[3]->mod_values[0] = strdup (charttl);
|
||||
tmp->attrs[3]->mod_values[1] = NULL;
|
||||
|
||||
|
||||
tmp->attrs[4] = NULL;
|
||||
tmp->attrcnt = flags;
|
||||
tmp->next = ldap_info_base;
|
||||
ldap_info_base = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (i = 0; tmp->attrs[i] != NULL; i++)
|
||||
{
|
||||
sprintf (ldap_type_buffer, "%sRecord", type);
|
||||
if (!strncmp
|
||||
(ldap_type_buffer, tmp->attrs[i]->mod_type,
|
||||
strlen (tmp->attrs[i]->mod_type)))
|
||||
{
|
||||
attrlist = get_attr_list_size (tmp->attrs[i]->mod_values);
|
||||
tmp->attrs[i]->mod_values =
|
||||
(char **) realloc (tmp->attrs[i]->mod_values,
|
||||
sizeof (char *) * (attrlist + 1));
|
||||
|
||||
if (tmp->attrs[i]->mod_values == (char **) NULL)
|
||||
{
|
||||
fprintf (stderr, "realloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
for (x = 0; tmp->attrs[i]->mod_values[x] != NULL; x++);
|
||||
|
||||
tmp->attrs[i]->mod_values[x] = strdup (data);
|
||||
tmp->attrs[i]->mod_values[x + 1] = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
tmp->attrs =
|
||||
(LDAPMod **) realloc (tmp->attrs,
|
||||
sizeof (LDAPMod) * ++(tmp->attrcnt));
|
||||
if (tmp->attrs == NULL)
|
||||
{
|
||||
fprintf (stderr, "realloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
for (x = 0; tmp->attrs[x] != NULL; x++);
|
||||
tmp->attrs[x] = (LDAPMod *) malloc (sizeof (LDAPMod));
|
||||
tmp->attrs[x]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[x]->mod_type = strdup (ldap_type_buffer);
|
||||
tmp->attrs[x]->mod_values = (char **) calloc (sizeof (char *), 2);
|
||||
tmp->attrs[x]->mod_values[0] = strdup (data);
|
||||
tmp->attrs[x]->mod_values[1] = NULL;
|
||||
tmp->attrs[x + 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Size of a mod_values list, plus the terminating NULL field. */
|
||||
int
|
||||
get_attr_list_size (char **tmp)
|
||||
{
|
||||
int i = 0;
|
||||
char **ftmp = tmp;
|
||||
while (*ftmp != NULL)
|
||||
{
|
||||
i++;
|
||||
ftmp++;
|
||||
}
|
||||
return ++i;
|
||||
}
|
||||
|
||||
|
||||
/* take a hostname, and split it into a char ** of the dc parts,
|
||||
* example, we have www.domain.com, this function will return:
|
||||
* array[0] = com, array[1] = domain, array[2] = www. */
|
||||
|
||||
char **
|
||||
hostname_to_dn_list (char *hostname, char *zone, unsigned int flags)
|
||||
{
|
||||
char *tmp;
|
||||
static char *dn_buffer[64];
|
||||
int i = 0;
|
||||
char *zname;
|
||||
char *hnamebuff;
|
||||
|
||||
zname = strdup (hostname);
|
||||
|
||||
if (flags == DNS_OBJECT)
|
||||
{
|
||||
|
||||
if (strlen (zname) != strlen (zone))
|
||||
{
|
||||
tmp = &zname[strlen (zname) - strlen (zone)];
|
||||
*--tmp = '\0';
|
||||
hnamebuff = strdup (zname);
|
||||
zname = ++tmp;
|
||||
}
|
||||
else
|
||||
hnamebuff = "@";
|
||||
}
|
||||
else
|
||||
{
|
||||
zname = zone;
|
||||
hnamebuff = NULL;
|
||||
}
|
||||
|
||||
for (tmp = strrchr (zname, '.'); tmp != (char *) 0;
|
||||
tmp = strrchr (zname, '.'))
|
||||
{
|
||||
*tmp++ = '\0';
|
||||
dn_buffer[i++] = tmp;
|
||||
}
|
||||
dn_buffer[i++] = zname;
|
||||
dn_buffer[i++] = hnamebuff;
|
||||
dn_buffer[i] = NULL;
|
||||
|
||||
return dn_buffer;
|
||||
}
|
||||
|
||||
|
||||
/* build an sdb compatible LDAP DN from a "dc_list" (char **).
|
||||
* will append dNSTTL information to each RR Record, with the
|
||||
* exception of "@"/SOA. */
|
||||
|
||||
char *
|
||||
build_dn_from_dc_list (char **dc_list, unsigned int ttl)
|
||||
{
|
||||
int size;
|
||||
int x;
|
||||
static char dn[1024];
|
||||
char tmp[128];
|
||||
|
||||
bzero (tmp, sizeof (tmp));
|
||||
bzero (dn, sizeof (dn));
|
||||
size = get_attr_list_size (dc_list);
|
||||
for (x = size - 2; x > 0; x--)
|
||||
{
|
||||
if (x == (size - 2) && (strncmp (dc_list[x], "@", 1)) && (ttl))
|
||||
sprintf (tmp, "dc=%s + dNSTTL=%d,", dc_list[x], ttl);
|
||||
else
|
||||
sprintf (tmp, "dc=%s,", dc_list[x]);
|
||||
|
||||
strncat (dn, tmp, sizeof (dn) - strlen (dn));
|
||||
}
|
||||
|
||||
sprintf (tmp, "dc=%s", dc_list[0]);
|
||||
strncat (dn, tmp, sizeof (dn) - strlen (dn));
|
||||
|
||||
return dn;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize LDAP Conn */
|
||||
void
|
||||
init_ldap_conn ()
|
||||
{
|
||||
int result;
|
||||
conn = ldap_open (ldapsystem, LDAP_PORT);
|
||||
if (conn == NULL)
|
||||
{
|
||||
fprintf (stderr, "Error opening Ldap connection: %s\n",
|
||||
strerror (errno));
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
result = ldap_simple_bind_s (conn, binddn, bindpw);
|
||||
ldap_result_check ("ldap_simple_bind_s", "LDAP Bind", result);
|
||||
}
|
||||
|
||||
/* Like isc_result_check, only for LDAP */
|
||||
void
|
||||
ldap_result_check (char *msg, char *dn, int err)
|
||||
{
|
||||
if ((err != LDAP_SUCCESS) && (err != LDAP_ALREADY_EXISTS))
|
||||
{
|
||||
ldap_perror (conn, dn);
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* For running the ldap_info run queue. */
|
||||
void
|
||||
add_ldap_values (ldap_info * ldinfo)
|
||||
{
|
||||
int result;
|
||||
char dnbuffer[1024];
|
||||
|
||||
|
||||
if (ldapbase != NULL)
|
||||
sprintf (dnbuffer, "%s,%s", ldinfo->dn, ldapbase);
|
||||
else
|
||||
sprintf (dnbuffer, "%s", ldinfo->dn);
|
||||
|
||||
result = ldap_add_s (conn, dnbuffer, ldinfo->attrs);
|
||||
ldap_result_check ("ldap_add_s", dnbuffer, result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* name says it all */
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
fprintf (stderr,
|
||||
"zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST]
|
||||
[-c Create LDAP Base structure][-d Debug Output (lots !)] \n ");}
|
||||
304
contrib/sdb/ldapdb.c
Normal file
304
contrib/sdb/ldapdb.c
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
* Copyright (C) 2001 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/sdb.h>
|
||||
|
||||
#include <named/globals.h>
|
||||
|
||||
#include <ldap.h>
|
||||
#include "ldapdb.h"
|
||||
|
||||
/*
|
||||
* A simple database driver for LDAP. Not production quality yet.
|
||||
*/
|
||||
|
||||
static dns_sdbimplementation_t *ldapdb = NULL;
|
||||
|
||||
struct ldapdb_data {
|
||||
char *hostname;
|
||||
int portno;
|
||||
char *base;
|
||||
int defaultttl;
|
||||
LDAP *ld;
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
ldapdb_create(const char *zone, int argc, char **argv,
|
||||
void *driverdata, void **dbdata)
|
||||
{
|
||||
struct ldapdb_data *data;
|
||||
char *s;
|
||||
int defaultttl;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(driverdata);
|
||||
|
||||
if ((argc < 2)
|
||||
|| (argv[0] != strstr( argv[0], "ldap://"))
|
||||
|| ((defaultttl = atoi(argv[1])) < 1))
|
||||
return (ISC_R_FAILURE);
|
||||
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) {
|
||||
isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
data->defaultttl = defaultttl;
|
||||
s = strchr(data->hostname, '/');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
data->base = *s != '\0' ? s : NULL;
|
||||
}
|
||||
s = strchr(data->hostname, ':');
|
||||
if (s != NULL) {
|
||||
*s++ = '\0';
|
||||
data->portno = atoi(s);
|
||||
} else
|
||||
data->portno = LDAP_PORT;
|
||||
data->ld = NULL;
|
||||
*dbdata = data;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
ldapdb_destroy(const char *zone, void *driverdata, void **dbdata) {
|
||||
struct ldapdb_data *data = *dbdata;
|
||||
|
||||
UNUSED(zone);
|
||||
UNUSED(driverdata);
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
if (data->ld != NULL)
|
||||
ldap_unbind(data->ld);
|
||||
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)
|
||||
{
|
||||
if (data->ld != NULL)
|
||||
ldap_unbind(data->ld);
|
||||
data->ld = ldap_open(data->hostname, data->portno);
|
||||
if (data->ld == NULL)
|
||||
return;
|
||||
if (ldap_simple_bind_s(data->ld, NULL, NULL) != LDAP_SUCCESS) {
|
||||
ldap_unbind(data->ld);
|
||||
data->ld = 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;
|
||||
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)
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
fltr = isc_mem_get(ns_g_mctx, strlen(name) + strlen("(dc=)") + 1);
|
||||
if (fltr == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
strcpy(fltr, "(dc=");
|
||||
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);
|
||||
}
|
||||
isc_mem_put(ns_g_mctx, fltr, strlen(fltr) + 1);
|
||||
if (data->ld == NULL)
|
||||
goto exit;
|
||||
|
||||
for (e = ldap_first_entry(data->ld, res); e != NULL;
|
||||
e = ldap_next_entry(data->ld, e)) {
|
||||
LDAP *ld = data->ld;
|
||||
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;
|
||||
LDAPMessage *res, *e;
|
||||
char type[64];
|
||||
char *a, **vals;
|
||||
BerElement *ptr;
|
||||
int i;
|
||||
|
||||
UNUSED(zone);
|
||||
|
||||
if (data->ld == NULL) {
|
||||
ldapdb_bind(data);
|
||||
if (data->ld == 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);
|
||||
}
|
||||
|
||||
for (e = ldap_first_entry(data->ld, res); e != NULL;
|
||||
e = ldap_next_entry(data->ld, e)) {
|
||||
LDAP *ld = data->ld;
|
||||
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, "dc")) {
|
||||
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);
|
||||
}
|
||||
|
||||
static dns_sdbmethods_t ldapdb_methods = {
|
||||
ldapdb_lookup,
|
||||
NULL, /* authority */
|
||||
ldapdb_allnodes,
|
||||
ldapdb_create,
|
||||
ldapdb_destroy
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapper around dns_sdb_register().
|
||||
*/
|
||||
isc_result_t
|
||||
ldapdb_init(void) {
|
||||
unsigned int flags;
|
||||
flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
|
||||
return (dns_sdb_register("ldap", &ldapdb_methods, NULL, flags,
|
||||
ns_g_mctx, &ldapdb));
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper around dns_sdb_unregister().
|
||||
*/
|
||||
void
|
||||
ldapdb_clear(void) {
|
||||
if (ldapdb != NULL)
|
||||
dns_sdb_unregister(&ldapdb);
|
||||
}
|
||||
6
contrib/sdb/ldapdb.h
Normal file
6
contrib/sdb/ldapdb.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include <isc/types.h>
|
||||
|
||||
isc_result_t ldapdb_init(void);
|
||||
|
||||
void ldapdb_clear(void);
|
||||
|
||||
64
contrib/sdb/zone2ldap.1
Normal file
64
contrib/sdb/zone2ldap.1
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
.TH zone2ldap 1 "8 March 2001"
|
||||
.SH NAME
|
||||
zone2ldap /- Load BIND 9 Zone files into LDAP Directory
|
||||
.SH SYNOPSIS
|
||||
zone2ldap [-D Bind DN] [-w Bind Password] [-b Base DN] [-z Zone] [-f Zone File ] [-h Ldap Host] [-cd] [-v]
|
||||
.SH DESCRIPTION
|
||||
zone2ldap will parse a complete BIND 9 format DNS zone file, and load
|
||||
the contents into an LDAP directory, for use with the LDAP sdb back-end.
|
||||
|
||||
If the zone already exists, zone2ldap will exit succesfully. If the zone does not exists, or
|
||||
partially exists, zone2ldap will attempt to add all/missing zone data.
|
||||
|
||||
.SS Options
|
||||
.TP
|
||||
-b
|
||||
LDAP Base DN. LDAP systems require a "base dn", which is generally considered the LDAP Directory root.
|
||||
If the zone you are loading is different from the base, then you will need to tell zone2ldap what your LDAP
|
||||
base is.
|
||||
.TP
|
||||
-v
|
||||
Print version information, and immediatly exit.
|
||||
.TP
|
||||
-f
|
||||
Zone file. Bind 9.1 compatible zone file, from which zone information will be read.
|
||||
.TP
|
||||
-d
|
||||
Dump debug information to standard out.
|
||||
.TP
|
||||
-w
|
||||
LDAP Bind password, corresponding the the value of "-b".
|
||||
.TP
|
||||
-h
|
||||
LDAP Directory host. This is the hostname of the LDAP system you wish to store zone information on.
|
||||
An LDAP server should be listening on port 389 of the target system. This may be ommited, and will default
|
||||
to "localhost".
|
||||
.TP
|
||||
-c
|
||||
This will create the zone portion of the DN you are importing. For instance, if you are creating a domain.com zone,
|
||||
zone2ldap should first create "dc=domain,dc=com". This is useful if you are creating multiple domains.
|
||||
.TP
|
||||
-z
|
||||
This is the name of the zone specified in the SOA record.
|
||||
.SH EXAMPLES
|
||||
Following are brief examples of how to import a zone file into your LDAP DIT.
|
||||
.SS Loading zone domain.com, with an LDAP Base DN of dc=domain,dc=com
|
||||
zone2ldap -D dc=root -w secret -h localhost -z domain.com -f domain.com.zone
|
||||
|
||||
This will add Resource Records into an ALREADY EXISTING dc=domain,dc=com. The final SOA DN in this case, will be
|
||||
dc=@,dc=domain,dc=com
|
||||
|
||||
.SS Loading customer.com, if your LDAP Base DN is dc=provider,dc=net.
|
||||
zone2ldap -D dc=root -w secret -h localhost -z customer.com -b dc=provider,dc=net -f customer.com.zone -c
|
||||
|
||||
This will create dc=customer,dc=com under dc=provider,dc=net, and add all necessary Resource Records. The final
|
||||
root DN to the SOA will be dc=@,dc=customer,dc=com,dc=provider,dc=net.
|
||||
|
||||
|
||||
.SH "SEE ALSO"
|
||||
named(8) ldap(3)
|
||||
.SH "BUGS"
|
||||
Send all bug reports to Jeff McNeil <jeffmcneil@mindspring.com>.
|
||||
.SH AUTHOR
|
||||
Jeff McNeil <jmcneil@interland.com>
|
||||
|
||||
677
contrib/sdb/zone2ldap.c
Normal file
677
contrib/sdb/zone2ldap.c
Normal file
|
|
@ -0,0 +1,677 @@
|
|||
/*
|
||||
* Copyright (C) 2001 Jeff McNeil <jeffmcneil@mindspring.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/result.h>
|
||||
|
||||
#include <dns/db.h>
|
||||
#include <dns/dbiterator.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdatasetiter.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/rdatatype.h>
|
||||
|
||||
#include <ldap.h>
|
||||
|
||||
#define DNS_OBJECT 5
|
||||
#define DNS_TOP 2
|
||||
|
||||
#define VERSION "0.2-ALPHA"
|
||||
|
||||
typedef struct LDAP_INFO
|
||||
{
|
||||
char *dn;
|
||||
LDAPMod **attrs;
|
||||
struct LDAP_INFO *next;
|
||||
int attrcnt;
|
||||
}
|
||||
ldap_info;
|
||||
|
||||
/* usage Info */
|
||||
void usage ();
|
||||
|
||||
/* Add to the ldap dit */
|
||||
void add_ldap_values (ldap_info * ldinfo);
|
||||
|
||||
/* Init an ldap connection */
|
||||
void init_ldap_conn ();
|
||||
|
||||
/* Ldap error checking */
|
||||
void ldap_result_check (char *msg, char *dn, int err);
|
||||
|
||||
/* Put a hostname into a char ** array */
|
||||
char **hostname_to_dn_list (char *hostname, char *zone, unsigned int flags);
|
||||
|
||||
/* Find out how many items are in a char ** array */
|
||||
int get_attr_list_size (char **tmp);
|
||||
|
||||
/* Get a DN */
|
||||
char *build_dn_from_dc_list (char **dc_list, unsigned int ttl);
|
||||
|
||||
/* Add to RR list */
|
||||
void add_to_rr_list (char *dn, char *name, char *type, char *data,
|
||||
unsigned int ttl, unsigned int flags);
|
||||
|
||||
/* Error checking */
|
||||
void isc_result_check (isc_result_t res, char *errorstr);
|
||||
|
||||
/* Generate LDIF Format files */
|
||||
void generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata,
|
||||
unsigned int ttl);
|
||||
|
||||
/* head pointer to the list */
|
||||
ldap_info *ldap_info_base = NULL;
|
||||
|
||||
char *argzone, *ldapbase, *binddn, *bindpw = NULL;
|
||||
char *ldapsystem = "localhost";
|
||||
static char *objectClasses[] =
|
||||
{ "top", "domain", "dNSDomain", "dNSDomain2", NULL };
|
||||
static char *topObjectClasses[] = { "top", NULL };
|
||||
LDAP *conn;
|
||||
unsigned int debug = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
debug = 1;
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int *argc, char **argv)
|
||||
{
|
||||
isc_mem_t *isc_ctx = NULL;
|
||||
isc_result_t result;
|
||||
char *basedn;
|
||||
ldap_info *tmp;
|
||||
LDAPMod *base_attrs[2];
|
||||
LDAPMod base;
|
||||
isc_buffer_t buff;
|
||||
char *zonefile;
|
||||
char fullbasedn[1024];
|
||||
char *ctmp;
|
||||
dns_fixedname_t fixedzone, fixedname;
|
||||
dns_rdataset_t rdataset;
|
||||
char **dc_list;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dns_rdatasetiter_t *riter;
|
||||
dns_name_t *zone, *name;
|
||||
dns_db_t *db = NULL;
|
||||
dns_dbiterator_t *dbit = NULL;
|
||||
dns_dbnode_t *node;
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
int create_base = 0;
|
||||
int topt;
|
||||
|
||||
if ((int) argc < 2)
|
||||
{
|
||||
usage ();
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
while ((topt = getopt ((int) argc, argv, "D:w:b:z:f:h:?dcv")) != -1)
|
||||
{
|
||||
switch (topt)
|
||||
{
|
||||
case 'v':
|
||||
printf("%s\n", VERSION);
|
||||
exit(0);
|
||||
case 'c':
|
||||
create_base++;
|
||||
break;
|
||||
case 'd':
|
||||
debug++;
|
||||
break;
|
||||
case 'D':
|
||||
binddn = strdup (optarg);
|
||||
break;
|
||||
case 'w':
|
||||
bindpw = strdup (optarg);
|
||||
break;
|
||||
case 'b':
|
||||
ldapbase = strdup (optarg);
|
||||
break;
|
||||
case 'z':
|
||||
argzone = strdup (optarg);
|
||||
break;
|
||||
case 'f':
|
||||
zonefile = strdup (optarg);
|
||||
break;
|
||||
case 'h':
|
||||
ldapsystem = strdup (optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage ();
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((argzone == NULL) || (zonefile == NULL))
|
||||
{
|
||||
usage ();
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
printf ("Initializing ISC Routines, parsing zone file\n");
|
||||
|
||||
result = isc_mem_create (0, 0, &isc_ctx);
|
||||
isc_result_check (result, "isc_mem_create");
|
||||
|
||||
isc_buffer_init (&buff, argzone, strlen (argzone));
|
||||
isc_buffer_add (&buff, strlen (argzone));
|
||||
dns_fixedname_init (&fixedzone);
|
||||
zone = dns_fixedname_name (&fixedzone);
|
||||
result = dns_name_fromtext (zone, &buff, dns_rootname, ISC_FALSE, NULL);
|
||||
isc_result_check (result, "dns_name_fromtext");
|
||||
|
||||
result =
|
||||
dns_db_create (isc_ctx, "rbt", zone, dns_dbtype_zone, dns_rdataclass_in,
|
||||
0, NULL, &db);
|
||||
isc_result_check (result, "dns_db_create");
|
||||
|
||||
result = dns_db_load (db, zonefile);
|
||||
isc_result_check (result, "Check Zone Syntax: dns_db_load");
|
||||
|
||||
result = dns_db_createiterator (db, ISC_FALSE, &dbit);
|
||||
isc_result_check (result, "dns_db_createiterator");
|
||||
|
||||
result = dns_dbiterator_first (dbit);
|
||||
isc_result_check (result, "dns_dbiterator_first");
|
||||
|
||||
dns_fixedname_init (&fixedname);
|
||||
name = dns_fixedname_name (&fixedname);
|
||||
dns_rdataset_init (&rdataset);
|
||||
dns_rdata_init (&rdata);
|
||||
|
||||
while (result == ISC_R_SUCCESS)
|
||||
{
|
||||
node = NULL;
|
||||
result = dns_dbiterator_current (dbit, &node, name);
|
||||
|
||||
if (result == ISC_R_NOMORE)
|
||||
break;
|
||||
|
||||
isc_result_check (result, "dns_dbiterator_current");
|
||||
|
||||
riter = NULL;
|
||||
result = dns_db_allrdatasets (db, node, NULL, 0, &riter);
|
||||
isc_result_check (result, "dns_db_allrdatasets");
|
||||
|
||||
result = dns_rdatasetiter_first (riter);
|
||||
//isc_result_check(result, "dns_rdatasetiter_first");
|
||||
|
||||
while (result == ISC_R_SUCCESS)
|
||||
{
|
||||
dns_rdatasetiter_current (riter, &rdataset);
|
||||
result = dns_rdataset_first (&rdataset);
|
||||
isc_result_check (result, "dns_rdatasetiter_current");
|
||||
|
||||
while (result == ISC_R_SUCCESS)
|
||||
{
|
||||
dns_rdataset_current (&rdataset, &rdata);
|
||||
generate_ldap (name, &rdata, rdataset.ttl);
|
||||
dns_rdata_reset (&rdata);
|
||||
result = dns_rdataset_next (&rdataset);
|
||||
}
|
||||
dns_rdataset_disassociate (&rdataset);
|
||||
result = dns_rdatasetiter_next (riter);
|
||||
|
||||
}
|
||||
dns_rdatasetiter_destroy (&riter);
|
||||
result = dns_dbiterator_next (dbit);
|
||||
|
||||
}
|
||||
|
||||
/* Initialize the LDAP Connection */
|
||||
if (debug)
|
||||
printf ("Initializing LDAP Connection to %s as %s\n", ldapsystem, binddn);
|
||||
|
||||
init_ldap_conn ();
|
||||
|
||||
if (create_base)
|
||||
{
|
||||
if (debug)
|
||||
printf ("Creating base zone DN %s\n", argzone);
|
||||
|
||||
dc_list = hostname_to_dn_list (argzone, argzone, DNS_TOP);
|
||||
basedn = build_dn_from_dc_list (dc_list, 0);
|
||||
for (ctmp = &basedn[strlen (basedn)]; ctmp >= &basedn[0]; ctmp--)
|
||||
{
|
||||
if ((*ctmp == ',') || (ctmp == &basedn[0]))
|
||||
{
|
||||
base.mod_op = LDAP_MOD_ADD;
|
||||
base.mod_type = "objectClass";
|
||||
base.mod_values = topObjectClasses;
|
||||
base_attrs[0] = &base;
|
||||
base_attrs[1] = NULL;
|
||||
|
||||
if (ldapbase)
|
||||
{
|
||||
if (ctmp != &basedn[0])
|
||||
sprintf (fullbasedn, "%s,%s", ctmp + 1, ldapbase);
|
||||
else
|
||||
sprintf (fullbasedn, "%s,%s", ctmp, ldapbase);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctmp != &basedn[0])
|
||||
sprintf (fullbasedn, "%s", ctmp + 1);
|
||||
else
|
||||
sprintf (fullbasedn, "%s", ctmp);
|
||||
}
|
||||
result = ldap_add_s (conn, fullbasedn, base_attrs);
|
||||
ldap_result_check ("intial ldap_add_s", fullbasedn, result);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
printf ("Skipping zone base dn creation for %s\n", argzone);
|
||||
}
|
||||
|
||||
for (tmp = ldap_info_base; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
|
||||
if (debug)
|
||||
printf ("Adding DN: %s\n", tmp->dn);
|
||||
|
||||
add_ldap_values (tmp);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
printf("Operation Complete.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check the status of an isc_result_t after any isc routines.
|
||||
* I should probably rename this function, as not to cause any
|
||||
* confusion with the isc* routines. Will exit on error. */
|
||||
void
|
||||
isc_result_check (isc_result_t res, char *errorstr)
|
||||
{
|
||||
if (res != ISC_R_SUCCESS)
|
||||
{
|
||||
fprintf (stderr, "%s: %s\n", errorstr, isc_result_totext (res));
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Takes DNS information, in bind data structure format, and adds textual
|
||||
* zone information to the LDAP run queue. */
|
||||
void
|
||||
generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, unsigned int ttl)
|
||||
{
|
||||
unsigned char name[DNS_NAME_MAXTEXT + 1];
|
||||
unsigned int len;
|
||||
unsigned char type[20];
|
||||
unsigned char data[2048];
|
||||
char **dc_list;
|
||||
char *dn;
|
||||
|
||||
isc_buffer_t buff;
|
||||
isc_result_t result;
|
||||
|
||||
isc_buffer_init (&buff, name, sizeof (name));
|
||||
result = dns_name_totext (dnsname, ISC_TRUE, &buff);
|
||||
isc_result_check (result, "dns_name_totext");
|
||||
name[isc_buffer_usedlength (&buff)] = 0;
|
||||
|
||||
isc_buffer_init (&buff, type, sizeof (type));
|
||||
result = dns_rdatatype_totext (rdata->type, &buff);
|
||||
isc_result_check (result, "dns_rdatatype_totext");
|
||||
type[isc_buffer_usedlength (&buff)] = 0;
|
||||
|
||||
isc_buffer_init (&buff, data, sizeof (data));
|
||||
result = dns_rdata_totext (rdata, NULL, &buff);
|
||||
isc_result_check (result, "dns_rdata_totext");
|
||||
data[isc_buffer_usedlength (&buff)] = 0;
|
||||
|
||||
dc_list = hostname_to_dn_list (name, argzone, DNS_OBJECT);
|
||||
len = (get_attr_list_size (dc_list) - 2);
|
||||
dn = build_dn_from_dc_list (dc_list, ttl);
|
||||
|
||||
if (debug)
|
||||
printf ("Adding %s (%s %s) to run queue list.\n", dn, type, data);
|
||||
|
||||
add_to_rr_list (dn, dc_list[len], type, data, ttl, DNS_OBJECT);
|
||||
}
|
||||
|
||||
|
||||
/* Locate an item in the Run queue linked list, by DN. Used by functions
|
||||
* which add items to the run queue.
|
||||
*/
|
||||
ldap_info *
|
||||
locate_by_dn (char *dn)
|
||||
{
|
||||
ldap_info *tmp;
|
||||
for (tmp = ldap_info_base; tmp != (ldap_info *) NULL; tmp = tmp->next)
|
||||
{
|
||||
if (!strncmp (tmp->dn, dn, strlen (dn)))
|
||||
return tmp;
|
||||
}
|
||||
return (ldap_info *) NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Take textual zone data, and add to the LDAP Run queue. This works like so:
|
||||
* If locate_by_dn does not return, alloc a new ldap_info structure, and then
|
||||
* calloc a LDAPMod array, fill in the default "everyone needs this" information,
|
||||
* including object classes and dc's. If it locate_by_dn does return, then we'll
|
||||
* realloc for more LDAPMod structs, and appened the new data. If an LDAPMod exists
|
||||
* for the parameter we're adding, then we'll realloc the mod_values array, and
|
||||
* add the new value to the existing LDAPMod. Finnaly, it assures linkage exists
|
||||
* within the Run queue linked ilst*/
|
||||
|
||||
void
|
||||
add_to_rr_list (char *dn, char *name, char *type,
|
||||
char *data, unsigned int ttl, unsigned int flags)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
ldap_info *tmp;
|
||||
int attrlist;
|
||||
char ldap_type_buffer[128];
|
||||
char charttl[64];
|
||||
|
||||
|
||||
if ((tmp = locate_by_dn (dn)) == NULL)
|
||||
{
|
||||
|
||||
/* There wasn't one already there, so we need to allocate a new one,
|
||||
* and stick it on the list */
|
||||
|
||||
tmp = (ldap_info *) malloc (sizeof (ldap_info));
|
||||
if (tmp == (ldap_info *) NULL)
|
||||
{
|
||||
fprintf (stderr, "malloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
tmp->dn = strdup (dn);
|
||||
tmp->attrs = (LDAPMod **) calloc (sizeof (LDAPMod *), flags);
|
||||
if (tmp->attrs == (LDAPMod **) NULL)
|
||||
{
|
||||
fprintf (stderr, "calloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < flags; i++)
|
||||
{
|
||||
tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod));
|
||||
if (tmp->attrs[i] == (LDAPMod *) NULL)
|
||||
{
|
||||
fprintf (stderr, "malloc: %s\n", strerror (errno));
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
tmp->attrs[0]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[0]->mod_type = "objectClass";
|
||||
|
||||
if (flags == DNS_OBJECT)
|
||||
tmp->attrs[0]->mod_values = objectClasses;
|
||||
else
|
||||
{
|
||||
tmp->attrs[0]->mod_values = topObjectClasses;
|
||||
tmp->attrs[1] = NULL;
|
||||
tmp->attrcnt = 2;
|
||||
tmp->next = ldap_info_base;
|
||||
ldap_info_base = tmp;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
tmp->attrs[1]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[1]->mod_type = "dc";
|
||||
tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 2);
|
||||
tmp->attrs[1]->mod_values[0] = strdup (name);
|
||||
tmp->attrs[1]->mod_values[2] = NULL;
|
||||
|
||||
sprintf (ldap_type_buffer, "%sRecord", type);
|
||||
|
||||
tmp->attrs[2]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[2]->mod_type = strdup (ldap_type_buffer);
|
||||
tmp->attrs[2]->mod_values = (char **) calloc (sizeof (char *), 2);
|
||||
tmp->attrs[2]->mod_values[0] = strdup (data);
|
||||
tmp->attrs[2]->mod_values[1] = NULL;
|
||||
|
||||
tmp->attrs[3]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[3]->mod_type = "dNSTTL";
|
||||
tmp->attrs[3]->mod_values = (char **) calloc (sizeof (char *), 2);
|
||||
sprintf (charttl, "%d", ttl);
|
||||
tmp->attrs[3]->mod_values[0] = strdup (charttl);
|
||||
tmp->attrs[3]->mod_values[1] = NULL;
|
||||
|
||||
|
||||
tmp->attrs[4] = NULL;
|
||||
tmp->attrcnt = flags;
|
||||
tmp->next = ldap_info_base;
|
||||
ldap_info_base = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (i = 0; tmp->attrs[i] != NULL; i++)
|
||||
{
|
||||
sprintf (ldap_type_buffer, "%sRecord", type);
|
||||
if (!strncmp
|
||||
(ldap_type_buffer, tmp->attrs[i]->mod_type,
|
||||
strlen (tmp->attrs[i]->mod_type)))
|
||||
{
|
||||
attrlist = get_attr_list_size (tmp->attrs[i]->mod_values);
|
||||
tmp->attrs[i]->mod_values =
|
||||
(char **) realloc (tmp->attrs[i]->mod_values,
|
||||
sizeof (char *) * (attrlist + 1));
|
||||
|
||||
if (tmp->attrs[i]->mod_values == (char **) NULL)
|
||||
{
|
||||
fprintf (stderr, "realloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
for (x = 0; tmp->attrs[i]->mod_values[x] != NULL; x++);
|
||||
|
||||
tmp->attrs[i]->mod_values[x] = strdup (data);
|
||||
tmp->attrs[i]->mod_values[x + 1] = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
tmp->attrs =
|
||||
(LDAPMod **) realloc (tmp->attrs,
|
||||
sizeof (LDAPMod) * ++(tmp->attrcnt));
|
||||
if (tmp->attrs == NULL)
|
||||
{
|
||||
fprintf (stderr, "realloc: %s\n", strerror (errno));
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
for (x = 0; tmp->attrs[x] != NULL; x++);
|
||||
tmp->attrs[x] = (LDAPMod *) malloc (sizeof (LDAPMod));
|
||||
tmp->attrs[x]->mod_op = LDAP_MOD_ADD;
|
||||
tmp->attrs[x]->mod_type = strdup (ldap_type_buffer);
|
||||
tmp->attrs[x]->mod_values = (char **) calloc (sizeof (char *), 2);
|
||||
tmp->attrs[x]->mod_values[0] = strdup (data);
|
||||
tmp->attrs[x]->mod_values[1] = NULL;
|
||||
tmp->attrs[x + 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Size of a mod_values list, plus the terminating NULL field. */
|
||||
int
|
||||
get_attr_list_size (char **tmp)
|
||||
{
|
||||
int i = 0;
|
||||
char **ftmp = tmp;
|
||||
while (*ftmp != NULL)
|
||||
{
|
||||
i++;
|
||||
ftmp++;
|
||||
}
|
||||
return ++i;
|
||||
}
|
||||
|
||||
|
||||
/* take a hostname, and split it into a char ** of the dc parts,
|
||||
* example, we have www.domain.com, this function will return:
|
||||
* array[0] = com, array[1] = domain, array[2] = www. */
|
||||
|
||||
char **
|
||||
hostname_to_dn_list (char *hostname, char *zone, unsigned int flags)
|
||||
{
|
||||
char *tmp;
|
||||
static char *dn_buffer[64];
|
||||
int i = 0;
|
||||
char *zname;
|
||||
char *hnamebuff;
|
||||
|
||||
zname = strdup (hostname);
|
||||
|
||||
if (flags == DNS_OBJECT)
|
||||
{
|
||||
|
||||
if (strlen (zname) != strlen (zone))
|
||||
{
|
||||
tmp = &zname[strlen (zname) - strlen (zone)];
|
||||
*--tmp = '\0';
|
||||
hnamebuff = strdup (zname);
|
||||
zname = ++tmp;
|
||||
}
|
||||
else
|
||||
hnamebuff = "@";
|
||||
}
|
||||
else
|
||||
{
|
||||
zname = zone;
|
||||
hnamebuff = NULL;
|
||||
}
|
||||
|
||||
for (tmp = strrchr (zname, '.'); tmp != (char *) 0;
|
||||
tmp = strrchr (zname, '.'))
|
||||
{
|
||||
*tmp++ = '\0';
|
||||
dn_buffer[i++] = tmp;
|
||||
}
|
||||
dn_buffer[i++] = zname;
|
||||
dn_buffer[i++] = hnamebuff;
|
||||
dn_buffer[i] = NULL;
|
||||
|
||||
return dn_buffer;
|
||||
}
|
||||
|
||||
|
||||
/* build an sdb compatible LDAP DN from a "dc_list" (char **).
|
||||
* will append dNSTTL information to each RR Record, with the
|
||||
* exception of "@"/SOA. */
|
||||
|
||||
char *
|
||||
build_dn_from_dc_list (char **dc_list, unsigned int ttl)
|
||||
{
|
||||
int size;
|
||||
int x;
|
||||
static char dn[1024];
|
||||
char tmp[128];
|
||||
|
||||
bzero (tmp, sizeof (tmp));
|
||||
bzero (dn, sizeof (dn));
|
||||
size = get_attr_list_size (dc_list);
|
||||
for (x = size - 2; x > 0; x--)
|
||||
{
|
||||
if (x == (size - 2) && (strncmp (dc_list[x], "@", 1)) && (ttl))
|
||||
sprintf (tmp, "dc=%s + dNSTTL=%d,", dc_list[x], ttl);
|
||||
else
|
||||
sprintf (tmp, "dc=%s,", dc_list[x]);
|
||||
|
||||
strncat (dn, tmp, sizeof (dn) - strlen (dn));
|
||||
}
|
||||
|
||||
sprintf (tmp, "dc=%s", dc_list[0]);
|
||||
strncat (dn, tmp, sizeof (dn) - strlen (dn));
|
||||
|
||||
return dn;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize LDAP Conn */
|
||||
void
|
||||
init_ldap_conn ()
|
||||
{
|
||||
int result;
|
||||
conn = ldap_open (ldapsystem, LDAP_PORT);
|
||||
if (conn == NULL)
|
||||
{
|
||||
fprintf (stderr, "Error opening Ldap connection: %s\n",
|
||||
strerror (errno));
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
result = ldap_simple_bind_s (conn, binddn, bindpw);
|
||||
ldap_result_check ("ldap_simple_bind_s", "LDAP Bind", result);
|
||||
}
|
||||
|
||||
/* Like isc_result_check, only for LDAP */
|
||||
void
|
||||
ldap_result_check (char *msg, char *dn, int err)
|
||||
{
|
||||
if ((err != LDAP_SUCCESS) && (err != LDAP_ALREADY_EXISTS))
|
||||
{
|
||||
ldap_perror (conn, dn);
|
||||
ldap_unbind_s (conn);
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* For running the ldap_info run queue. */
|
||||
void
|
||||
add_ldap_values (ldap_info * ldinfo)
|
||||
{
|
||||
int result;
|
||||
char dnbuffer[1024];
|
||||
|
||||
|
||||
if (ldapbase != NULL)
|
||||
sprintf (dnbuffer, "%s,%s", ldinfo->dn, ldapbase);
|
||||
else
|
||||
sprintf (dnbuffer, "%s", ldinfo->dn);
|
||||
|
||||
result = ldap_add_s (conn, dnbuffer, ldinfo->attrs);
|
||||
ldap_result_check ("ldap_add_s", dnbuffer, result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* name says it all */
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
fprintf (stderr,
|
||||
"zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST]
|
||||
[-c Create LDAP Base structure][-d Debug Output (lots !)] \n ");}
|
||||
|
|
@ -763,8 +763,12 @@
|
|||
./contrib/linux/coredump-patch X 2000,2001
|
||||
./contrib/named-bootconf/named-bootconf.sh SH.PORTION 1999,2000,2001
|
||||
./contrib/nanny/nanny.pl PERL 2000,2001
|
||||
./contrib/sdb/INSTALL.ldap X 2001
|
||||
./contrib/sdb/README.ldap X 2001
|
||||
./contrib/sdb/dirdb.c C 2000,2001
|
||||
./contrib/sdb/dirdb.h C 2000,2001
|
||||
./contrib/sdb/ldapdb.c X 2001
|
||||
./contrib/sdb/ldapdb.h X 2001
|
||||
./contrib/sdb/lookup.tcl TCL 2000,2001
|
||||
./contrib/sdb/pgsqldb.c C 2000,2001
|
||||
./contrib/sdb/pgsqldb.h C 2000,2001
|
||||
|
|
@ -773,6 +777,8 @@
|
|||
./contrib/sdb/timedb.c C 2000,2001
|
||||
./contrib/sdb/timedb.h C 2000,2001
|
||||
./contrib/sdb/zonetodb.c C 2000,2001
|
||||
./contrib/sdb/zonetoldap.c X 2001
|
||||
./contrib/sdb/zonetoldap.1 X 2001
|
||||
./doc/.cvsignore X 2000,2001
|
||||
./doc/Makefile.in MAKE 2000,2001
|
||||
./doc/arm/.cvsignore X 2000,2001
|
||||
|
|
|
|||
Loading…
Reference in a new issue