Importing version 0.3.4

git-svn-id: https://svn.alkaloid.net/gpl/ldap2dns/trunk@7 06cd67b6-e706-0410-b29e-9de616bca6e9
This commit is contained in:
Ben Klang
2005-12-02 04:26:14 +00:00
parent 8e85c2c2be
commit 24f0ba9a9c
45 changed files with 3757 additions and 144 deletions

View File

@@ -1,9 +1,38 @@
Version 0.2.7 (next)
Version ?.?.? (next)
+ Make ldap2dns behave like a secondary nameserver by storing
the serial number, expire, refresh, retry and minimum values
in a record.
Version 0.2.6 (latest)
Version 0.3.3 (latest)
- Removed a bug which caused ldap2dns to etablish more than one connections
to the LDAP server.
Version 0.3.2
+ Only patches from Martin Lesser <m-lesser@better-com.de>
applied. Nothing from myself.
+ connecting to a ldap-server where the server is given as URI works
(both ldap:// [with TLS] and ldaps://)
+ we use location-codes here, so ldap2dns.c was extended to make use of
them, this also requires an extension of dns.schema.
Version 0.3.1
+ ldap2dns now can work together with tinydns. This means that
all DNS queries are passed through tinydns directly onto the
LDAP backend. This avoids generating a data-file and calling
tinydns-data (or restarting BIND).
Drawback: Queries are much slower now. I am not sure if this
is acceptable on the long run. This is caused by the LDAP-schema
used here, were many objects with strict attribute-value-pair mapping
is used. Other schemas, such as the core- and cosine-schema need
less LDAP-objects, since they code multiple values into one attribute.
Nameservers based on this schema (such as ldapdns
http://nimh.org/code/ldapdns/) can therefore answer much faster.
Version 0.3.0
+ A new interface for web-administration written compleatly in PHP.
Much easier to install that the old mod_perl interface.
Version 0.2.6
+ Password passed with option -w now is invisible to 'ps'.
+ ldap2tinydns-conf now takes a parameter to specify to user under
which ldap2dns will be running.

19
FAQ Normal file
View File

@@ -0,0 +1,19 @@
From: Steven Dossett <sdossett@panath.com>
Right after I mailed you, I patched the schema :)
I moved from IA5 Strings to Numeric Strings in that section of the schema:
attributetype ( 1.3.6.1.4.1.7222.1.4.12
NAME 'dnsipaddr'
EQUALITY numericStringMatch
SUBSTR numericStringSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} )
attributetype ( 1.3.6.1.4.1.7222.1.4.13
NAME 'dnscipaddr'
EQUALITY numericStringMatch
SUBSTR numericStringSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} )
Thanks for the quick reply. Take care.

View File

