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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; k0 ? 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 + */ + +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] = '%';