@@ -1,9 +1,9 @@
# $Id: Makefile,v 1.27 2001/08/09 10:35:49 jrief Exp $
VERSION=0.2.6
# $Id: Makefile,v 1.30 2003/01/20 14:33:25 jrief Exp $
VERSION=0.3.4
RELEASE=1
CC=gcc -O2
CCDEBUG=gcc -g
CFLAGS=$(INC) -DVERSION='"$(VERSION)"'
OBJS=ldap2dns.o
LIBS=-lldap -llber
LD=gcc
LDFLAGS=
@@ -13,30 +13,37 @@ LDAPCONFDIR=$(INSTALL_PREFIX)/etc/openldap
TARFILE=/usr/src/redhat/SOURCES/ldap2dns-$(VERSION).tar.gz
SPECFILE=ldap2dns.spec
all: ldap2dns
all: ldap2dns ldap2dnsd ldap2dns-dbg
ldap2dns: $(OBJS) $(LIBS)
$(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
ldap2dns: ldap2dns.o $(LIBS)
$(LD) $(LDFLAGS) -o $@ $+
ldap2dnsd: ldap2dns
ln -f ldap2dns ldap2dnsd
ldap2dns-dbg: ldap2dns.o-dbg $(LIBS)
$(LD) $(LDFLAGS) -o $@ $+
ldap2dns.o: ldap2dns.c
$(CC) $(CFLAGS) -c $<
$(CC) $(CFLAGS) -c $< -o $@
ldap2dns.o-dbg: ldap2dns.c
$(CCDEBUG) $(CFLAGS) -c $< -o $@
install: all
mkdir -p $(PREFIXDIR)/bin
mkdir -p $(LDAPCONFDIR)
mkdir -p $(LDAPCONFDIR)/schema
install -s -o root -g root -m 755 ldap2dns $(PREFIXDIR)/bin/
ln -f $(PREFIXDIR)/bin/ldap2dns $(PREFIXDIR)/bin/ldap2dnsd
install -o root -g root -m 755 ldap2tinydns-conf $(PREFIXDIR)/bin/
install -o root -g root -m 644 dns.at.conf $(LDAPCONFDIR)/
install -o root -g root -m 644 dns.oc.conf $(LDAPCONFDIR)/
install -o root -g root -m 644 dns.schema $(LDAPCONFDIR)/schema/
clean:
rm -f $(OBJS) ldap2dns ldap2dnsd data* *.db core $(SPECFILE)
rm -f *.o *.o-dbg ldap2dns ldap2dnsd data* *.db core $(SPECFILE)
tar: clean
cd ..; \
tar czf $(TARFILE) ldap2dns-$(VERSION) --exclude CVS --exclude DNSadmin
tar czf $(TARFILE) ldap2dns-$(VERSION) --exclude CVS
$(SPECFILE): Specfile
sed -e 's#%VERSION%#$(VERSION)#g' \

View File

@@ -195,8 +195,12 @@ include /etc/openldap/dns.at.conf
include /etc/openldap/dns.oc.conf
</PRE>
or, if You are using openldap-2.0.x:<BR>
copy the file dns.schema into the directory /etc/openldap/schema or
appropriate and add the following line to Your slapd.conf file:<BR>
copy the file dns.schema-2.0 into the directory /etc/openldap/schema
and rename it to dns.schema.
If You are using openldap-2.2.x:<BR>
copy the file dns.schema-2.2 into the directory /etc/openldap/schema
and rename it to dns.schema.
Add the following line to Your slapd.conf file:<BR>
<PRE>
include /etc/openldap/schema/dns.schema
</PRE>

1
TODO.schema Normal file
View File

@@ -0,0 +1 @@
# schema for DNS data# include this file into Your slapd.conf for openldap-2.0.x# $Id: dns.schema,v 1.9 2001/11/06 08:01:51 config Exp $attributetype ( 1.3.6.1.4.1.7222.1.4.1 NAME 'dnszonename' SUP name )attributetype ( 1.3.6.1.4.1.7222.1.4.2 NAME 'dnsserial' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.3 NAME 'dnsrefresh' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.4 NAME 'dnsretry' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.5 NAME 'dnsexpire' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.6 NAME 'dnsminimum' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.7 NAME 'dnsadminmailbox' SUP name )attributetype ( 1.3.6.1.4.1.7222.1.4.8 NAME 'dnszonemaster' SUP name )attributetype ( 1.3.6.1.4.1.7222.1.4.9 NAME 'dnstype' SUP name )attributetype ( 1.3.6.1.4.1.7222.1.4.10 NAME 'dnsclass' SUP name )attributetype ( 1.3.6.1.4.1.7222.1.4.11 NAME 'dnsdomainname' SUP name )attributetype ( 1.3.6.1.4.1.7222.1.4.12 NAME 'dnsipaddr' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} ) SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.13 NAME 'dnscipaddr' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} )attributetype ( 1.3.6.1.4.1.7222.1.4.14 NAME 'dnscname' SUP name )attributetype ( 1.3.6.1.4.1.7222.1.4.15 NAME 'dnspreference' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.16 NAME 'dnsrr' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.17 NAME 'dnsttl' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.18 NAME 'dnstimestamp' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )attributetype ( 1.3.6.1.4.1.7222.1.4.21 NAME 'NIChandle' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} )attributetype ( 1.3.6.1.4.1.7222.1.4.22 NAME 'TIShandle' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} )objectclass ( 1.3.6.1.4.1.7222.1.4.19 NAME 'dnszone' MUST ( objectclass $ cn ) MAY ( dnszonename $ dnsserial $ dnsrefresh $ dnsretry $ dnsexpire $ dnsminimum $ dnsadminmailbox $ dnszonemaster $ dnstype $ dnsclass $ dnsttl $ dnstimestamp $ owner $ NIChandle $ TIShandle ) )objectclass ( 1.3.6.1.4.1.7222.1.4.20 NAME 'dnsrrset' SUP dnszone MUST ( objectclass $ cn ) MAY ( dnsdomainname $ dnsrr $ dnsclass $ dnstype $ dnsipaddr $ dnscipaddr $ dnscname $ dnspreference $ dnsttl $ dnstimestamp $ owner ) )

743
askldap.c Normal file
View File

@@ -0,0 +1,743 @@
/* Patch for tinydns to pass DNS-query to LDAP in favour of a cdb lookup.
* $Id: askldap.c,v 1.8 2002/08/12 16:41:25 jrief Exp $
* Copyright 2002 <jacob.rief@tiscover.com>
*/
#include <lber.h>
#include <ldap.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <setjmp.h>
#include "alloc.h"
#include "byte.h"
#include "response.h"
#include "askldap.h"
#include "dns.h"
static LDAP* ldap_con;
static sigjmp_buf stack_context;
static struct {
char ldaphosts[256];
const char* basedn;
char binddn[256];
char bindpwd[16];
struct timeval timeout;
int verbose;
int initialized;
} options;
struct zonerecord {
char zonedn[256];
char zonename[64];
char class[16];
char type[16];
char adminmailbox[64];
char zonemaster[64];
unsigned long serial, refresh, retry, expire, minimum;
int ttl;
int timestamp;
};
struct resourcerecord {
char qualifieddomainname[256];
char class[16];
char type[16];
char ipaddr[8][4];
int numipaddrs;
char cname[256];
unsigned int preference;
int ttl;
int timestamp;
int additionalinfo;
struct resourcerecord* next;
};
enum { ASKLDAP_RETRY = 1, ASKLDAP_RETURN = 2, ASKLDAP_RECONNECT = 3 };
static
void assert_ldap(int err)
{
static int retries;
switch (err) {
case LDAP_SUCCESS:
return;
case LDAP_TIMELIMIT_EXCEEDED:
fprintf(stderr, "Warning: %s\n", ldap_err2string(err));
retries++;
if (retries<3)
siglongjmp(stack_context, ASKLDAP_RETRY);
retries = 0;
siglongjmp(stack_context, ASKLDAP_RETURN);
case LDAP_TIMEOUT:
case LDAP_NO_SUCH_OBJECT:
fprintf(stderr, "Warning: %s\n", ldap_err2string(err));
siglongjmp(stack_context, ASKLDAP_RETURN);
case LDAP_BUSY:
case LDAP_UNAVAILABLE:
case LDAP_UNWILLING_TO_PERFORM:
case LDAP_SERVER_DOWN:
fprintf(stderr, "Warning: %s\n", ldap_err2string(err));
siglongjmp(stack_context, ASKLDAP_RECONNECT);
default:
fprintf(stderr, "Fatal error: %s\n", ldap_err2string(err));
#ifdef _DEBUG
abort();
#else
exit(1);
#endif
}
}
void free_domainrecords(struct resourcerecord* anchor)
{
struct resourcerecord* ptr;
for (ptr = anchor; ptr; ptr = anchor) {
anchor = anchor->next;
alloc_free(ptr);
}
}
static
void fill_resourcerecord(struct resourcerecord* rr, LDAPMessage* m, const char* zonename)
{
BerElement* ber = NULL;
char* attr;
byte_zero(rr, sizeof(struct resourcerecord));
strcpy(rr->class, "IN");
for (attr = ldap_first_attribute(ldap_con, m, &ber); attr; attr = ldap_next_attribute(ldap_con, m, ber)) {
struct berval** bvals = ldap_get_values_len(ldap_con, m, attr);
if (bvals && bvals[0] && bvals[0]->bv_len>0) {
if (strcasecmp(attr, "dnsdomainname")==0) {
char tmp[64];
if (sscanf(bvals[0]->bv_val, "%64s", tmp)==1) {
if (zonename[0]!='\0')
snprintf(rr->qualifieddomainname, 256, "%s.%s", tmp, zonename);
else
strncpy(rr->qualifieddomainname, tmp, 256);
}
} else if (strcasecmp(attr, "dnstype")==0) {
if (sscanf(bvals[0]->bv_val, "%16s", rr->type)!=1) {
rr->type[0] = '\0';
}
} else if (strcasecmp(attr, "dnsipaddr")==0) {
int k, ip[4];
for (k = 0; bvals[k] && k < 8-rr->numipaddrs; k++) {
if (sscanf(bvals[k]->bv_val, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4) {
rr->ipaddr[rr->numipaddrs][0] = (char)ip[0];
rr->ipaddr[rr->numipaddrs][1] = (char)ip[1];
rr->ipaddr[rr->numipaddrs][2] = (char)ip[2];
rr->ipaddr[rr->numipaddrs][3] = (char)ip[3];
rr->numipaddrs++;
}
}
} else if (rr->numipaddrs<8 && strcasecmp(attr, "dnscipaddr")==0) {
int ip[4];
if (sscanf(bvals[0]->bv_val, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4) {
rr->ipaddr[rr->numipaddrs][0] = (char)ip[0];
rr->ipaddr[rr->numipaddrs][1] = (char)ip[1];
rr->ipaddr[rr->numipaddrs][2] = (char)ip[2];
rr->ipaddr[rr->numipaddrs][3] = (char)ip[3];
rr->numipaddrs++;
}
} else if (strcasecmp(attr, "dnscname")==0) {
if (sscanf(bvals[0]->bv_val, "%256s", rr->cname)==1) {
int len = strlen(rr->cname);
if (rr->cname[len-1]!='.' && zonename[0]!='\0') {
strcat(rr->cname, ".");
strncat(rr->cname, zonename, 252-len);
strcat(rr->cname, ".");
}
} else {
rr->cname[0] = '\0';
}
} else if (strcasecmp(attr, "dnsttl")==0) {
if (sscanf(bvals[0]->bv_val, "%d", &rr->ttl)!=1)
rr->ttl = 0;
} else if (strcasecmp(attr, "dnstimestamp")==0) {
if (sscanf(bvals[0]->bv_val, "%d", &rr->timestamp)!=1)
rr->timestamp = 0;
} else if (strcasecmp(attr, "dnspreference")==0) {
if (sscanf(bvals[0]->bv_val, "%u", &rr->preference)!=1)
rr->preference = 1;
}
}
ldap_value_free_len(bvals);
}
if (rr->qualifieddomainname[0]=='\0')
strncpy(rr->qualifieddomainname, zonename, 256);
}
static
void fill_zonerecord(struct zonerecord* zone, LDAPMessage* m)
{
BerElement* ber = NULL;
char* attr;
byte_zero(zone, sizeof(struct zonerecord));
strcpy(zone->class, "IN");
for (attr = ldap_first_attribute(ldap_con, m, &ber); attr; attr = ldap_next_attribute(ldap_con, m, ber)) {
struct berval** bvals = ldap_get_values_len(ldap_con, m, attr);
if (bvals && bvals[0] && bvals[0]->bv_len>0) {
if (strcasecmp(attr, "dnstype")==0) {
if (sscanf(bvals[0]->bv_val, "%16s", zone->type)!=1)
zone->type[0] = '\0';
} else if (strcasecmp(attr, "dnsserial")==0) {
if (sscanf(bvals[0]->bv_val, "%lu", &zone->serial)!=1)
zone->serial = 0;
} else if (strcasecmp(attr, "dnsrefresh")==0) {
if (sscanf(bvals[0]->bv_val, "%lu", &zone->refresh)!=1)
zone->refresh = 0;
} else if (strcasecmp(attr, "dnsretry")==0) {
if (sscanf(bvals[0]->bv_val, "%lu", &zone->retry)!=1)
zone->retry = 0;
} else if (strcasecmp(attr, "dnsexpire")==0) {
if (sscanf(bvals[0]->bv_val, "%lu", &zone->expire)!=1)
zone->expire = 0;
} else if (strcasecmp(attr, "dnsminimum")==0) {
if (sscanf(bvals[0]->bv_val, "%lu", &zone->minimum)!=1)
zone->minimum = 0;
} else if (strcasecmp(attr, "dnsadminmailbox")==0) {
if (sscanf(bvals[0]->bv_val, "%64s", zone->adminmailbox)!=1)
zone->adminmailbox[0] = '\0';
} else if (strcasecmp(attr, "dnszonemaster")==0) {
if (sscanf(bvals[0]->bv_val, "%64s", zone->zonemaster)!=1)
zone->zonemaster[0] = '\0';
} else if (strcasecmp(attr, "dnsttl")==0) {
if (sscanf(bvals[0]->bv_val, "%d", &zone->ttl)!=1)
zone->ttl = 0;
} else if (strcasecmp(attr, "dnstimestamp")==0) {
if (sscanf(bvals[0]->bv_val, "%d", &zone->timestamp)!=1)
zone->timestamp = 0;
} else if (strcasecmp(attr, "dnszonename")==0) {
if (sscanf(bvals[0]->bv_val, "%s", zone->zonename)!=1)
zone->zonename[0] = '\0';
}
}
ldap_value_free_len(bvals);
}
}
static
int find_ipaddr(const char* queryname, char ip[4])
{
static char *rrattrs[] = { "dnsipaddr", "dnscipaddr", 0 };
LDAPMessage* res = NULL;
LDAPMessage* m;
int ret = 0;
char filter[256], domainname[64];
const char *zonename = queryname;
domainname[0] = '\0';
while (*zonename) {
int len = snprintf(filter, 256, "(&(dnszonename=%s", zonename);
if (filter[len-1]=='.')
filter[len-1] = '\0';
strncat(filter, ")(objectclass=dnszone)(dnsclass=IN))", 256-len);
assert_ldap(ldap_search_st(ldap_con, options.basedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
if (m = ldap_first_entry(ldap_con, res)) {
char* zonedn = ldap_get_dn(ldap_con, m);
if (ldap_next_entry(ldap_con, m))
printf("Warning: ambigous zonename for %s in %s\n", zonename, zonedn);
if (domainname[0]!='\0') {
len = strlen(domainname);
if (domainname[len-1]=='.')
domainname[len-1] = '\0';
snprintf(filter, 256, "(&(|(dnsdomainname=%s)(dnscname=%s))(objectclass=dnsrrset)(dnsclass=IN)(|(dnsipaddr=*)(dnscipaddr=*)))", domainname, domainname);
} else {
strcpy(filter, "(&(!(dnsdomainname=*))(objectclass=dnsrrset)(dnsclass=IN)(|(dnsipaddr=*)(dnscipaddr=*)))");
}
ldap_msgfree(res);
assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
if (m = ldap_first_entry(ldap_con, res)) {
struct resourcerecord rr;
fill_resourcerecord(&rr, m, "");
if (rr.numipaddrs>0) {
rr.numipaddrs = rand()%rr.numipaddrs;
ip[0] = rr.ipaddr[rr.numipaddrs][0];
ip[1] = rr.ipaddr[rr.numipaddrs][1];
ip[2] = rr.ipaddr[rr.numipaddrs][2];
ip[3] = rr.ipaddr[rr.numipaddrs][3];
ret = 1;
}
}
ldap_memfree(zonedn);
ldap_msgfree(res); res = NULL;
if (ret)
return 1;
break;
}
while (*zonename && *zonename!='.') {
domainname[zonename-queryname] = *zonename;
zonename++;
}
domainname[zonename-queryname] = *zonename;
if (*zonename=='.') {
zonename++;
domainname[zonename-queryname] = '\0';
}
}
/* sometimes the queryname resolves directly as cname in some other records */
snprintf(filter, 256, "(&(dnscname=%s)(objectclass=dnsrrset)(dnsclass=IN)(|(dnsipaddr=*)(dnscipaddr=*)))", queryname);
assert_ldap(ldap_search_st(ldap_con, options.basedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
if (m = ldap_first_entry(ldap_con, res)) {
struct resourcerecord rr;
fill_resourcerecord(&rr, m, "");
if (rr.numipaddrs>0) {
rr.numipaddrs = rand()%rr.numipaddrs;
ip[0] = rr.ipaddr[rr.numipaddrs][0];
ip[1] = rr.ipaddr[rr.numipaddrs][1];
ip[2] = rr.ipaddr[rr.numipaddrs][2];
ip[3] = rr.ipaddr[rr.numipaddrs][3];
ret = 1;
}
}
ldap_msgfree(res);
return ret;
}
static
struct resourcerecord* find_reverserecord(const char* queryname, int ip[4])
{
static char *rrattrs[] = { "dnstype", "dnsdomainname", "dnscname", "dnsttl", 0 };
LDAPMessage* res = NULL;
struct resourcerecord* rr = NULL;
LDAPMessage* m;
char filter[256];
snprintf(filter, 256, "(&(dnscipaddr=%u.%u.%u.%u)(objectclass=dnsrrset)(dnsclass=IN))", ip[0], ip[1], ip[2], ip[3]);
assert_ldap(ldap_search_st(ldap_con, options.basedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
if (m = ldap_first_entry(ldap_con, res)) {
char* rrsetdn = ldap_get_dn(ldap_con, m);
char** explodedn = NULL;
rr = (void*)alloc(sizeof(struct resourcerecord));
fill_resourcerecord(rr, m, "");
if (ldap_next_entry(ldap_con, m))
printf("Warning: ambigous IP-address for %u.%u.%u.%u in dn: %s\n", ip[0], ip[1], ip[2], ip[3], rrsetdn);
explodedn = ldap_explode_dn(rrsetdn, 0);
if (explodedn[0]) {
static char *zoneattrs[] = { "dnszonename", 0 };
char zonedn[256];
int i, len = 0;
struct zonerecord zone;
zonedn[0] = '\0';
for (i = 1; explodedn[i]; i++)
len += snprintf(zonedn+len, 256-len, "%s,", explodedn[i]);
zonedn[len-1] = '\0';
ldap_msgfree(res);
assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, "(objectclass=dnszone)", zoneattrs, 0, &options.timeout, &res));
m = ldap_first_entry(ldap_con, res);
if (m==NULL)
printf("Error: parent dn: %s not found for %s\n", zonedn, rrsetdn);
fill_zonerecord(&zone, m);
len = strlen(rr->qualifieddomainname);
if (len==0) {
len = strlen(rr->cname);
if (rr->cname[len-1]!='.') {
strcat(rr->cname, ".");
strncat(rr->cname, zone.zonename, 252-len);
}
} else {
/* in those situations where a dnsrrset
* defines something like MX or NS for a zone
* and also sets a canonical name for the
* service. */
snprintf(rr->cname, 256, "%s.%s", rr->qualifieddomainname, zone.zonename);
}
strcpy(rr->type, "PTR");
strncpy(rr->qualifieddomainname, queryname, 256);
}
ldap_memfree(rrsetdn);
ldap_value_free(explodedn);
}
ldap_msgfree(res);
return rr;
}
static
struct resourcerecord* read_domainrecords(const char* zonedn, const char* domainname, const char* zonename)
{
static char *rrattrs[] = { "dnsdomainname", "dnstype", "dnsttl", "dnscname", "dnsipaddr", "dnscipaddr", "dnstimestamp", "dnspreference", 0 };
LDAPMessage* res = NULL;
LDAPMessage* m;
char filter[256];
struct resourcerecord *prev, *anchor = NULL;
if (domainname[0]) {
if (strstr(zonename, "in-addr.arpa")) {
unsigned int ip[4];
char queryname[256];
snprintf(queryname, 256, "%s.%s", domainname, zonename);
if (sscanf(queryname, "%3u.%3u.%3u.%3u", &ip[3], &ip[2], &ip[1], &ip[0])!=4)
return NULL;
snprintf(filter, 256, "(&(dnsipaddr=%u.%u.%u.%u)(objectclass=dnsrrset)(dnsclass=IN))", ip[0], ip[1], ip[2], ip[3]);
assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
if (m = ldap_first_entry(ldap_con, res)) {
struct resourcerecord* rr;
rr = (void*)alloc(sizeof(struct resourcerecord));
fill_resourcerecord(rr, m, zonename);
strncpy(rr->qualifieddomainname, queryname, 256);
ldap_msgfree(res);
return rr;
} else {
/* ipaddr not in our baliwick, search the whole tree for canonical ipaddr */
ldap_msgfree(res);
return find_reverserecord(queryname, ip);
}
} else {
snprintf(filter, 256, "(&(dnsdomainname=%s)(objectclass=dnsrrset)(dnsclass=IN))", domainname);
assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
}
} else {
snprintf(filter, 256, "(&(!(dnsdomainname=*))(objectclass=dnsrrset)(dnsclass=IN))");
assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
}
for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
struct resourcerecord* rr;
rr = (void*)alloc(sizeof(struct resourcerecord));
fill_resourcerecord(rr, m, zonename);
if (anchor==NULL) {
prev = anchor = rr;
} else {
prev->next = rr;
prev = rr;
}
if (options.verbose&1)
printf("\trr: %s %s\n", domainname, rr->type);
}
ldap_msgfree(res);
return anchor;
}
static
int read_dnszone(struct zonerecord* zone, const char* zonename)
{
static char *zoneattrs[] = { "dnszonename", "dnstype", "dnsserial", "dnsrefresh", "dnsretry", "dnsexpire", "dnsminimum", "dnszonemaster", "dnsadminmailbox", "dnsttl", "dnstimestamp", 0 };
LDAPMessage* res = NULL;
LDAPMessage* m;
char* dn;
char filter[256];
snprintf(filter, 256, "(&(dnszonename=%s)(objectclass=dnszone)(dnsclass=IN))", zonename);
assert_ldap(ldap_search_st(ldap_con, options.basedn, LDAP_SCOPE_SUBTREE, filter, zoneattrs, 0, &options.timeout, &res));
m = ldap_first_entry(ldap_con, res);
if (m==NULL) {
ldap_msgfree(res);
return 0;
}
dn = ldap_get_dn(ldap_con, m);
fill_zonerecord(zone, m);
m = ldap_next_entry(ldap_con, m);
if (m) {
char* otherdn = ldap_get_dn(ldap_con, m);
printf("Warning: ambigous zonename found in dn: %s and dn: %s\n", dn, otherdn);
ldap_memfree(otherdn);
}
strncpy(zone->zonedn, dn, 256);
ldap_memfree(dn);
ldap_msgfree(res);
return 1;
}
static
void djb_name(const char* dotname, char* djbname)
{
const char* c = dotname;
int i, k;
for (i = 0; *c; c++) {
k = i;
while (*c!='.') {
k++;
djbname[k] = *c;
if (*c=='\0') {
djbname[i] = k-i-1;
return;
}
c++;
}
djbname[i] = k-i;
i = k+1;
}
djbname[i] = '\0';
}
static
void djb_type(const char* dottype, char djbtype[2])
{
djbtype[0] = '\0';
if (strcasecmp(dottype, "A")==0)
djbtype[1] = 001;
else if (strcasecmp(dottype, "NS")==0)
djbtype[1] = 002;
else if (strcasecmp(dottype, "CNAME")==0)
djbtype[1] = 005;
else if (strcasecmp(dottype, "SOA")==0)
djbtype[1] = 006;
else if (strcasecmp(dottype, "PTR")==0)
djbtype[1] = 014;
else if (strcasecmp(dottype, "MX")==0)
djbtype[1] = 017;
else if (strcasecmp(dottype, "TXT")==0)
djbtype[1] = 020;
}
static
void split_djbstyle(const char* djbname, char* domainname, char* zonename, int offset)
{
int i, k, m = 0, n = 0;
for (i = *djbname; i; i = *++djbname) {
if (offset>0) {
offset--;
for (k = m; k<m+i; k++) {
domainname[k] = *++djbname;
}
domainname[k] = '.';
m = k+1;
} else {
for (k = n; k<n+i; k++) {
zonename[k] = *++djbname;
}
zonename[k] = '.';
n = k+1;
}
}
domainname[m>0 ? m-1 : 0] = '\0';
zonename[n>0 ? n-1 : 0] = '\0';
}
static
void build_response_section(struct resourcerecord *rr, char qtype[2], int section)
{
char djbname[256], djbtype[2];
djb_name(rr->qualifieddomainname, djbname);
djb_type(rr->type, djbtype);
if (byte_equal(djbtype, 2, DNS_T_A)) {
if (byte_equal(qtype, 2, DNS_T_A) || byte_equal(qtype, 2, DNS_T_ANY)) {
response_rstart(djbname, djbtype, rr->ttl);
response_addbytes(rr->ipaddr[rand()%rr->numipaddrs], 4);
response_rfinish(section);
}
} else if (byte_equal(djbtype, 2, DNS_T_CNAME)) {
response_rstart(djbname, djbtype, rr->ttl);
djb_name(rr->cname, djbname);
response_addname(djbname);
response_rfinish(section);
} else if (byte_equal(djbtype, 2, DNS_T_NS)) {
if (byte_equal(qtype, 2, DNS_T_NS) || byte_equal(qtype, 2, DNS_T_ANY)) {
response_rstart(djbname, djbtype, rr->ttl);
if (rr->cname[0]) {
djb_name(rr->cname, djbname);
response_addname(djbname);
rr->additionalinfo = 1;
} else {
response_addbytes(rr->ipaddr[rand()%rr->numipaddrs], 4);
}
response_rfinish(section);
}
} else if (byte_equal(djbtype, 2, DNS_T_PTR)) {
response_rstart(djbname, djbtype, rr->ttl);
djb_name(rr->cname, djbname);
response_addname(djbname);
response_rfinish(section);
} else if (byte_equal(djbtype, 2, DNS_T_MX)) {
if (byte_equal(qtype, 2, DNS_T_MX) || byte_equal(qtype, 2, DNS_T_ANY)) {
char tmp[2];
response_rstart(djbname, djbtype, rr->ttl);
tmp[0] = rr->preference/0x100;
tmp[1] = rr->preference%0x100;
response_addbytes(tmp, 2);
if (rr->cname[0]) {
djb_name(rr->cname, djbname);
response_addname(djbname);
rr->additionalinfo = 1;
} else {
response_addbytes(rr->ipaddr[rand()%rr->numipaddrs], 4);
}
response_rfinish(section);
}
}
}
static
void build_soa_section(struct zonerecord *zone, int section)
{
time_t now;
char defaultsoa[20];
char djbname[256];
char zonesoa[20];
unsigned long tmp;
time(&now);
djb_name(zone->zonename, djbname);
response_rstart(djbname, DNS_T_SOA, zone->ttl);
djb_name(zone->zonemaster, djbname);
response_addname(djbname);
djb_name(zone->adminmailbox, djbname);
response_addname(djbname);
uint32_pack_big(defaultsoa, now);
if (byte_equal(defaultsoa,4,"\0\0\0\0"))
defaultsoa[3] = 1;
byte_copy(defaultsoa + 4, 16, "\0\0\100\000\0\0\010\000\0\020\000\000\0\0\012\000");
if (zone->serial==0)
uint32_unpack_big(defaultsoa, &tmp);
else
tmp = zone->serial;
uint32_pack_big(zonesoa, tmp);
if (zone->refresh==0)
uint32_unpack_big(defaultsoa+4, &tmp);
else
tmp = zone->refresh;
uint32_pack_big(zonesoa+4, tmp);
if (zone->retry==0)
uint32_unpack_big(defaultsoa+8, &tmp);
else
tmp = zone->retry;
uint32_pack_big(zonesoa+8, tmp);
if (zone->expire==0)
uint32_unpack_big(defaultsoa+12, &tmp);
else
tmp = zone->expire;
uint32_pack_big(zonesoa+12, tmp);
if (zone->minimum==0)
uint32_unpack_big(defaultsoa+16, &tmp);
else
tmp = zone->minimum;
uint32_pack_big(zonesoa+16, tmp);
response_addbytes(zonesoa, 20);
response_rfinish(section);
}
static
void build_additional_section(struct resourcerecord *rr)
{
char djbname[256], ip[4];
if (rr->additionalinfo && find_ipaddr(rr->cname, ip)) {
djb_name(rr->cname, djbname);
response_rstart(djbname, DNS_T_A, rr->ttl);
response_addbytes(ip, 4);
response_rfinish(RESPONSE_ADDITIONAL);
}
}
static
int connect_and_bind()
{
ldap_con = ldap_init(options.ldaphosts, LDAP_PORT);
if (ldap_simple_bind_s(ldap_con, options.binddn, options.bindpwd)==LDAP_SUCCESS) {
printf("Connected to %s as \"%s\"\n", options.ldaphosts, options.binddn);
return 1;
}
ldap_con = NULL;
return 0;
}
int askldap_query(const char* djbdomainname, char qtype[2])
{
int offset;
char domainname[64], zonename[64];
struct zonerecord zoneinfo;
int answer_ok = 0, flagsoa = 0, flagns = 0;
if (!options.initialized)
return 0;
switch (sigsetjmp(stack_context, 1)) {
default:
if (ldap_con==NULL && !connect_and_bind())
return answer_ok;
break;
case ASKLDAP_RECONNECT:
if (connect_and_bind())
break;
return answer_ok;
case ASKLDAP_RETURN:
return answer_ok;
}
for (offset = 0; offset<32; offset++) {
struct resourcerecord *rransw, *rrauth, *rr;
split_djbstyle(djbdomainname, domainname, zonename, offset);
if (zonename[0]=='\0') return 0;
if (!read_dnszone(&zoneinfo, zonename))
continue;
rransw = read_domainrecords(zoneinfo.zonedn, domainname, zonename);
rrauth = NULL;
if (offset==0) {
/* query is in our bailiwick */
if (byte_equal(qtype, 2, DNS_T_ANY) || byte_equal(qtype, 2, DNS_T_SOA)) {
build_soa_section(&zoneinfo, RESPONSE_ANSWER);
flagsoa = 1;
}
for (rr = rransw; rr; rr = rr->next) {
build_response_section(rr, qtype, RESPONSE_ANSWER);
answer_ok = 1;
}
if (!flagsoa) {
build_soa_section(&zoneinfo, RESPONSE_AUTHORITY);
flagsoa = 1;
}
if (!byte_equal(qtype, 2, DNS_T_ANY) && !byte_equal(qtype, 2, DNS_T_NS)) {
for (rr = rransw; rr; rr = rr->next)
if (strcmp(rr->type, "NS")==0) {
build_response_section(rr, DNS_T_NS, RESPONSE_AUTHORITY);
flagns = 1;
}
}
} else {
for (rr = rransw; rr; rr = rr->next) {
if (strcmp(rr->type, "NS")==0) {
build_response_section(rr, qtype, RESPONSE_AUTHORITY);
flagns = 1;
}
}
if (!flagns) {
for (rr = rransw; rr; rr = rr->next) {
build_response_section(rr, qtype, RESPONSE_ANSWER);
answer_ok = 1;
}
if (answer_ok) {
rrauth = read_domainrecords(zoneinfo.zonedn, "", zonename);
} else {
build_soa_section(&zoneinfo, RESPONSE_AUTHORITY);
flagsoa = 1;
}
}
for (rr = rrauth; rr; rr = rr->next) {
if (strcmp(rr->type, "NS")==0) {
build_response_section(rr, DNS_T_NS, RESPONSE_AUTHORITY);
flagns = 1;
}
}
}
for (rr = rransw; rr; rr = rr->next)
build_additional_section(rr);
for (rr = rrauth; rr; rr = rr->next)
build_additional_section(rr);
free_domainrecords(rransw);
free_domainrecords(rrauth);
break;
}
return answer_ok || flagsoa || flagns;
}
void askldap_init(const char* ldaphost, const char* basedn, const char* binddn, const char* passwd)
{
strncpy(options.ldaphosts, ldaphost, 256);
options.basedn = basedn;
if (binddn) strncpy(options.binddn, binddn, 256);
if (passwd) strncpy(options.bindpwd, passwd, 16);
/* LDAP timeout is hardcoded to 2/10 second.
* This must be enough because bindoperations usually
* timeout after one second and here we usually have to
* send five queries to the LDAP-server */
options.timeout.tv_sec = 1;
options.timeout.tv_usec = 200000;
options.verbose = 0;
options.initialized = 1;
connect_and_bind();
}

10
askldap.h Normal file
View File

@@ -0,0 +1,10 @@
/* Patch for tinydns to pass DNS-query to LDAP in favour of a cdb lookup.
* $Id: askldap.h,v 1.8 2002/08/12 16:41:25 jrief Exp $
* Copyright 2002 <jacob.rief@tiscover.com>
*/
extern
int askldap_query(const char* djbdomainname, char qtype[2]);
extern
void askldap_init(const char* ldaphost, const char* basedn, const char* binddn, const char* passwd);

972
djbdns-1.0.5.patch Normal file
View File

@@ -0,0 +1,972 @@
diff -Naur djbdns-1.05.orig/Makefile djbdns-1.05/Makefile
--- djbdns-1.05.orig/Makefile Sun Feb 11 22:11:45 2001
+++ djbdns-1.05/Makefile Tue Aug 13 14:28:52 2002
@@ -1,9 +1,6 @@
-# Don't edit Makefile! Use conf-* for configuration.
-
-SHELL=/bin/sh
-
default: it
+
alloc.a: \
makelib alloc.o alloc_re.o getln.o getln2.o stralloc_cat.o \
stralloc_catb.o stralloc_cats.o stralloc_copy.o stralloc_eady.o \
@@ -55,8 +52,8 @@
prot.o timeoutread.o timeoutwrite.o dns.a libtai.a alloc.a env.a \
cdb.a buffer.a unix.a byte.a
./load axfrdns iopause.o droproot.o tdlookup.o response.o \
- qlog.o prot.o timeoutread.o timeoutwrite.o dns.a libtai.a \
- alloc.a env.a cdb.a buffer.a unix.a byte.a
+ qlog.o prot.o timeoutread.o timeoutwrite.o askldap.o dns.a libtai.a \
+ alloc.a env.a cdb.a buffer.a unix.a byte.a `cat ldap.lib`
axfrdns-conf: \
load axfrdns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
@@ -626,11 +623,11 @@
./compile parsetype.c
pickdns: \
-load pickdns.o server.o response.o droproot.o qlog.o prot.o dns.a \
+load pickdns.o server.o response.o droproot.o qlog.o prot.o askldap.o dns.a \
env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
./load pickdns server.o response.o droproot.o qlog.o \
- prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
- byte.a `cat socket.lib`
+ prot.o askldap.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
+ byte.a `cat socket.lib` `cat ldap.lib`
pickdns-conf: \
load pickdns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
@@ -704,11 +701,11 @@
./compile random-ip.c
rbldns: \
-load rbldns.o server.o response.o dd.o droproot.o qlog.o prot.o dns.a \
+load rbldns.o server.o response.o dd.o droproot.o qlog.o prot.o askldap.o dns.a \
env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
./load rbldns server.o response.o dd.o droproot.o qlog.o \
- prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
- byte.a `cat socket.lib`
+ prot.o askldap.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
+ byte.a `cat socket.lib` `cat ldap.lib`
rbldns-conf: \
load rbldns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
@@ -792,6 +789,9 @@
&& echo -lsocket -lnsl || exit 0 ) > socket.lib
rm -f trylsock.o trylsock
+ldap.lib:
+ echo -lldap -llber > ldap.lib
+
socket_accept.o: \
compile socket_accept.c byte.h socket.h uint16.h
./compile socket_accept.c
@@ -978,13 +978,17 @@
timeoutwrite.h
./compile timeoutwrite.c
+askldap.o: \
+compile askldap.c askldap.h
+ ./compile askldap.c
+
tinydns: \
load tinydns.o server.o droproot.o tdlookup.o response.o qlog.o \
-prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
-socket.lib
+prot.o askldap.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
+socket.lib ldap.lib
./load tinydns server.o droproot.o tdlookup.o response.o \
- qlog.o prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \
- unix.a byte.a `cat socket.lib`
+ qlog.o prot.o askldap.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \
+ unix.a byte.a `cat socket.lib` `cat ldap.lib`
tinydns-conf: \
load tinydns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
@@ -1015,26 +1019,26 @@
tinydns-edit.o: \
compile tinydns-edit.c stralloc.h gen_alloc.h buffer.h exit.h open.h \
getln.h buffer.h stralloc.h strerr.h scan.h byte.h str.h fmt.h ip4.h \
-dns.h stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+dns.h stralloc.h iopause.h taia.h tai.h uint64.h taia.h askldap.h
./compile tinydns-edit.c
tinydns-get: \
load tinydns-get.o tdlookup.o response.o printpacket.o printrecord.o \
parsetype.o dns.a libtai.a cdb.a buffer.a alloc.a unix.a byte.a
./load tinydns-get tdlookup.o response.o printpacket.o \
- printrecord.o parsetype.o dns.a libtai.a cdb.a buffer.a \
- alloc.a unix.a byte.a
+ printrecord.o parsetype.o askldap.o dns.a libtai.a cdb.a buffer.a \
+ alloc.a unix.a byte.a `cat ldap.lib`
tinydns-get.o: \
compile tinydns-get.c str.h byte.h scan.h exit.h stralloc.h \
gen_alloc.h buffer.h strerr.h uint16.h response.h uint32.h case.h \
printpacket.h stralloc.h parsetype.h ip4.h dns.h stralloc.h iopause.h \
-taia.h tai.h uint64.h taia.h
+taia.h tai.h uint64.h taia.h askldap.h
./compile tinydns-get.c
tinydns.o: \
compile tinydns.c dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h \
-uint64.h taia.h
+uint64.h taia.h askldap.h
./compile tinydns.c
uint16_pack.o: \
@@ -1084,11 +1088,11 @@
./compile utime.c
walldns: \
-load walldns.o server.o response.o droproot.o qlog.o prot.o dd.o \
+load walldns.o server.o response.o droproot.o qlog.o prot.o dd.o askldap.o \
dns.a env.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
./load walldns server.o response.o droproot.o qlog.o \
- prot.o dd.o dns.a env.a cdb.a alloc.a buffer.a unix.a \
- byte.a `cat socket.lib`
+ prot.o dd.o askldap.o dns.a env.a cdb.a alloc.a buffer.a unix.a \
+ byte.a `cat socket.lib` `cat ldap.lib`
walldns-conf: \
load walldns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
diff -Naur djbdns-1.05.orig/askldap.c djbdns-1.05/askldap.c
--- djbdns-1.05.orig/askldap.c Thu Jan 1 01:00:00 1970
+++ djbdns-1.05/askldap.c Tue Aug 13 14:30:18 2002
@@ -0,0 +1,750 @@
+/* Patch for tinydns to pass DNS-query to LDAP in favour of a cdb lookup.
+ * $Id$
+ * Copyright 2002 <jacob.rief@tiscover.com>
+ */
+
+#include <lber.h>
+#include <ldap.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <setjmp.h>
+#include "alloc.h"
+#include "byte.h"
+#include "response.h"
+#include "askldap.h"
+#include "dns.h"
+
+static LDAP* ldap_con;
+static sigjmp_buf stack_context;
+
+static struct {
+ char ldaphosts[256];
+ const char* basedn;
+ char binddn[256];
+ char bindpwd[16];
+ struct timeval timeout;
+ int verbose;
+ int initialized;
+} options;
+
+struct zonerecord {
+ char zonedn[256];
+ char zonename[64];
+ char class[16];
+ char type[16];
+ char adminmailbox[64];
+ char zonemaster[64];
+ unsigned long serial, refresh, retry, expire, minimum;
+ int ttl;
+ int timestamp;
+};
+
+struct resourcerecord {
+ char qualifieddomainname[256];
+ char class[16];
+ char type[16];
+ char ipaddr[8][4];
+ int numipaddrs;
+ char cname[256];
+ unsigned int preference;
+ int ttl;
+ int timestamp;
+ int additionalinfo;
+ struct resourcerecord* next;
+};
+
+enum { ASKLDAP_RETRY = 1, ASKLDAP_RETURN = 2, ASKLDAP_RECONNECT = 3 };
+
+static
+void assert_ldap(int err)
+{
+ static int retries;
+ switch (err) {
+ case LDAP_SUCCESS:
+ return;
+ case LDAP_TIMELIMIT_EXCEEDED:
+ fprintf(stderr, "Warning: %s\n", ldap_err2string(err));
+ retries++;
+ if (retries<3)
+ siglongjmp(stack_context, ASKLDAP_RETRY);
+ retries = 0;
+ siglongjmp(stack_context, ASKLDAP_RETURN);
+ case LDAP_TIMEOUT:
+ case LDAP_NO_SUCH_OBJECT:
+ fprintf(stderr, "Warning: %s\n", ldap_err2string(err));
+ siglongjmp(stack_context, ASKLDAP_RETURN);
+ case LDAP_BUSY:
+ case LDAP_UNAVAILABLE:
+ case LDAP_UNWILLING_TO_PERFORM:
+ case LDAP_SERVER_DOWN:
+ fprintf(stderr, "Warning: %s\n", ldap_err2string(err));
+ siglongjmp(stack_context, ASKLDAP_RECONNECT);
+ default:
+ fprintf(stderr, "Fatal error: %s\n", ldap_err2string(err));
+#ifdef _DEBUG
+ abort();
+#else
+ exit(1);
+#endif
+ }
+}
+
+void free_domainrecords(struct resourcerecord* anchor)
+{
+ struct resourcerecord* ptr;
+ for (ptr = anchor; ptr; ptr = anchor) {
+ anchor = anchor->next;
+ alloc_free(ptr);
+ }
+}
+
+static
+void fill_resourcerecord(struct resourcerecord* rr, LDAPMessage* m, const char* zonename)
+{
+ BerElement* ber = NULL;
+ char* attr;
+
+ byte_zero(rr, sizeof(struct resourcerecord));
+ strcpy(rr->class, "IN");
+ for (attr = ldap_first_attribute(ldap_con, m, &ber); attr; attr = ldap_next_attribute(ldap_con, m, ber)) {
+ struct berval** bvals = ldap_get_values_len(ldap_con, m, attr);
+ if (bvals && bvals[0] && bvals[0]->bv_len>0) {
+ if (strcasecmp(attr, "dnsdomainname")==0) {
+ char tmp[64];
+ if (sscanf(bvals[0]->bv_val, "%64s", tmp)==1) {
+ if (zonename[0]!='\0')
+ snprintf(rr->qualifieddomainname, 256, "%s.%s", tmp, zonename);
+ else
+ strncpy(rr->qualifieddomainname, tmp, 256);
+ }
+ } else if (strcasecmp(attr, "dnstype")==0) {
+ if (sscanf(bvals[0]->bv_val, "%16s", rr->type)!=1) {
+ rr->type[0] = '\0';
+ }
+ } else if (strcasecmp(attr, "dnsipaddr")==0) {
+ int k, ip[4];
+ for (k = 0; bvals[k] && k < 8-rr->numipaddrs; k++) {
+ if (sscanf(bvals[k]->bv_val, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4) {
+ rr->ipaddr[rr->numipaddrs][0] = (char)ip[0];
+ rr->ipaddr[rr->numipaddrs][1] = (char)ip[1];
+ rr->ipaddr[rr->numipaddrs][2] = (char)ip[2];
+ rr->ipaddr[rr->numipaddrs][3] = (char)ip[3];
+ rr->numipaddrs++;
+ }
+ }
+ } else if (rr->numipaddrs<8 && strcasecmp(attr, "dnscipaddr")==0) {
+ int ip[4];
+ if (sscanf(bvals[0]->bv_val, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3])==4) {
+ rr->ipaddr[rr->numipaddrs][0] = (char)ip[0];
+ rr->ipaddr[rr->numipaddrs][1] = (char)ip[1];
+ rr->ipaddr[rr->numipaddrs][2] = (char)ip[2];
+ rr->ipaddr[rr->numipaddrs][3] = (char)ip[3];
+ rr->numipaddrs++;
+ }
+ } else if (strcasecmp(attr, "dnscname")==0) {
+ if (sscanf(bvals[0]->bv_val, "%256s", rr->cname)==1) {
+ int len = strlen(rr->cname);
+ if (rr->cname[len-1]!='.' && zonename[0]!='\0') {
+ strcat(rr->cname, ".");
+ strncat(rr->cname, zonename, 252-len);
+ strcat(rr->cname, ".");
+ }
+ } else {
+ rr->cname[0] = '\0';
+ }
+ } else if (strcasecmp(attr, "dnsttl")==0) {
+ if (sscanf(bvals[0]->bv_val, "%d", &rr->ttl)!=1)
+ rr->ttl = 0;
+ } else if (strcasecmp(attr, "dnstimestamp")==0) {
+ if (sscanf(bvals[0]->bv_val, "%d", &rr->timestamp)!=1)
+ rr->timestamp = 0;
+ } else if (strcasecmp(attr, "dnspreference")==0) {
+ if (sscanf(bvals[0]->bv_val, "%u", &rr->preference)!=1)
+ rr->preference = 1;
+ }
+ }
+ ldap_value_free_len(bvals);
+ }
+}
+
+static
+void fill_zonerecord(struct zonerecord* zone, LDAPMessage* m)
+{
+ BerElement* ber = NULL;
+ char* attr;
+
+ byte_zero(zone, sizeof(struct zonerecord));
+ strcpy(zone->class, "IN");
+ for (attr = ldap_first_attribute(ldap_con, m, &ber); attr; attr = ldap_next_attribute(ldap_con, m, ber)) {
+ struct berval** bvals = ldap_get_values_len(ldap_con, m, attr);
+ if (bvals && bvals[0] && bvals[0]->bv_len>0) {
+ if (strcasecmp(attr, "dnstype")==0) {
+ if (sscanf(bvals[0]->bv_val, "%16s", zone->type)!=1)
+ zone->type[0] = '\0';
+ } else if (strcasecmp(attr, "dnsserial")==0) {
+ if (sscanf(bvals[0]->bv_val, "%lu", &zone->serial)!=1)
+ zone->serial = 0;
+ } else if (strcasecmp(attr, "dnsrefresh")==0) {
+ if (sscanf(bvals[0]->bv_val, "%lu", &zone->refresh)!=1)
+ zone->refresh = 0;
+ } else if (strcasecmp(attr, "dnsretry")==0) {
+ if (sscanf(bvals[0]->bv_val, "%lu", &zone->retry)!=1)
+ zone->retry = 0;
+ } else if (strcasecmp(attr, "dnsexpire")==0) {
+ if (sscanf(bvals[0]->bv_val, "%lu", &zone->expire)!=1)
+ zone->expire = 0;
+ } else if (strcasecmp(attr, "dnsminimum")==0) {
+ if (sscanf(bvals[0]->bv_val, "%lu", &zone->minimum)!=1)
+ zone->minimum = 0;
+ } else if (strcasecmp(attr, "dnsadminmailbox")==0) {
+ if (sscanf(bvals[0]->bv_val, "%64s", zone->adminmailbox)!=1)
+ zone->adminmailbox[0] = '\0';
+ } else if (strcasecmp(attr, "dnszonemaster")==0) {
+ if (sscanf(bvals[0]->bv_val, "%64s", zone->zonemaster)!=1)
+ zone->zonemaster[0] = '\0';
+ } else if (strcasecmp(attr, "dnsttl")==0) {
+ if (sscanf(bvals[0]->bv_val, "%d", &zone->ttl)!=1)
+ zone->ttl = 0;
+ } else if (strcasecmp(attr, "dnstimestamp")==0) {
+ if (sscanf(bvals[0]->bv_val, "%d", &zone->timestamp)!=1)
+ zone->timestamp = 0;
+ } else if (strcasecmp(attr, "dnszonename")==0) {
+ if (sscanf(bvals[0]->bv_val, "%s", zone->zonename)!=1)
+ zone->zonename[0] = '\0';
+ }
+ }
+ ldap_value_free_len(bvals);
+ }
+}
+
+static
+int find_ipaddr(const char* queryname, char ip[4])
+{
+ static char *rrattrs[] = { "dnsipaddr", "dnscipaddr", 0 };
+ LDAPMessage* res = NULL;
+ LDAPMessage* m;
+ int ret = 0;
+ char filter[256], domainname[64];
+ const char *zonename = queryname;
+ domainname[0] = '\0';
+ while (*zonename) {
+ int len = snprintf(filter, 256, "(&(dnszonename=%s", zonename);
+ if (filter[len-1]=='.')
+ filter[len-1] = '\0';
+ strncat(filter, ")(objectclass=dnszone)(dnsclass=IN))", 256-len);
+ assert_ldap(ldap_search_st(ldap_con, options.basedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
+ if (m = ldap_first_entry(ldap_con, res)) {
+ char* zonedn = ldap_get_dn(ldap_con, m);
+ if (ldap_next_entry(ldap_con, m))
+ printf("Warning: ambigous zonename for %s in %s\n", zonename, zonedn);
+ if (domainname[0]!='\0') {
+ len = strlen(domainname);
+ if (domainname[len-1]=='.')
+ domainname[len-1] = '\0';
+ snprintf(filter, 256, "(&(|(dnsdomainname=%s)(dnscname=%s))(objectclass=dnsrrset)(dnsclass=IN)(|(dnsipaddr=*)(dnscipaddr=*)))", domainname, domainname);
+ } else {
+ strcpy(filter, "(&(!(dnsdomainname=*))(objectclass=dnsrrset)(dnsclass=IN)(|(dnsipaddr=*)(dnscipaddr=*)))");
+ }
+ ldap_msgfree(res);
+ assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
+ if (m = ldap_first_entry(ldap_con, res)) {
+ struct resourcerecord rr;
+ fill_resourcerecord(&rr, m, "");
+ if (rr.numipaddrs>0) {
+ rr.numipaddrs = rand()%rr.numipaddrs;
+ ip[0] = rr.ipaddr[rr.numipaddrs][0];
+ ip[1] = rr.ipaddr[rr.numipaddrs][1];
+ ip[2] = rr.ipaddr[rr.numipaddrs][2];
+ ip[3] = rr.ipaddr[rr.numipaddrs][3];
+ ret = 1;
+ }
+ }
+ ldap_memfree(zonedn);
+ ldap_msgfree(res); res = NULL;
+ if (ret)
+ return 1;
+ break;
+ }
+ while (*zonename && *zonename!='.') {
+ domainname[zonename-queryname] = *zonename;
+ zonename++;
+ }
+ domainname[zonename-queryname] = *zonename;
+ if (*zonename=='.') {
+ zonename++;
+ domainname[zonename-queryname] = '\0';
+ }
+ }
+ /* sometimes the queryname resolves directly as cname in some other records */
+ snprintf(filter, 256, "(&(dnscname=%s)(objectclass=dnsrrset)(dnsclass=IN)(|(dnsipaddr=*)(dnscipaddr=*)))", queryname);
+ assert_ldap(ldap_search_st(ldap_con, options.basedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
+ if (m = ldap_first_entry(ldap_con, res)) {
+ struct resourcerecord rr;
+ fill_resourcerecord(&rr, m, "");
+ if (rr.numipaddrs>0) {
+ rr.numipaddrs = rand()%rr.numipaddrs;
+ ip[0] = rr.ipaddr[rr.numipaddrs][0];
+ ip[1] = rr.ipaddr[rr.numipaddrs][1];
+ ip[2] = rr.ipaddr[rr.numipaddrs][2];
+ ip[3] = rr.ipaddr[rr.numipaddrs][3];
+ ret = 1;
+ }
+ }
+ ldap_msgfree(res);
+ return ret;
+}
+
+static
+struct resourcerecord* find_reverserecord(const char* queryname, int ip[4])
+{
+ static char *rrattrs[] = { "dnstype", "dnsdomainname", "dnscname", "dnsttl", 0 };
+ LDAPMessage* res = NULL;
+ struct resourcerecord* rr = NULL;
+ LDAPMessage* m;
+ char filter[256];
+ snprintf(filter, 256, "(&(dnscipaddr=%u.%u.%u.%u)(objectclass=dnsrrset)(dnsclass=IN))", ip[0], ip[1], ip[2], ip[3]);
+ assert_ldap(ldap_search_st(ldap_con, options.basedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
+ if (m = ldap_first_entry(ldap_con, res)) {
+ char* rrsetdn = ldap_get_dn(ldap_con, m);
+ char** explodedn = NULL;
+
+ rr = (void*)alloc(sizeof(struct resourcerecord));
+ fill_resourcerecord(rr, m, "");
+ if (ldap_next_entry(ldap_con, m))
+ printf("Warning: ambigous IP-address for %u.%u.%u.%u in dn: %s\n", ip[0], ip[1], ip[2], ip[3], rrsetdn);
+ explodedn = ldap_explode_dn(rrsetdn, 0);
+ if (explodedn[0]) {
+ static char *zoneattrs[] = { "dnszonename", 0 };
+ char zonedn[256];
+ int i, len = 0;
+ struct zonerecord zone;
+
+ zonedn[0] = '\0';
+ for (i = 1; explodedn[i]; i++)
+ len += snprintf(zonedn+len, 256-len, "%s,", explodedn[i]);
+ zonedn[len-1] = '\0';
+ ldap_msgfree(res);
+ assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, "(objectclass=dnszone)", zoneattrs, 0, &options.timeout, &res));
+ m = ldap_first_entry(ldap_con, res);
+ if (m==NULL)
+ printf("Error: parent dn: %s not found for %s\n", zonedn, rrsetdn);
+ fill_zonerecord(&zone, m);
+ len = strlen(rr->qualifieddomainname);
+ if (len==0) {
+ len = strlen(rr->cname);
+ if (rr->cname[len-1]!='.') {
+ strcat(rr->cname, ".");
+ strncat(rr->cname, zone.zonename, 252-len);
+ }
+ } else {
+ /* in those situations where a dnsrrset
+ * defines something like MX or NS for a zone
+ * and also sets a canonical name for the
+ * service. */
+ snprintf(rr->cname, 256, "%s.%s", rr->qualifieddomainname, zone.zonename);
+ }
+ strcpy(rr->type, "PTR");
+ strncpy(rr->qualifieddomainname, queryname, 256);
+ }
+ ldap_memfree(rrsetdn);
+ ldap_value_free(explodedn);
+ }
+ ldap_msgfree(res);
+ return rr;
+}
+
+static
+struct resourcerecord* read_domainrecords(const char* zonedn, const char* domainname, const char* zonename)
+{
+ static char *rrattrs[] = { "dnsdomainname", "dnstype", "dnsttl", "dnscname", "dnsipaddr", "dnscipaddr", "dnstimestamp", "dnspreference", 0 };
+ LDAPMessage* res = NULL;
+ LDAPMessage* m;
+ char filter[256];
+ struct resourcerecord *prev, *anchor = NULL;
+
+ if (domainname[0]) {
+ if (strstr(zonename, "in-addr.arpa")) {
+ unsigned int ip[4];
+ char queryname[256];
+ snprintf(queryname, 256, "%s.%s", domainname, zonename);
+ if (sscanf(queryname, "%3u.%3u.%3u.%3u", &ip[3], &ip[2], &ip[1], &ip[0])!=4)
+ return NULL;
+ snprintf(filter, 256, "(&(dnsipaddr=%u.%u.%u.%u)(objectclass=dnsrrset)(dnsclass=IN))", ip[0], ip[1], ip[2], ip[3]);
+ assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
+ if (m = ldap_first_entry(ldap_con, res)) {
+ struct resourcerecord* rr;
+ rr = (void*)alloc(sizeof(struct resourcerecord));
+ fill_resourcerecord(rr, m, zonename);
+ strncpy(rr->qualifieddomainname, queryname, 256);
+ ldap_msgfree(res);
+ return rr;
+ } else {
+ /* ipaddr not in our baliwick, search the whole tree for canonical ipaddr */
+ ldap_msgfree(res);
+ return find_reverserecord(queryname, ip);
+ }
+ } else {
+ int i;
+ for (i = 0; domainname[i]; i++) {
+ snprintf(filter, 256, (i==0 ? "(&(dnsdomainname=%s)(objectclass=dnsrrset)(dnsclass=IN))" :
+ "(&(dnsdomainname=\\*.%s)(objectclass=dnsrrset)(dnsclass=IN))"), &domainname[i]);
+ assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
+ if (ldap_count_entries(ldap_con, res)>0)
+ break;
+ while (domainname[i] && domainname[i]!='.')
+ i++;
+ }
+ }
+ } else {
+ snprintf(filter, 256, "(&(!(dnsdomainname=*))(objectclass=dnsrrset)(dnsclass=IN))");
+ assert_ldap(ldap_search_st(ldap_con, zonedn, LDAP_SCOPE_SUBTREE, filter, rrattrs, 0, &options.timeout, &res));
+ }
+ for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
+ struct resourcerecord* rr;
+ rr = (void*)alloc(sizeof(struct resourcerecord));
+ fill_resourcerecord(rr, m, zonename);
+ snprintf(rr->qualifieddomainname, 256, "%s%s%s", domainname, domainname[0] ? "." : "", zonename);
+ if (anchor==NULL) {
+ prev = anchor = rr;
+ } else {
+ prev->next = rr;
+ prev = rr;
+ }
+ if (options.verbose&1)
+ printf("\trr: %s %s\n", domainname, rr->type);
+ }
+ ldap_msgfree(res);
+ return anchor;
+}
+
+static
+int read_dnszone(struct zonerecord* zone, const char* zonename)
+{
+ static char *zoneattrs[] = { "dnszonename", "dnstype", "dnsserial", "dnsrefresh", "dnsretry", "dnsexpire", "dnsminimum", "dnszonemaster", "dnsadminmailbox", "dnsttl", "dnstimestamp", 0 };
+ LDAPMessage* res = NULL;
+ LDAPMessage* m;
+ char* dn;
+ char filter[256];
+
+ snprintf(filter, 256, "(&(dnszonename=%s)(objectclass=dnszone)(dnsclass=IN))", zonename);
+ assert_ldap(ldap_search_st(ldap_con, options.basedn, LDAP_SCOPE_SUBTREE, filter, zoneattrs, 0, &options.timeout, &res));
+ m = ldap_first_entry(ldap_con, res);
+ if (m==NULL) {
+ ldap_msgfree(res);
+ return 0;
+ }
+ dn = ldap_get_dn(ldap_con, m);
+ fill_zonerecord(zone, m);
+ m = ldap_next_entry(ldap_con, m);
+ if (m) {
+ char* otherdn = ldap_get_dn(ldap_con, m);
+ printf("Warning: ambigous zonename found in dn: %s and dn: %s\n", dn, otherdn);
+ ldap_memfree(otherdn);
+ }
+ strncpy(zone->zonedn, dn, 256);
+ ldap_memfree(dn);
+ ldap_msgfree(res);
+ return 1;
+}
+
+static
+void djb_name(const char* dotname, char* djbname)
+{
+ const char* c = dotname;
+ int i, k;
+ for (i = 0; *c; c++) {
+ k = i;
+ while (*c!='.') {
+ k++;
+ djbname[k] = *c;
+ if (*c=='\0') {
+ djbname[i] = k-i-1;
+ return;
+ }
+ c++;
+ }
+ djbname[i] = k-i;
+ i = k+1;
+ }
+ djbname[i] = '\0';
+}
+
+static
+void djb_type(const char* dottype, char djbtype[2])
+{
+ djbtype[0] = '\0';
+ if (strcasecmp(dottype, "A")==0)
+ djbtype[1] = 001;
+ else if (strcasecmp(dottype, "NS")==0)
+ djbtype[1] = 002;
+ else if (strcasecmp(dottype, "CNAME")==0)
+ djbtype[1] = 005;
+ else if (strcasecmp(dottype, "SOA")==0)
+ djbtype[1] = 006;
+ else if (strcasecmp(dottype, "PTR")==0)
+ djbtype[1] = 014;
+ else if (strcasecmp(dottype, "MX")==0)
+ djbtype[1] = 017;
+ else if (strcasecmp(dottype, "TXT")==0)
+ djbtype[1] = 020;
+}
+
+static
+void split_djbstyle(const char* djbname, char* domainname, char* zonename, int offset)
+{
+ int i, k, m = 0, n = 0;
+ for (i = *djbname; i; i = *++djbname) {
+ if (offset>0) {
+ offset--;
+ for (k = m; k<m+i; k++) {
+ domainname[k] = *++djbname;
+ }
+ domainname[k] = '.';
+ m = k+1;
+ } else {
+ for (k = n; k<n+i; k++) {
+ zonename[k] = *++djbname;
+ }
+ zonename[k] = '.';
+ n = k+1;
+ }
+ }
+ domainname[m>0 ? m-1 : 0] = '\0';
+ zonename[n>0 ? n-1 : 0] = '\0';
+}
+
+static
+void build_response_section(struct resourcerecord *rr, char qtype[2], int section)
+{
+ char djbname[256], djbtype[2];
+ djb_name(rr->qualifieddomainname, djbname);
+ djb_type(rr->type, djbtype);
+ if (byte_equal(djbtype, 2, DNS_T_A)) {
+ if (byte_equal(qtype, 2, DNS_T_A) || byte_equal(qtype, 2, DNS_T_ANY)) {
+ response_rstart(djbname, djbtype, rr->ttl);
+ response_addbytes(rr->ipaddr[rand()%rr->numipaddrs], 4);
+ response_rfinish(section);
+ }
+ } else if (byte_equal(djbtype, 2, DNS_T_CNAME)) {
+ response_rstart(djbname, djbtype, rr->ttl);
+ djb_name(rr->cname, djbname);
+ response_addname(djbname);
+ response_rfinish(section);
+ } else if (byte_equal(djbtype, 2, DNS_T_NS)) {
+ if (byte_equal(qtype, 2, DNS_T_NS) || byte_equal(qtype, 2, DNS_T_ANY)) {
+ response_rstart(djbname, djbtype, rr->ttl);
+ if (rr->cname[0]) {
+ djb_name(rr->cname, djbname);
+ response_addname(djbname);
+ rr->additionalinfo = 1;
+ } else {
+ response_addbytes(rr->ipaddr[rand()%rr->numipaddrs], 4);
+ }
+ response_rfinish(section);
+ }
+ } else if (byte_equal(djbtype, 2, DNS_T_PTR)) {
+ response_rstart(djbname, djbtype, rr->ttl);
+ djb_name(rr->cname, djbname);
+ response_addname(djbname);
+ response_rfinish(section);
+ } else if (byte_equal(djbtype, 2, DNS_T_MX)) {
+ if (byte_equal(qtype, 2, DNS_T_MX) || byte_equal(qtype, 2, DNS_T_ANY)) {
+ char tmp[2];
+ response_rstart(djbname, djbtype, rr->ttl);
+ tmp[0] = rr->preference/0x100;
+ tmp[1] = rr->preference%0x100;
+ response_addbytes(tmp, 2);
+ if (rr->cname[0]) {
+ djb_name(rr->cname, djbname);
+ response_addname(djbname);
+ rr->additionalinfo = 1;
+ } else {
+ response_addbytes(rr->ipaddr[rand()%rr->numipaddrs], 4);
+ }
+ response_rfinish(section);
+ }
+ }
+}
+
+static
+void build_soa_section(struct zonerecord *zone, int section)
+{
+ time_t now;
+ char defaultsoa[20];
+ char djbname[256];
+ char zonesoa[20];
+ unsigned long tmp;
+ time(&now);
+ djb_name(zone->zonename, djbname);
+ response_rstart(djbname, DNS_T_SOA, zone->ttl);
+ djb_name(zone->zonemaster, djbname);
+ response_addname(djbname);
+ djb_name(zone->adminmailbox, djbname);
+ response_addname(djbname);
+ uint32_pack_big(defaultsoa, now);
+ if (byte_equal(defaultsoa,4,"\0\0\0\0"))
+ defaultsoa[3] = 1;
+ byte_copy(defaultsoa + 4, 16, "\0\0\100\000\0\0\010\000\0\020\000\000\0\0\012\000");
+ if (zone->serial==0)
+ uint32_unpack_big(defaultsoa, &tmp);
+ else
+ tmp = zone->serial;
+ uint32_pack_big(zonesoa, tmp);
+ if (zone->refresh==0)
+ uint32_unpack_big(defaultsoa+4, &tmp);
+ else
+ tmp = zone->refresh;
+ uint32_pack_big(zonesoa+4, tmp);
+ if (zone->retry==0)
+ uint32_unpack_big(defaultsoa+8, &tmp);
+ else
+ tmp = zone->retry;
+ uint32_pack_big(zonesoa+8, tmp);
+ if (zone->expire==0)
+ uint32_unpack_big(defaultsoa+12, &tmp);
+ else
+ tmp = zone->expire;
+ uint32_pack_big(zonesoa+12, tmp);
+ if (zone->minimum==0)
+ uint32_unpack_big(defaultsoa+16, &tmp);
+ else
+ tmp = zone->minimum;
+ uint32_pack_big(zonesoa+16, tmp);
+ response_addbytes(zonesoa, 20);
+ response_rfinish(section);
+}
+
+static
+void build_additional_section(struct resourcerecord *rr)
+{
+ char djbname[256], ip[4];
+ if (rr->additionalinfo && find_ipaddr(rr->cname, ip)) {
+ djb_name(rr->cname, djbname);
+ response_rstart(djbname, DNS_T_A, rr->ttl);
+ response_addbytes(ip, 4);
+ response_rfinish(RESPONSE_ADDITIONAL);
+ }
+}
+
+static
+int connect_and_bind()
+{
+ ldap_con = ldap_init(options.ldaphosts, LDAP_PORT);
+ if (ldap_simple_bind_s(ldap_con, options.binddn, options.bindpwd)==LDAP_SUCCESS) {
+ printf("Connected to %s as \"%s\"\n", options.ldaphosts, options.binddn);
+ return 1;
+ }
+ ldap_con = NULL;
+ return 0;
+}
+
+int askldap_query(const char* djbdomainname, char qtype[2])
+{
+ int offset;
+ char domainname[64], zonename[64];
+ struct zonerecord zoneinfo;
+ int answer_ok = 0, flagsoa = 0, flagns = 0;
+ if (!options.initialized)
+ return 0;
+ switch (sigsetjmp(stack_context, 1)) {
+ default:
+ if (ldap_con==NULL && !connect_and_bind())
+ return answer_ok;
+ break;
+ case ASKLDAP_RECONNECT:
+ if (connect_and_bind())
+ break;
+ return answer_ok;
+ case ASKLDAP_RETURN:
+ return answer_ok;
+ }
+ for (offset = 0; offset<32; offset++) {
+ struct resourcerecord *rransw, *rrauth, *rr;
+
+ split_djbstyle(djbdomainname, domainname, zonename, offset);
+ if (zonename[0]=='\0') return 0;
+ if (!read_dnszone(&zoneinfo, zonename))
+ continue;
+ rransw = read_domainrecords(zoneinfo.zonedn, domainname, zonename);
+ rrauth = NULL;
+ if (offset==0) {
+ /* query is in our bailiwick */
+ if (byte_equal(qtype, 2, DNS_T_ANY) || byte_equal(qtype, 2, DNS_T_SOA)) {
+ build_soa_section(&zoneinfo, RESPONSE_ANSWER);
+ flagsoa = 1;
+ }
+ for (rr = rransw; rr; rr = rr->next) {
+ build_response_section(rr, qtype, RESPONSE_ANSWER);
+ answer_ok = 1;
+ }
+ if (!flagsoa) {
+ build_soa_section(&zoneinfo, RESPONSE_AUTHORITY);
+ flagsoa = 1;
+ }
+ if (!byte_equal(qtype, 2, DNS_T_ANY) && !byte_equal(qtype, 2, DNS_T_NS)) {
+ for (rr = rransw; rr; rr = rr->next)
+ if (strcmp(rr->type, "NS")==0) {
+ build_response_section(rr, DNS_T_NS, RESPONSE_AUTHORITY);
+ flagns = 1;
+ }
+ }
+ } else {
+ for (rr = rransw; rr; rr = rr->next) {
+ if (strcmp(rr->type, "NS")==0) {
+ build_response_section(rr, qtype, RESPONSE_AUTHORITY);
+ flagns = 1;
+ }
+ }
+ if (!flagns) {
+ for (rr = rransw; rr; rr = rr->next) {
+ build_response_section(rr, qtype, RESPONSE_ANSWER);
+ answer_ok = 1;
+ }
+ if (answer_ok) {
+ rrauth = read_domainrecords(zoneinfo.zonedn, "", zonename);
+ } else {
+ build_soa_section(&zoneinfo, RESPONSE_AUTHORITY);
+ flagsoa = 1;
+ }
+ }
+ for (rr = rrauth; rr; rr = rr->next) {
+ if (strcmp(rr->type, "NS")==0) {
+ build_response_section(rr, DNS_T_NS, RESPONSE_AUTHORITY);
+ flagns = 1;
+ }
+ }
+ }
+ for (rr = rransw; rr; rr = rr->next)
+ build_additional_section(rr);
+ for (rr = rrauth; rr; rr = rr->next)
+ build_additional_section(rr);
+ free_domainrecords(rransw);
+ free_domainrecords(rrauth);
+ break;
+ }
+ return answer_ok || flagsoa || flagns;
+}
+
+void askldap_init(const char* ldaphost, const char* basedn, const char* binddn, const char* passwd)
+{
+ strncpy(options.ldaphosts, ldaphost, 256);
+ options.basedn = basedn;
+ if (binddn) strncpy(options.binddn, binddn, 256);
+ if (passwd) strncpy(options.bindpwd, passwd, 16);
+ /* LDAP timeout is hardcoded to 2/10 second.
+ * This must be enough because bindoperations usually
+ * timeout after one second and here we usually have to
+ * send five queries to the LDAP-server */
+ options.timeout.tv_sec = 1;
+ options.timeout.tv_usec = 200000;
+ options.verbose = 0;
+ options.initialized = 1;
+ connect_and_bind();
+}
+
diff -Naur djbdns-1.05.orig/askldap.h djbdns-1.05/askldap.h
--- djbdns-1.05.orig/askldap.h Thu Jan 1 01:00:00 1970
+++ djbdns-1.05/askldap.h Tue Aug 13 14:30:22 2002
@@ -0,0 +1,10 @@
+/* Patch for tinydns to pass DNS-query to LDAP in favour of a cdb lookup.
+ * $Id$
+ * Copyright 2002 <jacob.rief@tiscover.com>
+ */
+
+extern
+int askldap_query(const char* djbdomainname, char qtype[2]);
+
+extern
+void askldap_init(const char* ldaphost, const char* basedn, const char* binddn, const char* passwd);
diff -Naur djbdns-1.05.orig/ldap.lib djbdns-1.05/ldap.lib
--- djbdns-1.05.orig/ldap.lib Thu Jan 1 01:00:00 1970
+++ djbdns-1.05/ldap.lib Tue Aug 13 14:29:53 2002
@@ -0,0 +1 @@
+-lldap -llber
diff -Naur djbdns-1.05.orig/server.c djbdns-1.05/server.c
--- djbdns-1.05.orig/server.c Sun Feb 11 22:11:45 2001
+++ djbdns-1.05/server.c Tue Aug 13 14:29:15 2002
@@ -11,6 +11,7 @@
#include "qlog.h"
#include "response.h"
#include "dns.h"
+#include "askldap.h"
extern char *fatal;
extern char *starting;
@@ -79,6 +80,7 @@
return 0;
}
+
int main()
{
char *x;
@@ -90,6 +92,19 @@
if (!ip4_scan(x,ip))
strerr_die3x(111,fatal,"unable to parse IP address ",x);
+ x = env_get("LDAPHOSTS");
+ if (x) {
+ char *basedn = env_get("LDAPBASEDN");
+ char *binddn = env_get("LDAPBINDDN");
+ char *bindpwd = env_get("LDAPPASSWD");
+ if (basedn)
+ askldap_init(x, basedn, binddn, bindpwd);
+ if (bindpwd) {
+ int len = str_len(bindpwd);
+ while (len) bindpwd[--len] = 'x';
+ }
+ }
+
udp53 = socket_udp();
if (udp53 == -1)
strerr_die2sys(111,fatal,"unable to create UDP socket: ");
diff -Naur djbdns-1.05.orig/tdlookup.c djbdns-1.05/tdlookup.c
--- djbdns-1.05.orig/tdlookup.c Sun Feb 11 22:11:45 2001
+++ djbdns-1.05/tdlookup.c Tue Aug 13 14:29:29 2002
@@ -8,6 +8,7 @@
#include "dns.h"
#include "seek.h"
#include "response.h"
+#include "askldap.h"
static int want(const char *owner,const char type[2])
{
@@ -285,10 +286,13 @@
char key[6];
tai_now(&now);
+ if (askldap_query(q, qtype))
+ return 1;
+
fd = open_read("data.cdb");
if (fd == -1) return 0;
cdb_init(&c,fd);
-
+
byte_zero(clientloc,2);
key[0] = 0;
key[1] = '%';

View File

@@ -1,24 +0,0 @@
# include this file into Your slapd.conf for openldap-1.2.x
# $Id: dns.at.conf,v 1.5 2000/12/04 12:59:57 jrief Exp $
attribute DNSzonename cis
attribute DNSserial cis
attribute DNSrefresh cis
attribute DNSretry cis
attribute DNSexpire cis
attribute DNSminimum cis
attribute DNSadminmailbox cis
attribute DNSzonemaster cis
attribute DNStype cis
attribute DNSclass cis
attribute DNSdomainname cis
attribute DNSipaddr cis
attribute DNScname cis
attribute DNSpreference cis
attribute DNSttl cis
attribute DNStimestamp cis
#attribute DNSaliasedobjectname cis
#attribute DNSrr cis
#attribute DNSrrcount cis
#attribute DNSmacaddress cis

View File

@@ -1,45 +0,0 @@
# include this file into Your slapd.conf for openldap-1.2.x
# $Id: dns.oc.conf,v 1.4 2000/12/01 14:48:25 jrief Exp $
# child of anybody
# information to setup a DNS zone
objectclass DNSzone
requires
objectclass,
cn
allows
DNSzonename,
DNSserial,
DNSrefresh,
DNSretry,
DNSexpire,
DNSminimum,
DNSadminmailbox,
DNSzonemaster,
DNStype,
DNSclass,
DNSttl,
DNStimestamp
#DNSrrcount,
# child of a DNSzone
# information to setup a resource record
objectclass DNSrrset
requires
objectclass,
cn
allows
DNSdomainname,
DNSclass,
DNStype,
DNSipaddr,
DNScname,
DNSpreference,
DNSttl,
DNStimestamp
#DNSaliasedobjectname,
#DNSrr,
#DNSmacaddress,

View File

@@ -1,103 +1,125 @@
# schema for DNS data
# include this file into Your slapd.conf for openldap-2.0.x
# $Id: dns.schema,v 1.8 2001/08/09 10:35:49 jrief Exp $
# $Id: dns.schema,v 1.9 2003/01/20 14:33:25 jrief Exp $
attributetype ( 1.3.6.1.4.1.7222.1.4.1
NAME 'DNSzonename'
NAME 'dnszonename'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.2
NAME 'DNSserial'
NAME 'dnsserial'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.3
NAME 'DNSrefresh'
NAME 'dnsrefresh'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.4
NAME 'DNSretry'
NAME 'dnsretry'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.5
NAME 'DNSexpire'
NAME 'dnsexpire'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.6
NAME 'DNSminimum'
NAME 'dnsminimum'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.7
NAME 'DNSadminmailbox'
NAME 'dnsadminmailbox'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.8
NAME 'DNSzonemaster'
NAME 'dnszonemaster'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.9
NAME 'DNStype'
NAME 'dnstype'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.10
NAME 'DNSclass'
NAME 'dnsclass'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.11
NAME 'DNSdomainname'
NAME 'dnsdomainname'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.12
NAME 'DNSipaddr'
NAME 'dnsipaddr'
EQUALITY numericStringMatch
SUBSTR numericStringSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} )
attributetype ( 1.3.6.1.4.1.7222.1.4.13
NAME 'DNScipaddr'
NAME 'dnscipaddr'
EQUALITY numericStringMatch
SUBSTR numericStringSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} )
attributetype ( 1.3.6.1.4.1.7222.1.4.14
NAME 'DNScname'
NAME 'dnscname'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.15
NAME 'DNSpreference'
NAME 'dnspreference'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.16
NAME 'DNSrr'
NAME 'dnsrr'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.17
NAME 'DNSttl'
NAME 'dnsttl'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.18
NAME 'DNStimestamp'
NAME 'dnstimestamp'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.21
NAME 'NIChandle'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} )
attributetype ( 1.3.6.1.4.1.7222.1.4.22
NAME 'TIShandle'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} )
attributetype ( 1.3.6.1.4.1.7222.1.4.23
NAME 'dnslocation'
EQUALITY caseExactIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{2}
SINGLE-VALUE )
objectclass ( 1.3.6.1.4.1.7222.1.4.19
NAME 'DNSzone'
NAME 'dnszone'
MUST ( objectclass $ cn )
MAY ( DNSzonename $ DNSserial $ DNSrefresh $ DNSretry $ DNSexpire
$ DNSminimum $ DNSadminmailbox $ DNSzonemaster $ DNStype $ DNSclass
$ DNSttl $ DNStimestamp $ owner ) )
MAY ( dnszonename $ dnsserial $ dnsrefresh $ dnsretry $ dnsexpire
$ dnsminimum $ dnsadminmailbox $ dnszonemaster $ dnstype $ dnsclass
$ dnsttl $ dnstimestamp $ owner $ NIChandle $ TIShandle $ dnslocation ) )
objectclass ( 1.3.6.1.4.1.7222.1.4.20
NAME 'DNSrrset'
SUP DNSzone
NAME 'dnsrrset'
SUP dnszone
MUST ( objectclass $ cn )
MAY ( DNSdomainname $ DNSrr $ DNSclass $ DNStype $ DNSipaddr $ DNScipaddr
$ DNScname $ DNSpreference $ DNSttl $ DNStimestamp $ owner ) )
MAY ( dnsdomainname $ dnsrr $ dnsclass $ dnstype $ dnsipaddr $ dnscipaddr
$ dnscname $ dnspreference $ dnsttl $ dnstimestamp $ owner ) )
objectclass ( 1.3.6.1.4.1.7222.1.4.24
NAME 'dnsloccodes'
MUST ( objectclass $ dnslocation )
MAY ( dnsipaddr $ uid $ description ) )

126
dns.schema-2.2 Normal file
View File

@@ -0,0 +1,126 @@
# schema for DNS data
# include this file into Your slapd.conf for openldap-2.0.x
# $Id: dns.schema,v 1.9 2001/11/06 08:01:51 config Exp $
attributetype ( 1.3.6.1.4.1.7222.1.4.1
NAME 'dnszonename'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.2
NAME 'dnsserial'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.3
NAME 'dnsrefresh'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.4
NAME 'dnsretry'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.5
NAME 'dnsexpire'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.6
NAME 'dnsminimum'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.7
NAME 'dnsadminmailbox'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.8
NAME 'dnszonemaster'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.9
NAME 'dnstype'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.10
NAME 'dnsclass'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.11
NAME 'dnsdomainname'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.12
NAME 'dnsipaddr'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} )
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.13
NAME 'dnscipaddr'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} )
attributetype ( 1.3.6.1.4.1.7222.1.4.14
NAME 'dnscname'
SUP name )
attributetype ( 1.3.6.1.4.1.7222.1.4.15
NAME 'dnspreference'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.16
NAME 'dnsrr'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.17
NAME 'dnsttl'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.18
NAME 'dnstimestamp'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.7222.1.4.21
NAME 'NIChandle'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} )
attributetype ( 1.3.6.1.4.1.7222.1.4.22
NAME 'TIShandle'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} )
objectclass ( 1.3.6.1.4.1.7222.1.4.19
NAME 'dnszone'
MUST ( objectclass $ cn )
MAY ( dnszonename $ dnsserial $ dnsrefresh $ dnsretry $ dnsexpire
$ dnsminimum $ dnsadminmailbox $ dnszonemaster $ dnstype $ dnsclass
$ dnsttl $ dnstimestamp $ owner $ NIChandle $ TIShandle ) )
objectclass ( 1.3.6.1.4.1.7222.1.4.20
NAME 'dnsrrset'
SUP dnszone
MUST ( objectclass $ cn )
MAY ( dnsdomainname $ dnsrr $ dnsclass $ dnstype $ dnsipaddr $ dnscipaddr
$ dnscname $ dnspreference $ dnsttl $ dnstimestamp $ owner ) )

190
export-ldap2dns.pl Executable file
View File

@@ -0,0 +1,190 @@
#!/usr/bin/perl
# Script to import data from DNS into LDAP
# Copyright 2000, Jacob Rief
# $Id: export-ldap2dns.pl,v 1.1 2002/09/03 10:43:40 jrief Exp $
###### configure this ######
# remember to allow zone transfers from Your nameserver
my $LDAPHOST = "localhost";
my $LDAPBINDDN = "uid=root,o=tiscover";
my $LDAPPASSWD = "1Fnegu!";
my $BASEDN = "ou=dns,o=tiscover";
###### don't edit below this line ######
use strict;
use Net::LDAP qw(LDAP_NO_SUCH_OBJECT LDAP_ALREADY_EXISTS);
my $ldap;
initialize();
migrate_zones();
sub initialize
{
$ldap = Net::LDAP->new($LDAPHOST) or die "Can't connect to LDAP server";
my $mesg = $ldap->bind( dn => $LDAPBINDDN, password => $LDAPPASSWD );
die "Unable to bind to LDAP ", $mesg->error if ($mesg->code);
}
sub migrate_zones
{
my $mesg = $ldap->search(base=>$BASEDN, scope=>'sub', filter=>"(objectclass=dnszone)");
my @oldzones = $mesg->entries();
foreach my $oldzone (@oldzones) {
my @zonename = $oldzone->get_value('dnszonename');
my $masterdn = dn_domain($zonename[0]) if ($#zonename>=0);
foreach my $zn (@zonename) {
my $newdn = dn_domain($zn);
next unless ($newdn =~ /^dc=\s*([^,]+).*/);
my $dc = $1;
my $soarecord = $oldzone->get_value('dnsserial')." "
.$oldzone->get_value('dnsrefresh')." "
.$oldzone->get_value('dnsretry')." "
.$oldzone->get_value('dnsexpire')." "
.$oldzone->get_value('dnsminimum');
my %attrs = ( 'objectclass' => [ qw(dNSDomain dcObject) ], 'dc' => $dc, 'sOARecord' => [ $soarecord ] );
$mesg = $ldap->modify($newdn, 'replace' => \%attrs);
while ($mesg->code()==LDAP_NO_SUCH_OBJECT) {
repeat:
$mesg = $ldap->add($newdn, 'attrs' => list_attrs(\%attrs));
last unless ($mesg->code()==LDAP_NO_SUCH_OBJECT);
my $filldn = $newdn;
do {
die("Invalid dn: $filldn") unless ($filldn =~ /[^,]+,((dc=[^,]+),.+)/);
$filldn = $1;
$mesg = $ldap->add($filldn, 'attrs' => [ 'objectclass'=>'dcObject', 'dc'=>$2) ]);
} until ($mesg->code()==0 || $mesg->code()==LDAP_ALREADY_EXISTS);
goto repeat;
}
die("Error from LDAP: \"".$mesg->error()."\" on $newdn (".$mesg->code().")") if ($mesg->code());
if ($masterdn ne $newdn) {
$mesg = $ldap->modify($masterdn, 'replace' => [ 'objectclass' => 'alias' ]);
$mesg = $ldap->modify($masterdn, 'add' => [ 'alias' => $newdn ]);
$mesg = $ldap->modify($newdn, 'replace' => [ 'objectclass' => 'alias', 'alias' => $masterdn ]);
}
migrate_rrrecords($zn, $newdn, $oldzone->dn());
}
}
}
sub migrate_rrrecords
{
my ($zonename, $newzonedn, $oldzonedn) = (@_);
my @objectclass = qw(dNSDomain dcObject);
my $mesg = $ldap->search(base=>$oldzonedn, scope=>'sub', filter=>"(objectclass=dnsrrset)");
my @rrsets = $mesg->entries();
foreach my $rr (@rrsets) {
my $domainname = $rr->get_value('dnsdomainname');
my $dn = dn_domain(length($domainname)>0 ? "$domainname.$zonename" : "$zonename");
my $type = $rr->get_value('dnstype');
print "dn: $dn (type: $type)\n";
next unless ($dn =~ /^dc=\s*([^,]+).*/);
my %attrs = read_ldapobject($dn);
$attrs{'objectclass'} = \@objectclass;
$attrs{'dc'} = $1;
my @cname = $rr->get_value('dnscname');
my @ipaddr = $rr->get_value('dnsipaddr');
my $cipaddr = $rr->get_value('dnscipaddr');
if ($type eq "A") {
push(@ipaddr, $cipaddr) if (length($cipaddr)>5);
my $ta = $attrs{'aRecord'};
push(@$ta, @ipaddr) if ($#ipaddr>=0);
} elsif ($type eq "NS") {
my $ta = $attrs{'NSRecord'};
foreach my $cn (@cname) {
if ($cn =~ /\.$/) {
push(@$ta, $cn);
} else {
push(@$ta, "$cn.$zonename");
}
}
} elsif ($type eq "MX") {
my $ta = $attrs{'MXRecord'};
my $pref = $rr->get_value('dnspreference');
foreach my $cn (@cname) {
if ($cn =~ /\.$/) {
push(@$ta, "$pref $cn");
} else {
push(@$ta, "$pref $cn.$zonename");
}
}
} elsif ($type eq "CNAME") {
my $ta = $attrs{'cNAMERecord'};
die("no CNAME") unless($#cname>=0);
foreach my $cn (@cname) {
if ($cn =~ /\.$/) {
push(@$ta, $cn);
} else {
push(@$ta, "$cn.$zonename");
}
}
}
remove_unused(\%attrs);
$mesg = $ldap->modify($dn, 'replace' => \%attrs);
while ($mesg->code()==LDAP_NO_SUCH_OBJECT) {
repeat:
$mesg = $ldap->add($dn, 'attrs' => list_attrs(\%attrs));
last unless ($mesg->code()==LDAP_NO_SUCH_OBJECT);
my $filldn = $dn;
do {
die("Invalid dn: $filldn") unless ($filldn =~ /[^,]+,((dc=[^,]+),.+)/);
$filldn = $1;
$mesg = $ldap->add($filldn, 'attrs' => [ qw(objectclass dcObject dc $2) ]);
} until ($mesg->code()==0 || $mesg->code()==LDAP_ALREADY_EXISTS);
goto repeat;
}
die("Error from LDAP: \"".$mesg->error()."\" on $dn") if ($mesg->code());
}
}
sub dn_domain
{
my ($domain)=(@_);
my @p = split /\./, lc($domain);
my $dc = 'dc='.join(',dc=', @p);
$dc .= ','.$BASEDN;
return $dc;
}
sub list_attrs
{
my $attr = shift;
my (@list, $key, $value);
while (($key, $value) = each %$attr) {
push(@list, $key => $value);
}
return \@list;
}
sub read_ldapobject
{
my $dn = shift;
my %attrs = ();
$attrs{'aRecord'} = [];
$attrs{'cNAMERecord'} = [];
$attrs{'MXRecord'} = [];
$attrs{'NSRecord'} = [];
my $mesg = $ldap->search(base => $dn, scope => 'base', filter => "(objectclass=dcObject)");
return %attrs if ($mesg->code()==LDAP_NO_SUCH_OBJECT);
return %attrs if ($mesg->count()==0);
my $obj = $mesg->entry(0);
my @tempa = $obj->get_value('aRecord');
$attrs{'aRecord'} = \@tempa if ($#tempa>=0);
my @tempcname = $obj->get_value('cNAMERecord');
$attrs{'cNAMERecord'} = \@tempcname if ($#tempcname>=0);
my @tempmx = $obj->get_value('MXRecord');
$attrs{'MXRecord'} = \@tempmx if ($#tempmx>=0);
my @tempns = $obj->get_value('NSRecord');
$attrs{'NSRecord'} = \@tempns if ($#tempns>=0);
return %attrs;
}
sub remove_unused
{
my $hash = shift;
foreach my $key (keys %$hash) {
my $ta = $$hash{$key};
next if ($key eq "dc");
delete $$hash{$key} if ($#$ta<0);
}
}

BIN
ldap2dns-dbg Executable file

Binary file not shown.

134
ldap2dns-ldapuri.patch Normal file
View File

@@ -0,0 +1,134 @@
--- ldap2dns-0.3.1-orig/ldap2dns.c 2002-08-02 17:19:36.000000000 +0200
+++ ldap2dns-0.3.1/ldap2dns.c 2002-09-01 13:31:52.000000000 +0200
@@ -14,7 +14,7 @@
#include <unistd.h>
#define UPDATE_INTERVALL 59
-#define LDAP_CONF "/etc/ldap.conf"
+#define LDAP_CONF "/etc/ldap/ldap.conf"
#define OUTPUT_DATA 1
#define OUTPUT_DB 2
#define MAXHOSTS 10
@@ -85,6 +85,7 @@
char searchbase[128];
char binddn[128];
char hostname[MAXHOSTS][128];
+ char urildap[MAXHOSTS][128];
int port[MAXHOSTS];
char password[128];
int usedhosts;
@@ -94,6 +95,7 @@
int verbose;
char ldifname[128];
char exec_command[128];
+ int use_tls[MAXHOSTS];
} options;
@@ -130,7 +132,8 @@
static void print_usage(void)
{
print_version();
- printf("usage: ldap2dns[d] [-D binddn] [-b searchbase] [-o data|db] [-h host] [-p port] [-w password] [-L[filename]] [-u numsecs] [-v[v]] [-V]\n\n");
+ printf("usage: ldap2dns[d] [-D binddn] [-b searchbase] [-o data|db] [-h host] [-p port] [-H hostURI] "
+ "[-w password] [-L[filename]] [-u numsecs] [-v[v]] [-V]\n\n");
printf("ldap2dns connects to an LDAP server reads the DNS information stored in objectclasses\n"
"\t\tDNSzone and DNSrrset and writes a file to be used by tinydns or named.\n"
"\t\tldap2dnsd starts as background-job and continouesly updates DNS information.\n");
@@ -143,6 +146,7 @@
printf(" -L[filename] Print output in LDIF format for reimport\n");
printf(" -h host\tHostname of LDAP server, defaults to localhost\n");
printf(" -p port\tPortnumber to connect to LDAP server, defaults to %d\n", LDAP_PORT);
+ printf(" -H hostURI\tURI (ldap://hostname or ldaps://hostname of LDAP server\n");
printf(" -u numsecs\tUpdate DNS data after numsecs. Defaults to %d if started as daemon.\n\t\t"
"Important notice: data.cdb is rewritten only after DNSserial in DNSzone is increased.\n",
UPDATE_INTERVALL);
@@ -159,7 +163,18 @@
options.usedhosts = 0;
for (i = 0; i<MAXHOSTS; i++) {
- if ((k = sscanf(buf, "%128s:%d %512[A-Za-z0-9 .:_+-]", value, &port, rest))>=2) {
+ if (!strncasecmp(buf, "ldaps://", 8) || !strncasecmp(buf, "ldap://", 7)) {
+ // LDAP-URI is given/found, at the moment only the standard-ports 389 and 636 are supported
+ if (!strncasecmp(buf, "ldap://", 7))
+ options.use_tls[i] = 1;
+ if ((k = sscanf(buf, "%128s %512[A-Za-z0-9 .:/_+-]", value, rest))>=1) {
+ strcpy(options.urildap[i], value);
+ options.usedhosts++;
+ if (k==1)
+ break;
+ buf = rest;
+ } else break;
+ } else if ((k = sscanf(buf, "%128s:%d %512[A-Za-z0-9 .:_+-]", value, &port, rest))>=2) {
strcpy(options.hostname[i], value);
options.port[i] = port;
options.usedhosts++;
@@ -194,6 +209,8 @@
int i;
if (sscanf(buf, "BASE %128s", value)==1)
strcpy(options.searchbase, value);
+ if (sscanf(buf, "URI %512[A-Za-z0-9 .:/_+-]", value)==1)
+ parse_hosts(value);
if (sscanf(buf, "HOST %512[A-Za-z0-9 .:_+-]", value)==1)
parse_hosts(value);
if (sscanf(buf, "PORT %d", &len)==1)
@@ -239,7 +256,7 @@
options.ldifname[0] = '\0';
strcpy(options.password, "");
strcpy(options.exec_command, "");
- while ( (len = getopt(main_argc, main_argv, "b:D:e:h:o:p:u:V:v::w:L::"))>0 ) {
+ while ( (len = getopt(main_argc, main_argv, "b:D:e:h:H:o:p:u:V:v::w:L::"))>0 ) {
if (optarg && strlen(optarg)>127) {
fprintf(stderr, "argument %s too long\n", optarg);
continue;
@@ -260,6 +277,10 @@
strcpy(options.hostname[0], optarg);
options.usedhosts = 1;
break;
+ case 'H':
+ strcpy(options.urildap[0], optarg);
+ options.usedhosts = 1;
+ break;
case 'L':
if (optarg==NULL)
strcpy(options.ldifname, "-");
@@ -796,12 +817,37 @@
static int connect()
{
- int i;
+ int i, rc, version;
for (i = 0; i<options.usedhosts; i++) {
+ if ( strlen(options.urildap[i]) > 0) {
+ rc = ldap_initialize(&ldap_con, options.urildap[i]);
+ if (options.verbose&1 && rc == LDAP_SUCCESS) {
+ printf("ldap_initialization successful (%s)\n", options.urildap[i]);
+ } else if ( rc != LDAP_SUCCESS ) {
+ printf("ldap_initialization to %s failed %d\n", options.urildap[i], ldap_err2string(rc));
+ ldap_con = NULL;
+ return 0;
+ }
+ version = LDAP_VERSION3;
+ if ( (rc=ldap_set_option(ldap_con, LDAP_OPT_PROTOCOL_VERSION, &version)) != LDAP_SUCCESS ) {
+ printf("ldap_set_option to %s failed with err %s!\n", options.urildap[i], ldap_err2string(rc));
+ ldap_con = NULL;
+ return 0;
+ }
+ if ( options.use_tls[i] && (rc=ldap_start_tls_s( ldap_con, NULL, NULL )) != LDAP_SUCCESS ) {
+ printf("ldap_start_tls_s to %s failed with err %s!\n", options.urildap[i], ldap_err2string(rc));
+ ldap_con = NULL;
+ return 0;
+ }
+ } else {
ldap_con = ldap_init(options.hostname[i], options.port[i]);
+ }
if (ldap_simple_bind_s(ldap_con, options.binddn, options.password)==LDAP_SUCCESS) {
- if (options.verbose&1)
+ if (options.verbose&1 && strlen(options.urildap[i]) > 0) {
+ printf("Connected to %s as \"%s\"\n", options.urildap[i], options.binddn);
+ } else if (options.verbose&1) {
printf("Connected to %s:%d as \"%s\"\n", options.hostname[i], options.port[i], options.binddn);
+ }
return 1;
}
}

299
ldap2dns-loccode.patch Normal file
View File

@@ -0,0 +1,299 @@
diff -bu ldap2dns-0.3.1-p1/dns.schema ldap2dns-0.3.1/dns.schema
--- ldap2dns-0.3.1-p1/dns.schema 2002-08-13 14:23:53.000000000 +0200
+++ ldap2dns-0.3.1/dns.schema 2002-09-02 10:10:32.000000000 +0200
@@ -99,12 +99,18 @@
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{16} )
+attributetype ( 1.3.6.1.4.1.7222.1.4.23
+ NAME 'dnslocation'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{2}
+ SINGLE-VALUE )
+
objectclass ( 1.3.6.1.4.1.7222.1.4.19
NAME 'dnszone'
MUST ( objectclass $ cn )
MAY ( dnszonename $ dnsserial $ dnsrefresh $ dnsretry $ dnsexpire
$ dnsminimum $ dnsadminmailbox $ dnszonemaster $ dnstype $ dnsclass
- $ dnsttl $ dnstimestamp $ owner $ NIChandle $ TIShandle ) )
+ $ dnsttl $ dnstimestamp $ owner $ NIChandle $ TIShandle $ dnslocation ) )
objectclass ( 1.3.6.1.4.1.7222.1.4.20
NAME 'dnsrrset'
@@ -113,3 +119,7 @@
MAY ( dnsdomainname $ dnsrr $ dnsclass $ dnstype $ dnsipaddr $ dnscipaddr
$ dnscname $ dnspreference $ dnsttl $ dnstimestamp $ owner ) )
+objectclass ( 1.3.6.1.4.1.7222.1.4.24
+ NAME 'dnsloccodes'
+ MUST ( objectclass $ dnslocation )
+ MAY ( dnsipaddr $ uid $ description ) )
diff -bu ldap2dns-0.3.1-p1/ldap2dns.c ldap2dns-0.3.1/ldap2dns.c
--- ldap2dns-0.3.1-p1/ldap2dns.c 2002-09-02 10:45:43.000000000 +0200
+++ ldap2dns-0.3.1/ldap2dns.c 2002-09-02 10:04:50.000000000 +0200
@@ -58,8 +58,15 @@
char minimum[12];
char ttl[12];
char timestamp[20];
+ char location[2];
} zone;
+static struct
+{
+ char locname[3];
+ char member[256][16];
+} loc_rec;
+
struct resourcerecord
{
char cn[64];
@@ -72,6 +79,7 @@
char ttl[12];
char timestamp[20];
char preference[12];
+ char location[2];
#if defined DRAFT_RFC
char rr[1024];
char aliasedobjectname[256];
@@ -360,19 +368,19 @@
if (tinyfile) {
if (znix==0) {
if (ipdx<=0 && rr->cipaddr[0]) {
- fprintf(tinyfile, "&%s::%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "&%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
if (rr->cname[0])
- fprintf(tinyfile, "=%s:%s:%s:%s\n", rr->cname, rr->cipaddr, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "=%s:%s:%s:%s:%s\n", rr->cname, rr->cipaddr, rr->ttl, rr->timestamp, rr->location);
if (ipdx==0)
- fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->cname, rr->ipaddr[0], rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->cname, rr->ipaddr[0], rr->ttl, rr->timestamp, rr->location);
} else if (ipdx<0)
- fprintf(tinyfile, "&%s::%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "&%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
else if (ipdx==0)
- fprintf(tinyfile, "&%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[0], rr->cname, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "&%s:%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[0], rr->cname, rr->ttl, rr->timestamp, rr->location);
else if (ipdx>0 && rr->cname[0])
- fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->cname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->cname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp, rr->location);
} else if (ipdx<=0) {
- fprintf(tinyfile, "&%s::%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "&%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
}
}
if (namedzone) {
@@ -384,19 +392,19 @@
if (tinyfile) {
if (znix==0) {
if (ipdx<=0 && rr->cipaddr[0]) {
- fprintf(tinyfile, "@%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "@%s::%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp, rr->location);
if (rr->cname[0])
- fprintf(tinyfile, "=%s:%s:%s:%s\n", rr->cname, rr->cipaddr, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "=%s:%s:%s:%s:%s\n", rr->cname, rr->cipaddr, rr->ttl, rr->timestamp, rr->location);
if (ipdx==0)
- fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->cname, rr->ipaddr[0], rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->cname, rr->ipaddr[0], rr->ttl, rr->timestamp, rr->location);
} else if (ipdx<0)
- fprintf(tinyfile, "@%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "@%s::%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp, rr->location);
else if (ipdx==0)
- fprintf(tinyfile, "@%s:%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[0], rr->cname, rr->preference, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "@%s:%s:%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[0], rr->cname, rr->preference, rr->ttl, rr->timestamp, rr->location);
else if (ipdx>0 && rr->cname[0])
- fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->cname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->cname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp, rr->location);
} else if (ipdx<=0) {
- fprintf(tinyfile, "@%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "@%s::%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp, rr->location);
}
}
if (namedzone) {
@@ -407,9 +415,9 @@
} else if ( strcasecmp(rr->type, "A")==0) {
if (tinyfile) {
if (ipdx<=0 && rr->cipaddr[0])
- fprintf(tinyfile, "%s%s:%s:%s:%s\n", (znix==0 ? "=" : "+"), rr->dnsdomainname, rr->cipaddr, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "%s%s:%s:%s:%s:%s\n", (znix==0 ? "=" : "+"), rr->dnsdomainname, rr->cipaddr, rr->ttl, rr->timestamp, rr->location);
if (ipdx>=0)
- fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp, rr->location);
}
if (namedzone) {
if (ipdx<=0 && rr->cipaddr[0])
@@ -431,17 +439,17 @@
strcpy(buf, rr->dnsdomainname);
}
if (tinyfile)
- fprintf(tinyfile, "^%s:%s:%s:%s\n", buf, rr->cname, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "^%s:%s:%s:%s:%s\n", buf, rr->cname, rr->ttl, rr->timestamp, rr->location);
if (namedzone)
fprintf(namedzone, "%s.\tIN PTR\t%s.\n", buf, rr->cname);
} else if (strcasecmp(rr->type, "CNAME")==0) {
if (tinyfile)
- fprintf(tinyfile, "C%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "C%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
if (namedzone)
fprintf(namedzone, "%s.\tIN CNAME\t%s.\n", rr->dnsdomainname, rr->cname);
} else if (strcasecmp(rr->type, "TXT")==0) {
if (tinyfile)
- fprintf(tinyfile, "'%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
+ fprintf(tinyfile, "'%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
if (namedzone)
fprintf(namedzone, "%s.\tIN TXT\t%s.\n", rr->dnsdomainname, rr->cname);
}
@@ -515,6 +523,7 @@
rr.ttl[0] = '\0';
rr.timestamp[0] = '\0';
rr.preference[0] = '\0';
+ rr.location[0] = '\0';
#if defined DRAFT_RFC
rr.aliasedobjectname[0] = '\0';
rr.rr[0] = '\0';
@@ -585,6 +594,11 @@
rr.preference[0] = '\0';
else if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
+ } else if (strcasecmp(attr, "DNSlocation")==0) {
+ if (sscanf(bvals[0]->bv_val, "%s", rr.location)!=1)
+ rr.location[0] = '\0';
+ else if (options.ldifname[0])
+ fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
}
#if defined DRAFT_RFC
else if (strcasecmp(attr, "DNSrr")==0) {
@@ -632,10 +646,10 @@
char soa[20];
if (tinyfile) {
- fprintf(tinyfile, "Z%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
+ fprintf(tinyfile, "Z%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
zone.domainname, zone.zonemaster, zone.adminmailbox,
zone.serial, zone.refresh, zone.retry, zone.expire,
- zone.minimum, zone.ttl, zone.timestamp);
+ zone.minimum, zone.ttl, zone.timestamp, zone.location);
}
if (namedmaster) {
fprintf(namedmaster, "zone \"%s\" %s {\n\ttype master;\n\tfile \"%s.db\";\n};\n",
@@ -717,6 +731,7 @@
zone.minimum[0] = '\0';
zone.ttl[0] = '\0';
zone.timestamp[0] = '\0';
+ zone.location[0] = '\0';
dn = ldap_get_dn(ldap_con, m);
if (options.ldifname[0])
fprintf(ldifout, "dn: %s\n", dn);
@@ -782,6 +797,11 @@
zone.timestamp[0] = '\0';
else if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, zone.timestamp);
+ } else if (strcasecmp(attr, "DNSlocation")==0) {
+ if (sscanf(bvals[0]->bv_val, "%2s", zone.location)!=1)
+ zone.location[0] = '\0';
+ else if (options.ldifname[0])
+ fprintf(ldifout, "%s: %s\n", attr, zone.location);
}
}
ldap_value_free_len(bvals);
@@ -815,6 +835,91 @@
ldap_msgfree(res);
}
+static void write_loccode(int lidx)
+{
+ if (tinyfile) {
+ fprintf(tinyfile, "%%%s:%s\n", loc_rec.locname, loc_rec.member[lidx]);
+ }
+ if (options.ldifname[0])
+ fprintf(ldifout, "\n");
+}
+
+
+static void read_loccodes(void)
+{
+ LDAPMessage* res = NULL;
+ LDAPMessage* m;
+ int ldaperr;
+
+ if (tinyfile)
+ fprintf(tinyfile, "# Location Codes (if any) - generated by ldap2dns - DO NOT EDIT!\n");
+
+ if ( (ldaperr = ldap_search_s(ldap_con, options.searchbase[0] ? options.searchbase : NULL,
+ LDAP_SCOPE_SUBTREE,
+ "objectclass=DNSloccodes",
+ NULL,
+ 0,
+ &res)
+ )!=LDAP_SUCCESS )
+ die_ldap(ldaperr);
+ for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
+ BerElement* ber = NULL;
+ char* attr;
+ char* dn = ldap_get_dn(ldap_con, m);
+ int i, locmembers = 0;
+ char l_members[256][15];
+ //char loc[256][64];
+ char loc[2];
+ char ldif0;
+
+ loc_rec.locname[0] = '\0';
+ if (options.ldifname[0])
+ fprintf(ldifout, "dn: %s\n", dn);
+ for (attr = ldap_first_attribute(ldap_con, m, &ber); attr; attr = ldap_next_attribute(ldap_con, m, ber)) {
+ struct berval** bvals = ldap_get_values_len(ldap_con, m, attr);
+ if (bvals!=NULL) {
+ if (bvals[0] && bvals[0]->bv_len>0) {
+ if (strcasecmp(attr, "objectclass")==0
+ || strcasecmp(attr, "cn")==0) {
+ if (options.ldifname[0])
+ fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
+ } else if (strcasecmp(attr, "DNSlocation")==0) {
+ if (sscanf(bvals[0]->bv_val, "%2s", loc_rec.locname)!=1)
+ loc_rec.locname[0] = '\0';
+ else if (options.ldifname[0])
+ fprintf(ldifout, "%s: %s\n", attr, loc_rec.locname);
+ } else if (strcasecmp(attr, "DNSipaddr")==0) {
+ for (locmembers = 0; bvals[locmembers] && locmembers<256; locmembers++) {
+ if (sscanf(bvals[locmembers]->bv_val, "%15s", loc_rec.member[locmembers])!=1)
+ loc_rec.member[locmembers][0] = '\0';
+ else if (options.ldifname[0])
+ fprintf(ldifout, "%s: %s\n", attr, loc_rec.member[locmembers]);
+ }
+ } else {
+ if (options.ldifname[0])
+ fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
+ }
+ }
+ ldap_value_free_len(bvals);
+ }
+ }
+ ldif0 = options.ldifname[0];
+ if (options.verbose&1)
+ printf("locationcodename: %s (%d members)\n", loc_rec.locname, locmembers);
+ for (i = 0; i<locmembers; i++) {
+ if (i>0)
+ options.ldifname[0] = '\0';
+ write_loccode(i);
+ if (options.ldifname[0])
+ fprintf(ldifout, "\n");
+ }
+ options.ldifname[0] = ldif0;
+ free(dn);
+ }
+ ldap_msgfree(res);
+}
+
+
static int connect()
{
int i, rc, version;
@@ -906,6 +1011,7 @@
die_exit("Unable to open file 'data.temp' for writing");
if ( options.output&OUTPUT_DB && !(namedmaster = fopen("named.zones", "w")) )
die_exit("Unable to open file 'named.zones' for writing");
+ read_loccodes();
read_dnszones();
if (namedmaster)
fclose(namedmaster);
Gemeinsame Unterverzeichnisse: ldap2dns-0.3.1-p1/webadmin und ldap2dns-0.3.1/webadmin.

View File

@@ -1,6 +1,6 @@
/*
* Create data from an LDAP directory service to be used for tinydns
* $Id: ldap2dns.c,v 1.30 2001/08/09 10:35:49 jrief Exp $
* $Id: ldap2dns.c,v 1.33 2003/01/20 14:33:25 jrief Exp $
* Copyright 2000 by Jacob Rief <jacob.rief@tiscover.com>
* License: GPL version 2 or later. See http://www.fsf.org for details
*/
@@ -14,7 +14,7 @@
#include <unistd.h>
#define UPDATE_INTERVALL 59
#define LDAP_CONF "/etc/ldap.conf"
#define LDAP_CONF "/etc/ldap/ldap.conf"
#define OUTPUT_DATA 1
#define OUTPUT_DB 2
#define MAXHOSTS 10
@@ -58,8 +58,15 @@ static struct
char minimum[12];
char ttl[12];
char timestamp[20];
char location[2];
} zone;
static struct
{
char locname[3];
char member[256][16];
} loc_rec;
struct resourcerecord
{
char cn[64];
@@ -72,6 +79,7 @@ struct resourcerecord
char ttl[12];
char timestamp[20];
char preference[12];
char location[2];
#if defined DRAFT_RFC
char rr[1024];
char aliasedobjectname[256];
@@ -85,6 +93,7 @@ static struct
char searchbase[128];
char binddn[128];
char hostname[MAXHOSTS][128];
char urildap[MAXHOSTS][128];
int port[MAXHOSTS];
char password[128];
int usedhosts;
@@ -94,6 +103,7 @@ static struct
int verbose;
char ldifname[128];
char exec_command[128];
int use_tls[MAXHOSTS];
} options;
@@ -130,7 +140,8 @@ static void set_datadir(void)
static void print_usage(void)
{
print_version();
printf("usage: ldap2dns[d] [-D binddn] [-b searchbase] [-o data|db] [-h host] [-p port] [-w password] [-L[filename]] [-u numsecs] [-v[v]] [-V]\n\n");
printf("usage: ldap2dns[d] [-D binddn] [-b searchbase] [-o data|db] [-h host] [-p port] [-H hostURI] "
"[-w password] [-L[filename]] [-u numsecs] [-v[v]] [-V]\n\n");
printf("ldap2dns connects to an LDAP server reads the DNS information stored in objectclasses\n"
"\t\tDNSzone and DNSrrset and writes a file to be used by tinydns or named.\n"
"\t\tldap2dnsd starts as background-job and continouesly updates DNS information.\n");
@@ -143,6 +154,7 @@ static void print_usage(void)
printf(" -L[filename] Print output in LDIF format for reimport\n");
printf(" -h host\tHostname of LDAP server, defaults to localhost\n");
printf(" -p port\tPortnumber to connect to LDAP server, defaults to %d\n", LDAP_PORT);
printf(" -H hostURI\tURI (ldap://hostname or ldaps://hostname of LDAP server\n");
printf(" -u numsecs\tUpdate DNS data after numsecs. Defaults to %d if started as daemon.\n\t\t"
"Important notice: data.cdb is rewritten only after DNSserial in DNSzone is increased.\n",
UPDATE_INTERVALL);
@@ -159,7 +171,18 @@ static void parse_hosts(char* buf)
options.usedhosts = 0;
for (i = 0; i<MAXHOSTS; i++) {
if ((k = sscanf(buf, "%128s:%d %512[A-Za-z0-9 .:_+-]", value, &port, rest))>=2) {
if (!strncasecmp(buf, "ldaps://", 8) || !strncasecmp(buf, "ldap://", 7)) {
// LDAP-URI is given/found, at the moment only the standard-ports 389 and 636 are supported
if (!strncasecmp(buf, "ldap://", 7))
options.use_tls[i] = 1;
if ((k = sscanf(buf, "%128s %512[A-Za-z0-9 .:/_+-]", value, rest))>=1) {
strcpy(options.urildap[i], value);
options.usedhosts++;
if (k==1)
break;
buf = rest;
} else break;
} else if ((k = sscanf(buf, "%128s:%d %512[A-Za-z0-9 .:_+-]", value, &port, rest))>=2) {
strcpy(options.hostname[i], value);
options.port[i] = port;
options.usedhosts++;
@@ -194,6 +217,8 @@ static int parse_options()
int i;
if (sscanf(buf, "BASE %128s", value)==1)
strcpy(options.searchbase, value);
if (sscanf(buf, "URI %512[A-Za-z0-9 .:/_+-]", value)==1)
parse_hosts(value);
if (sscanf(buf, "HOST %512[A-Za-z0-9 .:_+-]", value)==1)
parse_hosts(value);
if (sscanf(buf, "PORT %d", &len)==1)
@@ -239,7 +264,7 @@ static int parse_options()
options.ldifname[0] = '\0';
strcpy(options.password, "");
strcpy(options.exec_command, "");
while ( (len = getopt(main_argc, main_argv, "b:D:e:h:o:p:u:V:v::w:L::"))>0 ) {
while ( (len = getopt(main_argc, main_argv, "b:D:e:h:H:o:p:u:V:v::w:L::"))>0 ) {
if (optarg && strlen(optarg)>127) {
fprintf(stderr, "argument %s too long\n", optarg);
continue;
@@ -260,6 +285,10 @@ static int parse_options()
strcpy(options.hostname[0], optarg);
options.usedhosts = 1;
break;
case 'H':
strcpy(options.urildap[0], optarg);
options.usedhosts = 1;
break;
case 'L':
if (optarg==NULL)
strcpy(options.ldifname, "-");
@@ -339,19 +368,19 @@ static void write_rr(struct resourcerecord* rr, int ipdx, int znix)
if (tinyfile) {
if (znix==0) {
if (ipdx<=0 && rr->cipaddr[0]) {
fprintf(tinyfile, "&%s::%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
fprintf(tinyfile, "&%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
if (rr->cname[0])
fprintf(tinyfile, "=%s:%s:%s:%s\n", rr->cname, rr->cipaddr, rr->ttl, rr->timestamp);
fprintf(tinyfile, "=%s:%s:%s:%s:%s\n", rr->cname, rr->cipaddr, rr->ttl, rr->timestamp, rr->location);
if (ipdx==0)
fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->cname, rr->ipaddr[0], rr->ttl, rr->timestamp);
fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->cname, rr->ipaddr[0], rr->ttl, rr->timestamp, rr->location);
} else if (ipdx<0)
fprintf(tinyfile, "&%s::%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
fprintf(tinyfile, "&%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
else if (ipdx==0)
fprintf(tinyfile, "&%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[0], rr->cname, rr->ttl, rr->timestamp);
fprintf(tinyfile, "&%s:%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[0], rr->cname, rr->ttl, rr->timestamp, rr->location);
else if (ipdx>0 && rr->cname[0])
fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->cname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp);
fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->cname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp, rr->location);
} else if (ipdx<=0) {
fprintf(tinyfile, "&%s::%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
fprintf(tinyfile, "&%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
}
}
if (namedzone) {
@@ -363,19 +392,19 @@ static void write_rr(struct resourcerecord* rr, int ipdx, int znix)
if (tinyfile) {
if (znix==0) {
if (ipdx<=0 && rr->cipaddr[0]) {
fprintf(tinyfile, "@%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp);
fprintf(tinyfile, "@%s::%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp, rr->location);
if (rr->cname[0])
fprintf(tinyfile, "=%s:%s:%s:%s\n", rr->cname, rr->cipaddr, rr->ttl, rr->timestamp);
fprintf(tinyfile, "=%s:%s:%s:%s:%s\n", rr->cname, rr->cipaddr, rr->ttl, rr->timestamp, rr->location);
if (ipdx==0)
fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->cname, rr->ipaddr[0], rr->ttl, rr->timestamp);
fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->cname, rr->ipaddr[0], rr->ttl, rr->timestamp, rr->location);
} else if (ipdx<0)
fprintf(tinyfile, "@%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp);
fprintf(tinyfile, "@%s::%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp, rr->location);
else if (ipdx==0)
fprintf(tinyfile, "@%s:%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[0], rr->cname, rr->preference, rr->ttl, rr->timestamp);
fprintf(tinyfile, "@%s:%s:%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[0], rr->cname, rr->preference, rr->ttl, rr->timestamp, rr->location);
else if (ipdx>0 && rr->cname[0])
fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->cname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp);
fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->cname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp, rr->location);
} else if (ipdx<=0) {
fprintf(tinyfile, "@%s::%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp);
fprintf(tinyfile, "@%s::%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->preference, rr->ttl, rr->timestamp, rr->location);
}
}
if (namedzone) {
@@ -386,9 +415,9 @@ static void write_rr(struct resourcerecord* rr, int ipdx, int znix)
} else if ( strcasecmp(rr->type, "A")==0) {
if (tinyfile) {
if (ipdx<=0 && rr->cipaddr[0])
fprintf(tinyfile, "%s%s:%s:%s:%s\n", (znix==0 ? "=" : "+"), rr->dnsdomainname, rr->cipaddr, rr->ttl, rr->timestamp);
fprintf(tinyfile, "%s%s:%s:%s:%s:%s\n", (znix==0 ? "=" : "+"), rr->dnsdomainname, rr->cipaddr, rr->ttl, rr->timestamp, rr->location);
if (ipdx>=0)
fprintf(tinyfile, "+%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp);
fprintf(tinyfile, "+%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->ipaddr[ipdx], rr->ttl, rr->timestamp, rr->location);
}
if (namedzone) {
if (ipdx<=0 && rr->cipaddr[0])
@@ -410,17 +439,17 @@ static void write_rr(struct resourcerecord* rr, int ipdx, int znix)
strcpy(buf, rr->dnsdomainname);
}
if (tinyfile)
fprintf(tinyfile, "^%s:%s:%s:%s\n", buf, rr->cname, rr->ttl, rr->timestamp);
fprintf(tinyfile, "^%s:%s:%s:%s:%s\n", buf, rr->cname, rr->ttl, rr->timestamp, rr->location);
if (namedzone)
fprintf(namedzone, "%s.\tIN PTR\t%s.\n", buf, rr->cname);
} else if (strcasecmp(rr->type, "CNAME")==0) {
if (tinyfile)
fprintf(tinyfile, "C%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
fprintf(tinyfile, "C%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
if (namedzone)
fprintf(namedzone, "%s.\tIN CNAME\t%s.\n", rr->dnsdomainname, rr->cname);
} else if (strcasecmp(rr->type, "TXT")==0) {
if (tinyfile)
fprintf(tinyfile, "'%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp);
fprintf(tinyfile, "'%s:%s:%s:%s:%s\n", rr->dnsdomainname, rr->cname, rr->ttl, rr->timestamp, rr->location);
if (namedzone)
fprintf(namedzone, "%s.\tIN TXT\t%s.\n", rr->dnsdomainname, rr->cname);
}
@@ -474,7 +503,7 @@ static void read_resourcerecords(char* dn, int znix)
LDAPMessage* m;
int ldaperr;
if ( (ldaperr = ldap_search_s(ldap_con, dn, LDAP_SCOPE_ONELEVEL, "objectclass=DNSrrset", NULL, 0, &res))!=LDAP_SUCCESS )
if ( (ldaperr = ldap_search_s(ldap_con, dn, LDAP_SCOPE_SUBTREE, "objectclass=DNSrrset", NULL, 0, &res))!=LDAP_SUCCESS )
die_ldap(ldaperr);
for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
BerElement* ber = NULL;
@@ -494,6 +523,7 @@ static void read_resourcerecords(char* dn, int znix)
rr.ttl[0] = '\0';
rr.timestamp[0] = '\0';
rr.preference[0] = '\0';
rr.location[0] = '\0';
#if defined DRAFT_RFC
rr.aliasedobjectname[0] = '\0';
rr.rr[0] = '\0';
@@ -564,6 +594,11 @@ static void read_resourcerecords(char* dn, int znix)
rr.preference[0] = '\0';
else if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
} else if (strcasecmp(attr, "DNSlocation")==0) {
if (sscanf(bvals[0]->bv_val, "%s", rr.location)!=1)
rr.location[0] = '\0';
else if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
}
#if defined DRAFT_RFC
else if (strcasecmp(attr, "DNSrr")==0) {
@@ -611,17 +646,17 @@ static void write_zone(void)
char soa[20];
if (tinyfile) {
fprintf(tinyfile, "Z%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
fprintf(tinyfile, "Z%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
zone.domainname, zone.zonemaster, zone.adminmailbox,
zone.serial, zone.refresh, zone.retry, zone.expire,
zone.minimum, zone.ttl, zone.timestamp);
zone.minimum, zone.ttl, zone.timestamp, zone.location);
}
if (namedmaster) {
fprintf(namedmaster, "zone \"%s\" %s {\n\ttype master;\n\tfile \"%s.db\";\n};\n",
zone.domainname, zone.class, zone.domainname);
}
if (namedzone) {
fprintf(namedzone, "# Automatically generated by ldap2dns - DO NOT EDIT!\n");
fprintf(namedzone, "; Automatically generated by ldap2dns - DO NOT EDIT!\n");
if (zone.ttl[0])
fprintf(namedzone, "$TTL %s\n", zone.ttl);
else
@@ -677,7 +712,7 @@ static void read_dnszones(void)
if (tinyfile)
fprintf(tinyfile, "# Automatically generated by ldap2dns - DO NOT EDIT!\n");
if (namedmaster)
fprintf(namedmaster, "# Automatically generated by ldap2dns - DO NOT EDIT!\n");
fprintf(namedmaster, "; Automatically generated by ldap2dns - DO NOT EDIT!\n");
if ( (ldaperr = ldap_search_s(ldap_con, options.searchbase[0] ? options.searchbase : NULL, LDAP_SCOPE_SUBTREE, "objectclass=DNSzone", NULL, 0, &res))!=LDAP_SUCCESS )
die_ldap(ldaperr);
for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
@@ -696,6 +731,7 @@ static void read_dnszones(void)
zone.minimum[0] = '\0';
zone.ttl[0] = '\0';
zone.timestamp[0] = '\0';
zone.location[0] = '\0';
dn = ldap_get_dn(ldap_con, m);
if (options.ldifname[0])
fprintf(ldifout, "dn: %s\n", dn);
@@ -761,6 +797,11 @@ static void read_dnszones(void)
zone.timestamp[0] = '\0';
else if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, zone.timestamp);
} else if (strcasecmp(attr, "DNSlocation")==0) {
if (sscanf(bvals[0]->bv_val, "%2s", zone.location)!=1)
zone.location[0] = '\0';
else if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, zone.location);
}
}
ldap_value_free_len(bvals);
@@ -794,14 +835,124 @@ static void read_dnszones(void)
ldap_msgfree(res);
}
static void write_loccode(int lidx)
{
if (tinyfile) {
fprintf(tinyfile, "%%%s:%s\n", loc_rec.locname, loc_rec.member[lidx]);
}
if (options.ldifname[0])
fprintf(ldifout, "\n");
}
static void read_loccodes(void)
{
LDAPMessage* res = NULL;
LDAPMessage* m;
int ldaperr;
if (tinyfile)
fprintf(tinyfile, "# Location Codes (if any) - generated by ldap2dns - DO NOT EDIT!\n");
if ( (ldaperr = ldap_search_s(ldap_con, options.searchbase[0] ? options.searchbase : NULL,
LDAP_SCOPE_SUBTREE,
"objectclass=DNSloccodes",
NULL,
0,
&res)
)!=LDAP_SUCCESS )
die_ldap(ldaperr);
for (m = ldap_first_entry(ldap_con, res); m; m = ldap_next_entry(ldap_con, m)) {
BerElement* ber = NULL;
char* attr;
char* dn = ldap_get_dn(ldap_con, m);
int i, locmembers = 0;
char l_members[256][15];
//char loc[256][64];
char loc[2];
char ldif0;
loc_rec.locname[0] = '\0';
if (options.ldifname[0])
fprintf(ldifout, "dn: %s\n", dn);
for (attr = ldap_first_attribute(ldap_con, m, &ber); attr; attr = ldap_next_attribute(ldap_con, m, ber)) {
struct berval** bvals = ldap_get_values_len(ldap_con, m, attr);
if (bvals!=NULL) {
if (bvals[0] && bvals[0]->bv_len>0) {
if (strcasecmp(attr, "objectclass")==0
|| strcasecmp(attr, "cn")==0) {
if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
} else if (strcasecmp(attr, "DNSlocation")==0) {
if (sscanf(bvals[0]->bv_val, "%2s", loc_rec.locname)!=1)
loc_rec.locname[0] = '\0';
else if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, loc_rec.locname);
} else if (strcasecmp(attr, "DNSipaddr")==0) {
for (locmembers = 0; bvals[locmembers] && locmembers<256; locmembers++) {
if (sscanf(bvals[locmembers]->bv_val, "%15s", loc_rec.member[locmembers])!=1)
loc_rec.member[locmembers][0] = '\0';
else if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, loc_rec.member[locmembers]);
}
} else {
if (options.ldifname[0])
fprintf(ldifout, "%s: %s\n", attr, bvals[0]->bv_val);
}
}
ldap_value_free_len(bvals);
}
}
ldif0 = options.ldifname[0];
if (options.verbose&1)
printf("locationcodename: %s (%d members)\n", loc_rec.locname, locmembers);
for (i = 0; i<locmembers; i++) {
if (i>0)
options.ldifname[0] = '\0';
write_loccode(i);
if (options.ldifname[0])
fprintf(ldifout, "\n");
}
options.ldifname[0] = ldif0;
free(dn);
}
ldap_msgfree(res);
}
static int connect()
{
int i;
int i, rc, version;
for (i = 0; i<options.usedhosts; i++) {
if ( strlen(options.urildap[i]) > 0) {
rc = ldap_initialize(&ldap_con, options.urildap[i]);
if (options.verbose&1 && rc == LDAP_SUCCESS) {
printf("ldap_initialization successful (%s)\n", options.urildap[i]);
} else if ( rc != LDAP_SUCCESS ) {
printf("ldap_initialization to %s failed %d\n", options.urildap[i], ldap_err2string(rc));
ldap_con = NULL;
return 0;
}
version = LDAP_VERSION3;
if ( (rc=ldap_set_option(ldap_con, LDAP_OPT_PROTOCOL_VERSION, &version)) != LDAP_SUCCESS ) {
printf("ldap_set_option to %s failed with err %s!\n", options.urildap[i], ldap_err2string(rc));
ldap_con = NULL;
return 0;
}
if ( options.use_tls[i] && (rc=ldap_start_tls_s( ldap_con, NULL, NULL )) != LDAP_SUCCESS ) {
printf("ldap_start_tls_s to %s failed with err %s!\n", options.urildap[i], ldap_err2string(rc));
ldap_con = NULL;
return 0;
}
} else {
ldap_con = ldap_init(options.hostname[i], options.port[i]);
}
if (ldap_simple_bind_s(ldap_con, options.binddn, options.password)==LDAP_SUCCESS) {
if (options.verbose&1)
if (options.verbose&1 && strlen(options.urildap[i]) > 0) {
printf("Connected to %s as \"%s\"\n", options.urildap[i], options.binddn);
} else if (options.verbose&1) {
printf("Connected to %s:%d as \"%s\"\n", options.hostname[i], options.port[i], options.binddn);
}
return 1;
}
}
@@ -860,6 +1011,7 @@ int main(int argc, char** argv)
die_exit("Unable to open file 'data.temp' for writing");
if ( options.output&OUTPUT_DB && !(namedmaster = fopen("named.zones", "w")) )
die_exit("Unable to open file 'named.zones' for writing");
read_loccodes();
read_dnszones();
if (namedmaster)
fclose(namedmaster);

2
webadmin/.htaccess Normal file
View File

@@ -0,0 +1,2 @@
AddType application/x-httpd-php .php
DirectoryIndex index.php

81
webadmin/common.inc Normal file
View File

@@ -0,0 +1,81 @@
<?
// $Id: common.inc,v 1.5 2002/08/13 12:20:21 tis Exp $
// common functions used by dns and portal-admin
function connect_ldap()
{
global $ldap, $binddn, $LDAPHOST, $BINDBASE, $BINDUID, $PHP_AUTH_USER, $PHP_AUTH_PW;
$binddn = "$BINDUID=$PHP_AUTH_USER,$BINDBASE";
$ldap = ldap_connect($LDAPHOST);
if ($ldap) {
if (!$PHP_AUTH_PW || !@ldap_bind($ldap, $binddn, $PHP_AUTH_PW)) {
header("WWW-Authenticate: Basic realm=\"Bind to 1 ldap://$LDAPHOST/$binddn\"");
header("HTTP/1.0 401 Unauthorized");
exit;
}
} else {
die("Unable to connect to LDAP host: $LDAPHOST");
}
}
function error_confirm($errmsg)
{
print "<CENTER><BR><h2><FONT color='red'>$errmsg</FONT></h2><BR>\n";
log_action("error: ".$errmsg);
}
function log_action($errmsg)
{
global $LOGFILE, $REMOTE_ADDR, $PHP_AUTH_USER;
$fd = fopen("$LOGFILE", "a");
fwrite($fd, "[".date("H:i:s d/M/Y")."] $PHP_AUTH_USER@$REMOTE_ADDR $errmsg\n");
fclose($fd);
}
# Use this function to determine contraints on objects and returns a set
# of characters with the following meaning:
# o: binddn owns the object
# a: binddn is administrator
# m: binddn is member
function check_constraint($dn = "")
{
global $ldap, $binddn, $BASEDN;
$result = "";
$num_owners = 0;
if (strlen($dn)>0) {
// get owners for this object
$query = ldap_read($ldap, $dn, "(objectclass=*)", array("owner"));
$entries = ldap_get_entries($ldap, $query);
ldap_free_result($query);
$num_owners = $entries[0][owner][count];
for ($i = 0; $i<$num_owners; $i++) {
if ($entries[0][owner][$i]==$binddn) {
$result .= "o";
$num_owners = 0;
}
}
}
// get administrators for BASEDN
$query = ldap_read($ldap, $BASEDN, "(objectclass=*)", array("administrator", "member"));
$entries = ldap_get_entries($ldap, $query);
ldap_free_result($query);
for ($i = 0; $i<$entries[0][administrator][count]; $i++) {
if ($entries[0][administrator][$i]==$binddn) {
$result .= "a";
break;
}
}
if ($num_owners==0) {
// only objects owned by nobody except binddn are granted to members
for ($i = 0; $i<$entries[0][member][count]; $i++) {
if ($entries[0][member][$i]==$binddn) {
$result .= "m";
break;
}
}
}
print "<!-- dn: $dn constraint: $result -->";
return $result;
}
?>

44
webadmin/config.inc Normal file
View File

@@ -0,0 +1,44 @@
<?
#################### basic configuration ####################
$LDAPHOST = "ldap.company.com";
$BASEDN = "ou=dns,o=company";
$BINDBASE = "ou=people,o=company";
$BINDUID = "uid";
$ANONBINDDN = "ou=dns,o=company";
$ZONEEDIT = "/dns/index.php";
$LOGFILE = "/var/log/zoneedit_log";
#################### default values ####################
$DEFAULT_TTL = "3600";
$DEFAULT_PREFERENCE = "10";
$DNSADMIN_MAILTO = "hostmaster\@company.com";
$NAMESERVERS = array("ns1.company.com", "ns2.company.com");
$ZONE_INFO = array("dnszonename", "dnsserial", "dnsclass", "dnstype", "dnsexpire", "dnsretry", "dnsminimum",
"dnszonemaster", "dnsrefresh", "dnsadminmailbox", "dnsttl" );
$ZONE_SOA = array(
"dnszonename" => "",
"dnsserial" => "",
"dnsclass" => "IN",
"dnstype" => "SOA",
"dnsexpire" => "604800",
"dnsretry" => "3600",
"dnsminimum" => "86400",
"dnsrefresh" => "10800",
"dnsttl" => "3600",
"dnszonemaster" => "ns1.company.com.",
"dnsadminmailbox" => "hostmaster.company.com.",
);
$ZONE_ENTRY = array(
array("cn"=>"NS1:", "objectclass"=>"dnsrrset", "dnstype"=>"NS", "dnsclass"=>"IN", "dnsttl"=>"3600", "dnscname"=>"ns1.company.com."),
array("cn"=>"NS2:", "objectclass"=>"dnsrrset", "dnstype"=>"NS", "dnsclass"=>"IN", "dnsttl"=>"3600", "dnscname"=>"ns2.company.com."),
);
#################### whois configuration ####################
$WHOISSERVERS = array( "at"=>"whois.nic.at", "de"=>"whois.denic.de", "ch"=>"whois.nic.ch",
"com"=>"whois.networksolutions.com", "net"=>"whois.networksolutions.com",
"org"=>"whois.networksolutions.com", "be"=>"whois.dns.be", "cz"=>"whois.nic.cz",
"fr"=>"whois.nic.fr", "hu"=>"whois.nic.hu", "it"=>"whois.nic.it", "dk"=>"whois.dk-hostmaster.dk",
"li"=>"whois.nic.li", "lu"=>"whois.dns.lu", "cc"=>"whois.nic.cc", "uk"=>"whois.nic.uk" );
?>

3
webadmin/footer.inc Normal file
View File

@@ -0,0 +1,3 @@
<BR>
</BODY>
</HTML>

8
webadmin/framesets.inc Normal file
View File

@@ -0,0 +1,8 @@
<TITLE>DNS Zone Admin</TITLE><BASE TARGET='_top' /></HEAD>
<FRAMESET COLS='250,*' BORDER='0' FRAMEBORDER='0' FRAMESPACING='0'>
<FRAME SRC='<? echo $ZONEEDIT ?>?call=dnslist&selet=f' NAME='menu' NORESIZE MARGINWIDTH='0' MARGINHEIGHT='0'>
<FRAME SRC='xearth.php' NAME='main' MARGINWIDTH='0' MARGINHEIGHT='0'>
</FRAMESET>
<BODY>You need a frame capable browser</BODY>
</HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 B

BIN
webadmin/icons/plus-end.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 972 B

BIN
webadmin/icons/zone_new.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

BIN
webadmin/icons/zone_val.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

725
webadmin/index.php Normal file
View File

@@ -0,0 +1,725 @@
<?
// $Id: index.php,v 1.11 2002/08/13 12:20:22 tis Exp $
include("config.inc");
include("common.inc");
error_reporting(E_ERROR|E_WARNING|E_PARSE);
if (isset($HTTP_GET_VARS[call])) {
main($HTTP_GET_VARS[call]);
} elseif (isset($HTTP_POST_VARS[call])) {
main($HTTP_POST_VARS[call]);
} else {
include("framesets.inc");
}
function main($call)
{
global $ZONEEDIT, $HTTP_GET_VARS, $HTTP_POST_VARS;
switch ($call) {
case "dnslist":
connect_ldap();
include("menuheader.inc");
if (ereg("[am]", check_constraint())) {
full_dns_list();
} else {
individual_dns_list();
}
include("footer.inc");
break;
case "search":
connect_ldap();
include("mainheader.inc");
if (isset($HTTP_GET_VARS[zonename])) {
$zonedn = search_zone($HTTP_GET_VARS[zonename]);
if (strlen($zonedn)>0) {
zone_edit_plus($zonedn);
} else {
new_zone($HTTP_GET_VARS[zonename]);
}
}
include("footer.inc");
break;
case "editzone":
connect_ldap();
include("mainheader.inc");
if (isset($HTTP_POST_VARS[modifysoa])) {
modify_zone_soa($HTTP_POST_VARS[zonedn]);
log_action("modify_zone_soa: $HTTP_POST_VARS[zonedn]");
} elseif (isset($HTTP_POST_VARS[addrrset])) {
add_rrset($HTTP_POST_VARS[zonedn]);
log_action("add_rrset: $HTTP_POST_VARS[zonedn]");
} elseif (isset($HTTP_POST_VARS[modifyrrset])) {
if (isset($HTTP_POST_VARS[deleterrset])) {
delete_rrset($HTTP_POST_VARS[zonedn], $HTTP_POST_VARS[setdn]);
log_action("delete_rrset: $HTTP_POST_VARS[setdn]");
} else {
modify_rrset($HTTP_POST_VARS[zonedn], $HTTP_POST_VARS[setdn]);
log_action("modify_rrset: ".$HTTP_POST_VARS[setdn]);
}
}
if (isset($HTTP_GET_VARS[zonedn]))
zone_edit_plus($HTTP_GET_VARS[zonedn]);
elseif (isset($HTTP_POST_VARS[zonedn]))
edit_zone_attrs($HTTP_POST_VARS[zonedn]);
include("footer.inc");
break;
case "newzone":
connect_ldap();
include("mainheader.inc");
new_zone();
include("footer.inc");
break;
case "addzone":
connect_ldap();
include("mainheader.inc");
zone_edit_plus(add_zone());
include("footer.inc");
break;
case "removezone":
connect_ldap();
if (isset($HTTP_GET_VARS[zonedn]) && remove_zone($HTTP_GET_VARS[zonedn])) {
include("xearthheader.inc");
include("footer.inc");
}
break;
}
}
function full_dns_list()
{
global $ldap, $BASEDN, $ZONEEDIT, $HTTP_GET_VARS;
$letters = array( "0-9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q-R","S","T","U","V","W","X-Z" );
if (isset($HTTP_GET_VARS[wait])) sleep($HTTP_GET_VARS[wait]);
if (isset($HTTP_GET_VARS[selet])) $selet = $HTTP_GET_VARS[selet];
?>
<form method="GET" action="<? echo $ZONEEDIT ?>" target="main" enctype="multipart/form-data">
<input type="hidden" name="call" value="search"><input type="hidden" name="selet" value="<? echo $selet ?>">
&nbsp;Find&nbsp;<input type="text" name="zonename" size="20" maxlength="64">
&nbsp;<input type="submit" name="Go" value="Go">
</form>
<a href="<? echo "$ZONEEDIT?call=newzone&selet=$selet" ?>" TARGET="main">
<img src="icons/zone_new.gif" width="16" height="16" align="texttop" border="0">&nbsp;&nbsp;Add new Zone</a><br>
<?
foreach ($letters as $let) {
$tree1 = ($let==$letters[count($letters)-1] ? "end" : "cont");
if (ereg("(.*)[$let]-[$let](.*)", $selet, $regs)
|| ereg("(.*)[$let](.*)", $selet, $regs)) {
$newselet = $regs[1].$regs[2];
ereg_replace("[$let]+", "", $newselet);
print "<a href='$ZONEEDIT?call=dnslist&selet=$newselet'>".
"<img src='icons/minus-$tree1.gif' width='19' height='16' align='texttop' border='0'>".
"<img src='icons/folder-open.gif' width='16' height='16' align='texttop' border='0'>...$let</a><br>\n";
} else {
$newselet = $selet.$let;
print "<a href='$ZONEEDIT?call=dnslist&selet=$newselet'>".
"<img src='icons/plus-$tree1.gif' width='19' height='16' align='texttop' border='0'>".
"<img src='icons/folder-closed.gif' width='16' height='16' align='texttop' border='0'>...$let</a><br>\n";
continue;
}
$filter = "(&(objectclass=dnszone)";
if (ereg("([0-9A-Z])-([0-9A-Z])", $let, $regs)) {
$filter .= "(|";
for ($i = ord($regs[1]); $i<=ord($regs[2]); $i++) {
$filter .= "(cn=".chr($i)."*)";
}
$filter .= "))";
} else {
$filter .= "(cn=$let*))";
}
$query = ldap_search($ldap, $BASEDN, $filter);
//ldap_sort($ldap, $query, "cn");
$entries = ldap_get_entries($ldap, $query);
ldap_free_result($query);
for ($i = 0; $i<$entries[count]; $i++) {
$zonedn = $entries[$i]["dn"];
$zonename = $entries[$i]["dnszonename"][0];
$tree2 = ($i==$entries[count]-1 ? "end" : "cont");
print "<a href='$ZONEEDIT?call=editzone&zonedn=$zonedn&selet=$selet' TARGET='main'>".
"<img src='".($tree1=="cont" ? "icons/img-vert-line.gif" : "icons/img-blank.gif" )."'".
" width='19' height='16' align='texttop' border='0'>".
"<img src='icons/branch-$tree2.gif' width='19' height='16' align='texttop' border='0'><img src='";
if (ereg("[d]", $selet)) {
$auth = authorized($zonename);
if ($auth==1) {
print "icons/zone_val.gif";
} elseif ($auth==-1) {
print "icons/zone_forb.gif";
} else {
print "icons/zone_unre.gif";
}
} else {
print "icons/zone_unkn.gif";
}
print "' width='16' height='16' align='texttop' border='0'>&nbsp;$zonename</a><br>\n";
}
print "\n";
}
#print "<tr align=center><th><a href='$ZONEEDIT?call=dnslist'";
if (ereg("[d]", $selet)) {
ereg_replace("[d]", "", $selet);
print "<a href='$ZONEEDIT?call=dnslist&selet=$selet' TARGET='menu'>Without DNS-lookup</a><br>\n";
} else {
print "<a href='$ZONEEDIT?call=dnslist&selet=$selet"."d' TARGET='menu'>With DNS-lookup</a><br>\n";
}
}
function individual_dns_list()
{
global $ldap, $binddn, $BASEDN, $ZONEEDIT, $HTTP_GET_VARS;
$query = ldap_search($ldap, $BASEDN, "(&(objectclass=DNSzone)(owner=$binddn))");
$entries = ldap_get_entries($ldap, $query);
for ($i = 0; $i<$entries[count]; $i++) {
$zonedn = $entries[$i][dn];
$zonename = $entries[$i][dnszonename][0];
$tree = ($i==$entries[count]-1 ? "end" : "cont");
print "<a href='$ZONEEDIT?call=editzone&zonedn=$zonedn' TARGET='main'>".
"<img src='icons/branch-$tree.gif' width='19' height='16' align='texttop' border='0'>".
"<img src='icons/zone_unkn.gif' width='16' height='16' align='texttop' border='0'>&nbsp;$zonename</a><br>\n";
}
}
function search_zone($zonename)
{
global $ldap, $BASEDN;
$filter = "(&(objectclass=dnszone)(dnszonename=$zonename))";
$query = ldap_search($ldap, $BASEDN, $filter);
$entries = ldap_get_entries($ldap, $query);
if ($entries[count]>1) {
$mesg = "Ambigous zonenames $zonename in<br>";
for ($i = 0; $i<$entries[count]; $i++) {
$mesg .= "dn: <a href='$ZONEEDIT?call=editzone&zonedn=".$entries[$i]["dn"]."' target='main'>".
$entries[$i]["dn"]."</a><br>";
}
print "<br><h3 align='center'><font color='orange'>Warning: $mesg</font></h3>";
exit;
}
if ($entries[count]==1) {
return $entries[0][dn];
} else switch (authorized($zonename)) {
case -2:
error_confirm("The zone does not belong to a valid top level domain");
exit;
case -1:
error_confirm("The zone is owned by someone else");
print_whois($zonename);
exit;
default:
return;
}
}
function print_zone_soa($zonedata, $constr)
{
print "<tr><td align='right'>Serial: </td>";
if (ereg("[amo]", $constr)) {
print "<td><input type='text' name='dnsserial' size='16' maxlength='24' value='$zonedata[dnsserial]'></td>";
} else {
print "<td><b> ".$zonedata["dnsserial"]." </b></td>";
}
print "<td align='right'>Refresh: </td><td>";
if (ereg("[amo]", $constr)) {
print "<input type='text' name='dnsrefresh' size='16' maxlength='24' value='$zonedata[dnsrefresh]'>";
} else {
print " <b> ".$zonedata["dnsrefresh"]." </b>";
}
print "</td></tr>\n<tr><td align='right'>Retry: </td><td>";
if (ereg("[amo]", $constr)) {
print "<input type='text' name='dnsretry' size='16' maxlength='24' value='$zonedata[dnsretry]'>";
} else {
print " <b> ".$zonedata["dnsretry"]." </b>";
}
print "</td>\n<td align='right'>Expire: </td><td>";
if (ereg("[amo]", $constr)) {
print "<input type='text' name='dnsexpire' size='16' maxlength='24' value='$zonedata[dnsexpire]'>";
} else {
print " <b> ".$zonedata["dnsexpire"]." </b>";
}
print "</td></tr>\n<tr><td align='right'>Minimum: </td><td>";
if (ereg("[amo]", $constr)) {
print "<input type='text' name='dnsminimum' size='16' maxlength='24' value='$zonedata[dnsminimum]'>";
} else {
print " <b> ".$zonedata["dnsminimum"]." </b>";
}
print "</td>\n<td align='right'>Adminmailbox: </td><td>";
if (ereg("[amo]", $constr)) {
print "<input type='text' name='dnsadminmailbox' size='16' maxlength='24' value='$zonedata[dnsadminmailbox]'>";
} else {
print " <b> ".$zonedata["dnsadminmailbox"]." </b>";
}
print "</td></tr>\n<tr><td align='right'>Zonemaster: </td><td>";
if (ereg("[amo]", $constr)) {
print "<input type='text' name='dnszonemaster' size='16' maxlength='24' value='$zonedata[dnszonemaster]'>";
} else {
print " <b> ".$zonedata["dnszonemaster"]." </b>";
}
print "</td>\n<td align='right'>Time to live: </td><td>";
if (ereg("[amo]", $constr)) {
print "<input type='text' name='dnsttl' size='16' maxlength='24' value='$zonedata[dnsttl]'>";
} else {
print " <b> ".$zonedata["dnsttl"]." </b>";
}
print "</td></tr>\n";
}
function get_zone_name($zonedn)
{
global $ldap;
$query = ldap_read($ldap, $zonedn, "(objectclass=dnszone)", array("dnszonename"));
$entries = ldap_get_entries($ldap, $query);
$zonename = $entries[0][dnszonename][0];
ldap_free_result($query);
return $zonename;
}
function modify_zone_soa($zonedn)
{
global $ldap, $ZONE_INFO, $HTTP_POST_VARS;
$zonename = get_zone_name($zonedn);
$entry = array();
foreach ($ZONE_INFO as $za) {
if (strlen($HTTP_POST_VARS["$za"])>0)
$entry["$za"] = $HTTP_POST_VARS["$za"];
}
if (ereg("[a]", check_constraint($zonedn))) {
$entry[dnszonename] = array("$zonename");
for ($i = 0; isset($HTTP_POST_VARS["dnszonename$i"]); $i++) {
if (strlen($HTTP_POST_VARS["dnszonename$i"])>3)
array_push($entry[dnszonename], $HTTP_POST_VARS["dnszonename$i"]);
}
}
ldap_modify($ldap, $zonedn, $entry) or die("ldap_modify failed to update SOA for $zonedn");
}
function authorized($zonename)
{
return 1;
}
function zone_edit_plus($zonedn)
{
$zonename = get_zone_name($zonedn);
$auth = authorized($zonename);
if ($auth==1) {
print "<center><br><h3><font color='green'>The nameserver is active and authorized to handle this zone</font></h3>\n";
edit_zone_attrs($zonedn);
print_whois($zonename);
} elseif ($auth==0) {
print "<center><br><h3><font color='orange'>The nameserver is not active for this zone</font></h3>\n";
edit_zone_attrs($zonedn);
print_whois($zonename);
} elseif ($auth==-1) {
print "<center><br><h3><font color='red'>The nameserver is not authorized to handle this zone</font></h3>\n";
edit_zone_attrs($zonedn);
print_whois($zonename);
} else {
print "<br><H2 align='center'><font color='red'>Zone <I>$zonename</I> does not not belong to a valid TLD</font></H2>\n";
delete_zone();
}
}
function edit_zone_attrs($zonedn)
{
global $ldap, $ZONE_INFO, $ZONEEDIT, $HTTP_GET_VARS, $HTTP_POST_VARS;
if (isset($HTTP_GET_VARS[selet])) $selet = $HTTP_GET_VARS[selet]; elseif (isset($HTTP_POST_VARS[selet])) $selet = $HTTP_POST_VARS[selet];
$query = ldap_read($ldap, $zonedn, "(objectclass=dnszone)");
$entries = ldap_get_entries($ldap, $query);
$zonename = $entries[0][dnszonename][0];
ldap_free_result($query);
$zonedn = $entries[0][dn];
$zonename0 = $entries[0][dnszonename][0];
$zonenames = array();
for ($i = 1; $i<$entries[0][dnszonename][count]; $i++) {
array_push($zonenames, $entries[0][dnszonename][$i]);
}
$zonedata = array();
foreach ($ZONE_INFO as $za) {
$zonedata[$za] = $entries[0][$za][0];
}
print "<center><h2>Edit DNS zone <I>$zonename0</I></h2>";
$zoneconstr = check_constraint($zonedn);
if (ereg("[a]", $zoneconstr)) {
# Print modifiable table for SOA
if (ereg("[f]", $selet)) {
print "<form method='POST' action='$ZONEEDIT' target='main' enctype='multipart/form-data'>".
"<input type='hidden' name='call' value='editzone'>".
"<input type='hidden' name='zonedn' value='$zonedn'>";
} else {
print "<form method='POST' action='$ZONEEDIT' enctype='multipart/form-data'>".
"<input type='hidden' name='call' value='editzone'>".
"<input type='hidden' name='zonedn' value='$zonedn'>".
"<input type='hidden' name='selet' value='$selet'>";
}
print "<table border='1' width='85%' COLS='4' CELLSPACING='1' CELLPADDING='0'>\n";
$zc = 0;
foreach ($zonenames as $zn) {
print "<tr><td align='right' colspan='2'> Aliasing Zonename: </td><td colspan='2'>";
if (ereg("[a]", $zoneconstr))
print "<input type='text' name='dnszonename$zc' value='$zn' size='40' maxlength='64'>";
else
print "<b>$zn</b>";
print "</td></tr>\n";
$zc++;
}
if (ereg("[a]", $zoneconstr)) {
print "<tr><td align='right' colspan='2'> Add aliasing Zonename: </td><td colspan='2'>".
"<input type='text' name='dnszonename$zc' size='40' maxlength='64'></td></tr>\n";
}
print_zone_soa($zonedata, $zoneconstr);
print "<tr><td colspan='4' align='center'><input type='submit' name='modifysoa' value=' Modify SOA for zone: \"$zonename0\" '>".
"</td></tr></table><P></form>";
} else {
# Print non-modifiable table for SOA
print "<table border='1' width='85%' COLS='4' CELLSPACING='1' CELLPADDING='0'>\n";
foreach ($zonenames as $zn) {
print "<tr><td align='right' colspan='2'> Aliasing Zonename: </td><td colspan='2'> <b>$zn</b></td></tr>\n";
}
print_zone_soa($zonedata, $zoneconstr);
print "</table><P>\n";
}
# Tables for RRsets
$query = ldap_list($ldap, $zonedn, "(objectclass=dnsrrset)");
$rrsets = ldap_get_entries($ldap, $query);
ldap_free_result($query);
print "<table border='1' width='98%' COLS='5' CELLSPACING='1' CELLPADDING='0'>\n".
"<tr><th width='1%'>DNS Name</th><th width='1%'>Type</th><th width='250'>Mapping</th>".
"<th width='1%'>TTL/Pref</th><th width='1%'>&nbsp;</th></tr>\n";
for ($i = 0; $i<$rrsets[count]; $i++) {
$setdn = $rrsets[$i][dn];
$setconstr = $zoneconstr.check_constraint($setdn);
$domainname = $rrsets[$i][dnsdomainname][0];
$ipaddr = $rrsets[$i][dnsipaddr];
$cipaddr = $rrsets[$i][dnscipaddr][0];
$cname = $rrsets[$i][dnscname][0];
$type = $rrsets[$i][dnstype][0];
$ttl = $rrsets[$i][dnsttl][0];
$preference = $rrsets[$i][dnspreference][0];
if (ereg("[amo]", $setconstr)) {
if (ereg("[f]", $selet)) {
print "<form method='POST' action='$ZONEEDIT' target='main' enctype='multipart/form-data'>".
"<input type='hidden' name='call' value='editzone'>".
"<input type='hidden' name='selet' value='$selet'>".
"<input type='hidden' name='zonedn' value='$zonedn'>".
"<input type='hidden' name='setdn' value='$setdn'>";
} else {
print "<form method='POST' action='$ZONEEDIT' enctype='multipart/form-data'>".
"<input type='hidden' name='call' value='editzone'>".
"<input type='hidden' name='zonedn' value='$zonedn'>".
"<input type='hidden' name='setdn' value='$setdn'>";
}
}
if (ereg("[amo]", $setconstr)) {
print "<br><input type='checkbox' name='deleterrset' value=' Delete '>Delete";
}
print "</td><td><b>$type</b></td><td><table border='0'>";
if ($type=="CNAME" || $type=="MX" || $type=="NS") {
print "<tr><td align='right'>CName:</td>";
if (ereg("[amo]", $setconstr))
print "<td><input type='text' name='dnscname' value='$cname' size='20' maxlength='64'></td></tr>\n";
else
print "<td><b>$cname</b></td></tr>\n";
}
if ($type=="A" || $type=="MX" || $type=="NS") {
if (ereg("[a]", $setconstr)) {
print "<tr><td align='right'>Canonical IP:</td>".
"<td><input type='text' name='dnscipaddr' value='$cipaddr' size='20' maxlength='15'></td></tr>\n";
} else if (isset($cipaddr)) {
print "<tr><td align='right'>Canonical IP:</td><td><b>$cipaddr</b></td></tr>\n";
}
for ($k = 0; $k<$rrsets[$i][dnsipaddr][count]; $k++) {
print "<tr><td align='right'>Modify IP:</td>";
$ipaddr = $rrsets[$i][dnsipaddr][$k];
if (ereg("[amo]", $setconstr))
print "<td><input type='text' name='dnsipaddr$k' value='$ipaddr' size='20' maxlength='15'></td></tr>\n";
else
print "<td><b>$ipaddr</b></td></tr>\n";
}
if (ereg("[amo]", $setconstr)) {
print "<tr><td align='right'>Add IP: </td><td><input type='text' name='dnsipaddr$k' value='' size='20' maxlength='15'></td></tr>\n";
}
}
print "</table></td>";
if (ereg("[amo]", $setconstr)) {
print "</td><td>TTL: <input type='text' name='dnsttl' value='$ttl' size='6' maxlength='6'>";
if ($type=="MX")
print "<br>Pref: <input type='text' name='dnspreference' value='$preference' size='6' maxlength='6'>";
print "</td><td><input type='submit' name='modifyrrset' value=' Modify '></td></tr></form>\n";
} else {
print "</td><td>TTL: <b>$ttl</b>";
if ($type=="MX")
print "<br>Pref: <b>$preference</b>";
print "</td></tr>\n";
}
}
if (ereg("[amo]", $setconstr)) {
if (ereg("[f]", $selet)) {
print "\n<form method='POST' action='$ZONEEDIT' target='main' enctype='multipart/form-data'>".
"<input type='hidden' name='call' value='editzone'>".
"<input type='hidden' name='selet' value='$selet'>".
"<input type='hidden' name='zonedn' value='$zonedn'";
} else {
print "\n<form method='POST' action='$ZONEEDIT' enctype='multipart/form-data'>".
"<input type='hidden' name='call' value='editzone'>".
"<input type='hidden' name='zonedn' value='$zonedn'";
}
print "<tr><td align='center'><input type='text' name='dnsdomainname' size='12' maxlength='32' override='1'></td>".
"<td align='center'><select name='dnstype'><option value='CNAME'>CNAME</option><option value='A'>A</option>".
"<option value='MX'>MX</option><option value='NS'>NS</option><option value='PTR'>PTR</option>".
"<option value='TXT'>TXT</option></select></td>".
"<td>&nbsp;</td><td colspan='2' align='center'><input type='submit' name='addrrset' value=' Add new record '></td></tr>".
"</form>";
}
print "</table><P>\n";
print "<table border='1' COLS='2' width='66%'><tr>";
// 'Delete' form
$onclick = "if(confirm('Do you really want to remove zone: $zonename0 and all its resource records?'))";
if (ereg("[f]", $selet)) {
$onclick .= "{ parent.frames.menu.location='$ZONEEDIT?call=dnslist&selet=$selet&wait=1';".
"parent.frames.main.location='$ZONEEDIT?call=removezone&zonedn=$zonedn&selet=$selet'; }";
} else {
$onclick .= "{ parent.window.location='$ZONEEDIT?call=removezone&zonedn=$zonedn'; }";
}
if (ereg("[am]", $setconstr)) {
print "<form><td align='center'><INPUT TYPE='BUTTON' VALUE=' Delete Zone \"$zonename0\" ' ONCLICK=\"$onclick\"></td></form>\n";
}
// form for reset/refresh button
if (ereg("[f]", $selet)) {
print "<form method='POST' action='$ZONEEDIT' target='main' enctype='multipart/form-data'>".
"<input type='hidden' name='call' value='editzone'>".
"<input type='hidden' name='zonedn' value='$zonedn'>".
"<input type='hidden' name='selet' value='$selet'>";
} else {
print "<form method='POST' action='$ZONEEDIT' enctype='multipart/form-data'>".
"<input type='hidden' name='call' value='editzone'>".
"<input type='hidden' name='zonedn' value='$zonedn'>";
}
print "<td align='center'><input type='submit' name='resetform' value=' Reset and Refresh '></td></form>".
"</tr></table>\n";
}
function new_zone($new_zonename = "")
{
global $HTTP_GET_VARS, $ZONE_SOA, $ZONEEDIT, $BASEDN;
if (isset($HTTP_GET_VARS[selet])) $selet = $HTTP_GET_VARS[selet];
$zonedata = $ZONE_SOA;
$zonedata[dnsserial] = new_serial();
$onsubmit = "{ parent.frames.menu.location='$ZONEEDIT?call=dnslist&selet=$selet&wait=1'; }";
print "<center><h2>Add new DNS zone</h2>";
print "<form action='$ZONEEDIT' method='POST' target='main' enctype='multipart/form-data' onsubmit=\"$onsubmit\">".
"<input type='hidden' name='call' value='addzone'>".
"<input type='hidden' name='selet value='$selet'>".
"<table border='1' width='85%' COLS='4'>\n".
"<tr><td align='right' colspan='2'> New Zonename: </td><td colspan='2'>".
"<input type='text' name='dnszonename' size='40' maxlength='64' value='".(strlen($new_zonename)>3 ? $new_zonename : "")."'>".
"</td></tr>\n";
print_zone_soa($zonedata, check_constraint());
print "</td></tr><tr><td colspan='2' align='center'>".
"<input type='submit'>".
"</td><td colspan='2' align='center'>".
"<input type='reset'>".
"</td></tr></table>\n".
"</form>";
}
function add_zone()
{
global $ldap, $HTTP_POST_VARS, $BASEDN, $ZONE_SOA, $ZONE_ENTRY, $ZONE_INFO;
$zonedata = array();
foreach ($ZONE_INFO as $za) {
if (strlen($HTTP_POST_VARS[$za])>0) {
$zonedata[$za] = $HTTP_POST_VARS[$za];
}
}
$zonedata["cn"] = $zonedata["dnszonename"];
$zonedata["objectclass"] = "dnszone";
$zonedn = "cn=$zonedata[cn],$BASEDN";
ldap_add($ldap, $zonedn, $zonedata) or die("Failed to add zonedn: $zonedn");
foreach ($ZONE_ENTRY as $ze) {
$dnch = "cn=$ze[cn],$zonedn";
ldap_add($ldap, $dnch, $ze) or die("Failed to add rrset dn: $dnch");
}
return $zonedn;
}
function remove_zone($zonedn)
{
global $ldap;
$query = ldap_list($ldap, $zonedn, "(objectclass=DNSrrset)");
$entries = ldap_get_entries($ldap, $query);
ldap_free_result($query);
for ($i = 0; $i<$entries[count]; $i++) {
ldap_delete($ldap, $entries[$i][dn]) or die("Failed to delete dn: $entries[$i][dn]");
}
ldap_delete($ldap, $zonedn) or die("Failed to delete dn: $zonedn");
return 1;
}
function new_serial($zonedn = 0)
{
global $ldap;
$newserial = date("Ymd")."00";
if ($zonedn) {
$query = ldap_read($ldap, $zonedn, "(objectclass=DNSzone)");
$entries = ldap_get_entries($ldap, $query);
$oldserial = $entries[0][dnsserial][0];
}
return ($newserial>$oldserial) ? $newserial : $oldserial+1;
}
function add_rrset($zonedn)
{
global $ldap, $binddn, $HTTP_POST_VARS, $DEFAULT_TTL, $DEFAULT_PREFERENCE;
if (!isset($HTTP_POST_VARS[dnsdomainname])) die("No domainname specified");
if (strlen($HTTP_POST_VARS[dnsdomainname])>0)
$entry[dnsdomainname] = $HTTP_POST_VARS[dnsdomainname];
if (!isset($HTTP_POST_VARS[dnstype])) die("No type specified");
$entry[dnstype] = $HTTP_POST_VARS[dnstype];
$entry[dnsclass] = "IN"; // INternet is hardcoded
$entry[dnsttl] = $DEFAULT_TTL;
// $entry[owner] = $binddn;
if ($entry[dnstype]=="MX" || $entry[dnstype]=="NS") {
for ($i = 1;; $i++) {
$setcn = "$entry[dnstype]$i:$entry[dnsdomainname]";
$query = ldap_list($ldap, $zonedn, "(&(objectclass=dnsrrset)(cn=$setcn))");
$rrset = ldap_get_entries($ldap, $query);
ldap_free_result($query);
if ($rrset[count]==0)
break;
}
if ($entry[dnstype]=="MX")
$entry[dnspreference] = $DEFAULT_PREFERENCE;
} else {
$setcn = "$entry[dnstype]:$entry[dnsdomainname]";
$query = ldap_list($ldap, $zonedn, "(&(objectclass=dnsrrset)(cn=$setcn))");
$rrset = ldap_get_entries($ldap, $query);
ldap_free_result($query);
if ($rrset[count]>0) {
error_confirm("$entry[dnsdomainname] has already been added to this zone");
return;
}
}
$entry[objectclass] = "dnsrrset";
$entry[cn] = $setcn;
$setdn = "cn=$setcn,$zonedn";
ldap_add($ldap, $setdn, $entry) or die("Faild to add DNSrrset $setdn to DNSzone $zonedn");
}
function modify_rrset($zonedn, $setdn)
{
global $ldap, $HTTP_POST_VARS;
$zonename = get_zone_name($zonedn);
$entry = array();
if (isset($HTTP_POST_VARS[dnscname])) {
if ($HTTP_POST_VARS[dnscname]=="") {
$entry[dnscname] = array();
} elseif (ereg("\.$", $HTTP_POST_VARS[dnscname])) {
if (checkdnsrr($HTTP_POST_VARS[dnscname], "A")) {
$entry[dnscname] = $HTTP_POST_VARS[dnscname];
} else {
error_confirm("Error: $HTTP_POST_VARS[dnscname] does not resolve to a valid IP-address");
return;
}
} elseif (isset($HTTP_POST_VARS[dnsipaddr0]) || isset($HTTP_POST_VARS[dnscipaddr])) {
// records with their own address settings are not checked against DNS
$entry[dnscname] = $HTTP_POST_VARS[dnscname];
} else {
if (!checkdnsrr("$HTTP_POST_VARS[dnscname].$zonename", "A")) {
print "<br><h2 align='center'><font color='orange'>Warning: $HTTP_POST_VARS[dnscname].$zonename".
" does not resolve to a valid IP-address</font></h2>\n";
}
$entry[dnscname] = $HTTP_POST_VARS[dnscname];
}
}
if (isset($HTTP_POST_VARS[dnscipaddr])) {
if (ereg("^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$", $HTTP_POST_VARS[dnscipaddr], $reg)) {
$regip = "$reg[1].$reg[2].$reg[3].$reg[4]";
if (check_unique_cipaddr($setdn, $regip))
$entry[dnscipaddr] = $regip;
else
return;
} elseif ($HTTP_POST_VARS[dnscipaddr]=="") {
$entry[dnscipaddr] = array();
} else {
error_confirm("$HTTP_POST_VARS[dnscipaddr] is not a valid IP-address");
return;
}
}
if (isset($HTTP_POST_VARS[dnsttl])) {
if (ereg("([0-9]+)", $HTTP_POST_VARS[dnsttl], $reg)) {
$entry[dnsttl] = $reg[1];
} else {
error_confirm("$HTTP_POST_VARS[dnsttl] is not a valid Time To Live");
return;
}
}
if (isset($HTTP_POST_VARS[dnspreference])) {
if (ereg("([0-9]+)", $HTTP_POST_VARS[dnspreference], $reg)) {
$entry[dnspreference] = $reg[1];
} else {
error_confirm("$HTTP_POST_VARS[dnspreference] is not a valid MX-prefrence");
return;
}
}
$entry[dnsipaddr] = array();
for ($i = 0; isset($HTTP_POST_VARS["dnsipaddr$i"]); $i++) {
$ipaddr = $HTTP_POST_VARS["dnsipaddr$i"];
if (ereg("^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$", $ipaddr, $reg)) {
array_push($entry[dnsipaddr], "$reg[1].$reg[2].$reg[3].$reg[4]");
} elseif ($ipaddr!="") {
error_confirm("$ipaddr is not a valid IP-address");
return;
}
}
ldap_modify($ldap, $setdn, $entry) or die("Faild to modify DNSrrest $setdn in DNSzone $zonedn");
ldap_mod_replace($ldap, $zonedn, array("dnsserial"=>new_serial($zonedn)));
}
function delete_rrset($zonedn, $setdn)
{
global $ldap;
ldap_delete($ldap, $setdn) or die("Failed to delete $setdn from LDAP");;
ldap_mod_replace($ldap, $zonedn, array("dnsserial"=>new_serial($zonedn)));
}
function check_unique_cipaddr($setdn, $cipaddr)
{
global $ldap, $BASEDN;
$query = ldap_search($ldap, $BASEDN, "(&(objectclass=dnsrrset)(dnscipaddr=$cipaddr))");
$entries = ldap_get_entries($ldap, $query);
ldap_free_result($query);
for ($i = 0; $i<$entries[count]; $i++) {
$dn = $entries[$i][dn];
if ($dn!=$setdn) {
error_confirm("Canonical IP-address $cipaddr is already used by $dn");
return 0;
}
}
return 1;
}
function print_whois($zonename)
{
global $WHOISSERVERS;
return; // weil unser FW-Gschaftler den Port 43 von innen nach aussen zugedreht hat
if (ereg("\.([a-zA-Z]+)$", $zonename, $regex)) {
$whoissrv = $WHOISSERVERS["$regex[1]"];
if (isset($whoissrv)) {
$whoisrecord = system("whois -h $whoissrv $zonename");
print "<h3 align='center'>Whois-record for zone <I>$zonename</I></h3><P>\n".
"as serverd by $whoissrv<br>\n".
"<table border='1' width='85%' CELLSPACING='1' CELLPADDING='0'><tr align='LEFT'>".
"<td><PRE>$whoisrecord</PRE></td></tr></table>\n";
} else {
print "<h3 align=center><font color=red>No WHOIS-Server found for \"$regex[1]\"</font></h3>\n";
}
}
}
?>

17
webadmin/main.css Normal file
View File

@@ -0,0 +1,17 @@
BODY, TD {
font-family: Verdana,Arial,Helvetica;
font-size: 11pt;
background-color: white;
color: black;
}
SMALL {
font-family: Verdana,Arial,Helvetica;
font-size: 8pt;
}
BIG {
font-family: Verdana,Arial,Helvetica;
font-size: 14pt;
}

8
webadmin/mainheader.inc Normal file
View File

@@ -0,0 +1,8 @@
<HTML>
<HEAD>
<TITLE>Zone-Editor</TITLE>
<BASE TARGET="main" />
<LINK REL="stylesheet" HREF="/dns/main.css" TYPE="text/css">
</HEAD>
<BODY>

37
webadmin/menu.css Normal file
View File

@@ -0,0 +1,37 @@
A {
text-decoration: none;
}
A:link {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
color: black;
}
A:visited {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
color: #222222;
}
A:hover {
text-decoration: underline;
}
BODY, TD {
font-family: Verdana,Arial,Helvetica;
font-size: 10pt;
background-color: lightgrey;
color: black;
}
SMALL {
font-family: Verdana,Arial,Helvetica;
font-size: 8pt;
}
BIG {
font-family: Verdana,Arial,Helvetica;
font-size: 14pt;
}

8
webadmin/menuheader.inc Normal file
View File

@@ -0,0 +1,8 @@
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Zone-Selector</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="/dns/menu.css" ?></LINK>
</HEAD>
<BODY>
<br>

21
webadmin/xearth.css Normal file
View File

@@ -0,0 +1,21 @@
A {
text-decoration: none;
}
BODY, TD {
font-family: Verdana,Arial,Helvetica;
font-size: 10pt;
background-color: black;
color: white;
}
SMALL {
font-family: Verdana,Arial,Helvetica;
font-size: 8pt;
}
BIG {
font-family: Verdana,Arial,Helvetica;
font-size: 12pt;
}

16
webadmin/xearth.php Normal file
View File

@@ -0,0 +1,16 @@
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>XEarth</TITLE>
<LINK REL="stylesheet" TYPE="text/css" HREF="xearth.css"></LINK>
</HEAD>
<BODY rightmargin="0" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" bgcolor="#ffffff">
<CENTER><BR><BR><BR>
<TABLE WIDTH="500" COLS="1" border="0">
<TR ALIGN="center"><TH><BIG><? echo date("H:i:s d/M/Y") ?></BIG></TH></TR>
<TR><TD><IMG SRC="xearthimage.php" width="500" height="500"></TD></TR>
</TABLE>
<BR>
</BODY>
</HTML>

4
webadmin/xearthimage.php Normal file
View File

@@ -0,0 +1,4 @@
<?
header("Content-Type: image/gif");
passthru("/usr/bin/X11/xearth -size 500,500 -nostars -gif");
?>