diff --git a/.cvsignore b/.cvsignore index a9afba7..eccdd60 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,5 +1,5 @@ -bind-9.5.0a5.tar.gz +bind-9.5.0a6.tar.gz bind-chroot.tar.bz2 config.tar libbind-man.tar.gz -bind-9.5.0a5-autotools.tar.bz2 +bind-9.5.0a6-autotools.tar.bz2 diff --git a/bind-9.3.2b1-fix_sdb_ldap.patch b/bind-9.3.2b1-fix_sdb_ldap.patch index 6768b30..ff4a391 100644 --- a/bind-9.3.2b1-fix_sdb_ldap.patch +++ b/bind-9.3.2b1-fix_sdb_ldap.patch @@ -1,403 +1,3 @@ ---- /dev/null 2005-10-06 11:34:58.093275500 -0400 -+++ bind-9.3.2b1/bin/sdb_tools/ldap2zone.c 2005-10-06 18:57:32.000000000 -0400 -@@ -0,0 +1,397 @@ -+/* -+ * Copyright (C) 2004, 2005 Stig Venaas -+ * $Id: ldap2zone.c,v 0.1 2005/04/23 21:30:12 venaas Exp $ -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ */ -+ -+#include -+#include -+ -+#include -+ -+struct string { -+ void *data; -+ size_t len; -+}; -+ -+struct assstack_entry { -+ struct string key; -+ struct string val; -+ struct assstack_entry *next; -+}; -+ -+struct assstack_entry *assstack_find(struct assstack_entry *stack, struct string *key) { -+ for (; stack; stack = stack->next) -+ if (stack->key.len == key->len && !memcmp(stack->key.data, key->data, key->len)) -+ return stack; -+ return NULL; -+} -+ -+void assstack_push(struct assstack_entry **stack, struct assstack_entry *item) { -+ item->next = *stack; -+ *stack = item; -+} -+ -+void assstack_insertbottom(struct assstack_entry **stack, struct assstack_entry *item) { -+ struct assstack_entry *p; -+ -+ item->next = NULL; -+ if (!*stack) { -+ *stack = item; -+ return; -+ } -+ /* find end, should keep track of end somewhere */ -+ /* really a queue, not a stack */ -+ p = *stack; -+ while (p->next) -+ p = p->next; -+ p->next = item; -+} -+ -+void printsoa(struct string *soa) { -+ char *s; -+ int i; -+ -+ s = (char *)soa->data; -+ i = 0; -+ while (i < soa->len) { -+ putchar(s[i]); -+ if (s[i++] == ' ') -+ break; -+ } -+ while (i < soa->len) { -+ putchar(s[i]); -+ if (s[i++] == ' ') -+ break; -+ } -+ printf("(\n\t\t\t\t"); -+ while (i < soa->len) { -+ putchar(s[i]); -+ if (s[i++] == ' ') -+ break; -+ } -+ printf("; Serialnumber\n\t\t\t\t"); -+ while (i < soa->len) { -+ if (s[i] == ' ') -+ break; -+ putchar(s[i++]); -+ } -+ i++; -+ printf("\t; Refresh\n\t\t\t\t"); -+ while (i < soa->len) { -+ if (s[i] == ' ') -+ break; -+ putchar(s[i++]); -+ } -+ i++; -+ printf("\t; Retry\n\t\t\t\t"); -+ while (i < soa->len) { -+ if (s[i] == ' ') -+ break; -+ putchar(s[i++]); -+ } -+ i++; -+ printf("\t; Expire\n\t\t\t\t"); -+ while (i < soa->len) { -+ putchar(s[i++]); -+ } -+ printf(" )\t; Minimum TTL\n"); -+} -+ -+void printrrs(char *defaultttl, struct assstack_entry *item) { -+ struct assstack_entry *stack; -+ char *s; -+ int first; -+ int i; -+ char *ttl, *type; -+ int top; -+ -+ s = (char *)item->key.data; -+ -+ if (item->key.len == 1 && *s == '@') { -+ top = 1; -+ printf("@\t"); -+ } else { -+ top = 0; -+ for (i = 0; i < item->key.len; i++) -+ putchar(s[i]); -+ if (item->key.len < 8) -+ putchar('\t'); -+ putchar('\t'); -+ } -+ -+ first = 1; -+ for (stack = (struct assstack_entry *) item->val.data; stack; stack = stack->next) { -+ ttl = (char *)stack->key.data; -+ s = strchr(ttl, ' '); -+ *s++ = '\0'; -+ type = s; -+ -+ if (first) -+ first = 0; -+ else -+ printf("\t\t"); -+ -+ if (strcmp(defaultttl, ttl)) -+ printf("%s", ttl); -+ putchar('\t'); -+ -+ if (top) { -+ top = 0; -+ printf("IN\t%s\t", type); -+ /* Should always be SOA here */ -+ if (!strcmp(type, "SOA")) { -+ printsoa(&stack->val); -+ continue; -+ } -+ } else -+ printf("%s\t", type); -+ -+ s = (char *)stack->val.data; -+ for (i = 0; i < stack->val.len; i++) -+ putchar(s[i]); -+ putchar('\n'); -+ } -+} -+ -+void print_zone(char *defaultttl, struct assstack_entry *stack) { -+ printf("$TTL %s\n", defaultttl); -+ for (; stack; stack = stack->next) -+ printrrs(defaultttl, stack); -+}; -+ -+void usage(char *name) { -+ fprintf(stderr, "Usage:%s zone-name LDAP-URL default-ttl [serial]\n", name); -+ exit(1); -+}; -+ -+void err(char *name, char *msg) { -+ fprintf(stderr, "%s: %s\n", name, msg); -+ exit(1); -+}; -+ -+int putrr(struct assstack_entry **stack, struct berval *name, char *type, char *ttl, struct berval *val) { -+ struct string key; -+ struct assstack_entry *rr, *rrdata; -+ -+ /* Do nothing if name or value have 0 length */ -+ if (!name->bv_len || !val->bv_len) -+ return 0; -+ -+ /* see if already have an entry for this name */ -+ key.len = name->bv_len; -+ key.data = name->bv_val; -+ -+ rr = assstack_find(*stack, &key); -+ if (!rr) { -+ /* Not found, create and push new entry */ -+ rr = (struct assstack_entry *) malloc(sizeof(struct assstack_entry)); -+ if (!rr) -+ return -1; -+ rr->key.len = name->bv_len; -+ rr->key.data = (void *) malloc(rr->key.len); -+ if (!rr->key.data) { -+ free(rr); -+ return -1; -+ } -+ memcpy(rr->key.data, name->bv_val, name->bv_len); -+ rr->val.len = sizeof(void *); -+ rr->val.data = NULL; -+ if (name->bv_len == 1 && *(char *)name->bv_val == '@') -+ assstack_push(stack, rr); -+ else -+ assstack_insertbottom(stack, rr); -+ } -+ -+ rrdata = (struct assstack_entry *) malloc(sizeof(struct assstack_entry)); -+ if (!rrdata) { -+ free(rr->key.data); -+ free(rr); -+ return -1; -+ } -+ rrdata->key.len = strlen(type) + strlen(ttl) + 1; -+ rrdata->key.data = (void *) malloc(rrdata->key.len); -+ if (!rrdata->key.data) { -+ free(rrdata); -+ free(rr->key.data); -+ free(rr); -+ return -1; -+ } -+ sprintf((char *)rrdata->key.data, "%s %s", ttl, type); -+ -+ rrdata->val.len = val->bv_len; -+ rrdata->val.data = (void *) malloc(val->bv_len); -+ if (!rrdata->val.data) { -+ free(rrdata->key.data); -+ free(rrdata); -+ free(rr->key.data); -+ free(rr); -+ return -1; -+ } -+ memcpy(rrdata->val.data, val->bv_val, val->bv_len); -+ -+ if (!strcmp(type, "SOA")) -+ assstack_push((struct assstack_entry **) &(rr->val.data), rrdata); -+ else -+ assstack_insertbottom((struct assstack_entry **) &(rr->val.data), rrdata); -+ return 0; -+} -+ -+int main(int argc, char **argv) { -+ char *s, *hostporturl, *base = NULL; -+ char *ttl, *defaultttl; -+ LDAP *ld; -+ char *fltr = NULL; -+ LDAPMessage *res, *e; -+ char *a, **ttlvals, **soavals, *serial; -+ struct berval **vals, **names; -+ char type[64]; -+ BerElement *ptr; -+ int i, j, rc, msgid; -+ struct assstack_entry *zone = NULL; -+ -+ if (argc < 4 || argc > 5) -+ usage(argv[0]); -+ -+ hostporturl = argv[2]; -+ -+ if (hostporturl != strstr( hostporturl, "ldap")) -+ err(argv[0], "Not an LDAP URL"); -+ -+ s = strchr(hostporturl, ':'); -+ -+ if (!s || strlen(s) < 3 || s[1] != '/' || s[2] != '/') -+ err(argv[0], "Not an LDAP URL"); -+ -+ s = strchr(s+3, '/'); -+ if (s) { -+ *s++ = '\0'; -+ base = s; -+ s = strchr(base, '?'); -+ if (s) -+ err(argv[0], "LDAP URL can only contain host, port and base"); -+ } -+ -+ defaultttl = argv[3]; -+ -+ rc = ldap_initialize(&ld, hostporturl); -+ if (rc != LDAP_SUCCESS) -+ err(argv[0], "ldap_initialize() failed"); -+ -+ if (argc == 5) { -+ /* serial number specified, check if different from one in SOA */ -+ fltr = (char *)malloc(strlen(argv[1]) + strlen("(&(relativeDomainName=@)(zoneName=))") + 1); -+ sprintf(fltr, "(&(relativeDomainName=@)(zoneName=%s))", argv[1]); -+ msgid = ldap_search(ld, base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0); -+ if (msgid == -1) -+ err(argv[0], "ldap_search() failed"); -+ -+ while ((rc = ldap_result(ld, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) { -+ /* not supporting continuation references at present */ -+ if (rc != LDAP_RES_SEARCH_ENTRY) -+ err(argv[0], "ldap_result() returned cont.ref? Exiting"); -+ -+ /* only one entry per result message */ -+ e = ldap_first_entry(ld, res); -+ if (e == NULL) { -+ ldap_msgfree(res); -+ err(argv[0], "ldap_first_entry() failed"); -+ } -+ -+ soavals = ldap_get_values(ld, e, "SOARecord"); -+ if (soavals) -+ break; -+ } -+ -+ ldap_msgfree(res); -+ if (!soavals) { -+ err(argv[0], "No SOA Record found"); -+ } -+ -+ /* We have a SOA, compare serial numbers */ -+ /* Only checkinf first value, should be only one */ -+ s = strchr(soavals[0], ' '); -+ s++; -+ s = strchr(s, ' '); -+ s++; -+ serial = s; -+ s = strchr(s, ' '); -+ *s = '\0'; -+ if (!strcmp(serial, argv[4])) { -+ ldap_value_free(soavals); -+ err(argv[0], "serial numbers match"); -+ } -+ ldap_value_free(soavals); -+ } -+ -+ if (!fltr) -+ fltr = (char *)malloc(strlen(argv[1]) + strlen("(zoneName=)") + 1); -+ if (!fltr) -+ err(argv[0], "Malloc failed"); -+ sprintf(fltr, "(zoneName=%s)", argv[1]); -+ -+ msgid = ldap_search(ld, base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0); -+ if (msgid == -1) -+ err(argv[0], "ldap_search() failed"); -+ -+ while ((rc = ldap_result(ld, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) { -+ /* not supporting continuation references at present */ -+ if (rc != LDAP_RES_SEARCH_ENTRY) -+ err(argv[0], "ldap_result() returned cont.ref? Exiting"); -+ -+ /* only one entry per result message */ -+ e = ldap_first_entry(ld, res); -+ if (e == NULL) { -+ ldap_msgfree(res); -+ err(argv[0], "ldap_first_entry() failed"); -+ } -+ -+ names = ldap_get_values_len(ld, e, "relativeDomainName"); -+ if (!names) -+ continue; -+ -+ ttlvals = ldap_get_values(ld, e, "dNSTTL"); -+ ttl = ttlvals ? ttlvals[0] : defaultttl; -+ -+ for (a = ldap_first_attribute(ld, e, &ptr); a != NULL; a = ldap_next_attribute(ld, e, ptr)) { -+ char *s; -+ -+ for (s = a; *s; s++) -+ *s = toupper(*s); -+ s = strstr(a, "RECORD"); -+ if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) { -+ ldap_memfree(a); -+ continue; -+ } -+ -+ strncpy(type, a, s - a); -+ type[s - a] = '\0'; -+ vals = ldap_get_values_len(ld, e, a); -+ if (vals) { -+ for (i = 0; vals[i]; i++) -+ for (j = 0; names[j]; j++) -+ if (putrr(&zone, names[j], type, ttl, vals[i])) -+ err(argv[0], "malloc failed"); -+ ldap_value_free_len(vals); -+ } -+ ldap_memfree(a); -+ } -+ -+ if (ptr) -+ ber_free(ptr, 0); -+ if (ttlvals) -+ ldap_value_free(ttlvals); -+ ldap_value_free_len(names); -+ /* free this result */ -+ ldap_msgfree(res); -+ } -+ -+ /* free final result */ -+ ldap_msgfree(res); -+ -+ print_zone(defaultttl, zone); -+ return 0; -+} --- bind-9.3.2b1/bin/sdb_tools/Makefile.in.fix_sdb_ldap 2005-02-17 01:43:28.000000000 -0500 +++ bind-9.3.2b1/bin/sdb_tools/Makefile.in 2005-10-06 18:57:32.000000000 -0400 @@ -30,11 +30,11 @@ diff --git a/bind-9.5.0-errno-init.patch b/bind-9.5.0-errno-init.patch deleted file mode 100644 index 9c96ec0..0000000 --- a/bind-9.5.0-errno-init.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff -up bind-9.5.0a5/lib/bind/resolv/res_init.c.errno bind-9.5.0a5/lib/bind/resolv/res_init.c ---- bind-9.5.0a5/lib/bind/resolv/res_init.c.errno 2007-07-02 14:55:54.000000000 +0200 -+++ bind-9.5.0a5/lib/bind/resolv/res_init.c 2007-07-02 14:57:03.000000000 +0200 -@@ -168,7 +168,7 @@ __res_vinit(res_state statp, int preinit - union res_sockaddr_union u[2]; - int maxns = MAXNS; - -- h_errno = 0; -+ RES_SET_H_ERRNO(statp, 0); - if (statp->_u._ext.ext != NULL) - res_ndestroy(statp); - -@@ -231,7 +231,7 @@ __res_vinit(res_state statp, int preinit - * to check our return code wont be able to make - * queries anyhow. - */ -- h_errno = statp->res_h_errno = NETDB_INTERNAL; -+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL); - maxns = 0; - } - #ifdef RESOLVSORT -@@ -498,7 +498,7 @@ __res_vinit(res_state statp, int preinit - if ((cp = getenv("RES_OPTIONS")) != NULL) - res_setoptions(statp, cp, "env"); - statp->options |= RES_INIT; -- return (h_errno); -+ return (statp->res_h_errno); - } - - static void diff --git a/bind.spec b/bind.spec index 44c7c93..49905c4 100644 --- a/bind.spec +++ b/bind.spec @@ -1,6 +1,15 @@ # # Red Hat BIND package .spec file # + +# Release numbers + +%define BIND_MAJORVER 9 +%define BIND_MINORVER 5 +%define BIND_PATCHVER 0 +%define BIND_RELEASETYPE a +%define BIND_RELEASEVER 6 + %{?!SDB: %define SDB 1} %{?!LIBBIND: %define LIBBIND 1} %{?!efence: %define efence 0} @@ -17,14 +26,14 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) server. Name: bind License: BSD-like -Version: 9.5.0a5 -Release: 5%{?dist} -Epoch: 31 +Version: %{BIND_MAJORVER}.%{BIND_MINORVER}.%{BIND_PATCHVER} +Release: 6.%{BIND_RELEASETYPE}%{BIND_RELEASEVER}%{?dist} +Epoch: 32 Url: http://www.isc.org/products/BIND/ Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Group: System Environment/Daemons # -Source: ftp://ftp.isc.org/isc/bind9/%{version}/bind-%{version}.tar.gz +Source: ftp://ftp.isc.org/isc/bind9/%{version}/bind-%{version}%{BIND_RELEASETYPE}%{BIND_RELEASEVER}.tar.gz Source1: named.sysconfig Source2: named.init Source3: named.logrotate @@ -44,7 +53,8 @@ Source22: bind-chroot-admin.in Source24: libbind.pc Source25: named.conf.sample Source28: config.tar -Source29: bind-%{version}-autotools.tar.bz2 +Source29: bind-%{version}%{BIND_RELEASETYPE}%{BIND_RELEASEVER}-autotools.tar.bz2 +Source30: ldap2zone.c # Common patches Patch0: bind-9.2.0rc3-varrun.patch @@ -58,7 +68,6 @@ Patch32: bind-9.3.2-prctl_set_dumpable.patch Patch52: bind-9.3.3-edns.patch Patch63: bind-9.4.0-dnssec-directory.patch Patch69: bind-9.5.0-generate-xml.patch -Patch70: bind-9.5.0-errno-init.patch Patch71: bind-9.5-overflow.patch Patch72: bind-9.5-dlz-64bit.patch @@ -180,7 +189,7 @@ chroot(2) jail for the named(8) program from the BIND package. Based off code from Jan "Yenya" Kasprzak %prep -%setup -q -n %{name}-%{version} +%setup -q -n %{name}-%{version}%{BIND_RELEASETYPE}%{BIND_RELEASEVER} tar -xvf %{SOURCE29} patch -p1 -b < patch @@ -206,6 +215,7 @@ cp -fp contrib/sdb/sqlite/sqlitedb.[ch] bin/named cp -fp contrib/sdb/dir/dirdb.[ch] bin/named # SDB tools mkdir -p bin/sdb_tools +cp -fp %{SOURCE30} bin/sdb_tools/ldap2zone.c cp -fp %{SOURCE7} bin/sdb_tools/Makefile.in #cp -fp contrib/sdb/bdb/zone2bdb.c bin/sdb_tools cp -fp contrib/sdb/ldap/{zone2ldap.1,zone2ldap.c} bin/sdb_tools @@ -242,7 +252,6 @@ pushd contrib/idn %patch64 -p0 -b .autotools popd %patch65 -p1 -b .idn -%patch70 -p1 -b .errno-init %patch71 -p1 -b .overflow %patch72 -p1 -b .64bit :; @@ -253,7 +262,9 @@ export CFLAGS="$CFLAGS $RPM_OPT_FLAGS -O0" pushd contrib/idn/idnkit-1.0-src libtoolize --copy --force; aclocal; automake -a; autoconf -%configure +%configure \ + --with-iconv-include=/usr/include/ \ + --with-iconv=-lc make %{?_smp_mflags} popd @@ -686,11 +697,16 @@ rm -rf ${RPM_BUILD_ROOT} %{_sbindir}/bind-chroot-admin %changelog -* Mon Jul 21 2007 Adam Tkac 31:9.5.0a5-5.fc8 +* Tue Jul 24 2007 Adam Tkac 32:9.5.0-6.a6.fc8 +- updated to 9.5.0a6 which contains fixes for CVE-2007-2925 and + CVE-2007-2926 +- fixed building on 64bits + +* Mon Jul 23 2007 Adam Tkac 31:9.5.0a5-5.fc8 - integrated "autotools" patch for testing purposes (upstream will accept it in future, for easier building) -* Mon Jul 21 2007 Adam Tkac 31:9.5.0a5-4.1.fc8 +* Mon Jul 23 2007 Adam Tkac 31:9.5.0a5-4.1.fc8 - fixed DLZ drivers building on 64bit systems * Fri Jul 20 2007 Adam Tkac 31:9.5.0a5-4.fc8 diff --git a/ldap2zone.c b/ldap2zone.c new file mode 100644 index 0000000..58fc515 --- /dev/null +++ b/ldap2zone.c @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2004, 2005 Stig Venaas + * $Id: ldap2zone.c,v 0.1 2005/04/23 21:30:12 venaas Exp $ + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include +#include +#include +#include + +#include + +struct string { + void *data; + size_t len; +}; + +struct assstack_entry { + struct string key; + struct string val; + struct assstack_entry *next; +}; + +struct assstack_entry *assstack_find(struct assstack_entry *stack, struct string *key); +void assstack_push(struct assstack_entry **stack, struct assstack_entry *item); +void assstack_insertbottom(struct assstack_entry **stack, struct assstack_entry *item); +void printsoa(struct string *soa); +void printrrs(char *defaultttl, struct assstack_entry *item); +void print_zone(char *defaultttl, struct assstack_entry *stack); +void usage(char *name); +void err(char *name, const char *msg); +int putrr(struct assstack_entry **stack, struct berval *name, char *type, char *ttl, struct berval *val); + +struct assstack_entry *assstack_find(struct assstack_entry *stack, struct string *key) { + for (; stack; stack = stack->next) + if (stack->key.len == key->len && !memcmp(stack->key.data, key->data, key->len)) + return stack; + return NULL; +} + +void assstack_push(struct assstack_entry **stack, struct assstack_entry *item) { + item->next = *stack; + *stack = item; +} + +void assstack_insertbottom(struct assstack_entry **stack, struct assstack_entry *item) { + struct assstack_entry *p; + + item->next = NULL; + if (!*stack) { + *stack = item; + return; + } + /* find end, should keep track of end somewhere */ + /* really a queue, not a stack */ + p = *stack; + while (p->next) + p = p->next; + p->next = item; +} + +void printsoa(struct string *soa) { + char *s; + size_t i; + + s = (char *)soa->data; + i = 0; + while (i < soa->len) { + putchar(s[i]); + if (s[i++] == ' ') + break; + } + while (i < soa->len) { + putchar(s[i]); + if (s[i++] == ' ') + break; + } + printf("(\n\t\t\t\t"); + while (i < soa->len) { + putchar(s[i]); + if (s[i++] == ' ') + break; + } + printf("; Serialnumber\n\t\t\t\t"); + while (i < soa->len) { + if (s[i] == ' ') + break; + putchar(s[i++]); + } + i++; + printf("\t; Refresh\n\t\t\t\t"); + while (i < soa->len) { + if (s[i] == ' ') + break; + putchar(s[i++]); + } + i++; + printf("\t; Retry\n\t\t\t\t"); + while (i < soa->len) { + if (s[i] == ' ') + break; + putchar(s[i++]); + } + i++; + printf("\t; Expire\n\t\t\t\t"); + while (i < soa->len) { + putchar(s[i++]); + } + printf(" )\t; Minimum TTL\n"); +} + +void printrrs(char *defaultttl, struct assstack_entry *item) { + struct assstack_entry *stack; + char *s; + int first; + size_t i; + char *ttl, *type; + int top; + + s = (char *)item->key.data; + + if (item->key.len == 1 && *s == '@') { + top = 1; + printf("@\t"); + } else { + top = 0; + for (i = 0; i < item->key.len; i++) + putchar(s[i]); + if (item->key.len < 8) + putchar('\t'); + putchar('\t'); + } + + first = 1; + for (stack = (struct assstack_entry *) item->val.data; stack; stack = stack->next) { + ttl = (char *)stack->key.data; + s = strchr(ttl, ' '); + *s++ = '\0'; + type = s; + + if (first) + first = 0; + else + printf("\t\t"); + + if (strcmp(defaultttl, ttl)) + printf("%s", ttl); + putchar('\t'); + + if (top) { + top = 0; + printf("IN\t%s\t", type); + /* Should always be SOA here */ + if (!strcmp(type, "SOA")) { + printsoa(&stack->val); + continue; + } + } else + printf("%s\t", type); + + s = (char *)stack->val.data; + for (i = 0; i < stack->val.len; i++) + putchar(s[i]); + putchar('\n'); + } +} + +void print_zone(char *defaultttl, struct assstack_entry *stack) { + printf("$TTL %s\n", defaultttl); + for (; stack; stack = stack->next) + printrrs(defaultttl, stack); +}; + +void usage(char *name) { + fprintf(stderr, "Usage:%s zone-name LDAP-URL default-ttl [serial]\n", name); + exit(1); +}; + +void err(char *name, const char *msg) { + fprintf(stderr, "%s: %s\n", name, msg); + exit(1); +}; + +int putrr(struct assstack_entry **stack, struct berval *name, char *type, char *ttl, struct berval *val) { + struct string key; + struct assstack_entry *rr, *rrdata; + + /* Do nothing if name or value have 0 length */ + if (!name->bv_len || !val->bv_len) + return 0; + + /* see if already have an entry for this name */ + key.len = name->bv_len; + key.data = name->bv_val; + + rr = assstack_find(*stack, &key); + if (!rr) { + /* Not found, create and push new entry */ + rr = (struct assstack_entry *) malloc(sizeof(struct assstack_entry)); + if (!rr) + return -1; + rr->key.len = name->bv_len; + rr->key.data = (void *) malloc(rr->key.len); + if (!rr->key.data) { + free(rr); + return -1; + } + memcpy(rr->key.data, name->bv_val, name->bv_len); + rr->val.len = sizeof(void *); + rr->val.data = NULL; + if (name->bv_len == 1 && *(char *)name->bv_val == '@') + assstack_push(stack, rr); + else + assstack_insertbottom(stack, rr); + } + + rrdata = (struct assstack_entry *) malloc(sizeof(struct assstack_entry)); + if (!rrdata) { + free(rr->key.data); + free(rr); + return -1; + } + rrdata->key.len = strlen(type) + strlen(ttl) + 1; + rrdata->key.data = (void *) malloc(rrdata->key.len); + if (!rrdata->key.data) { + free(rrdata); + free(rr->key.data); + free(rr); + return -1; + } + sprintf((char *)rrdata->key.data, "%s %s", ttl, type); + + rrdata->val.len = val->bv_len; + rrdata->val.data = (void *) malloc(val->bv_len); + if (!rrdata->val.data) { + free(rrdata->key.data); + free(rrdata); + free(rr->key.data); + free(rr); + return -1; + } + memcpy(rrdata->val.data, val->bv_val, val->bv_len); + + if (!strcmp(type, "SOA")) + assstack_push((struct assstack_entry **) &(rr->val.data), rrdata); + else + assstack_insertbottom((struct assstack_entry **) &(rr->val.data), rrdata); + return 0; +} + +int main(int argc, char **argv) { + char *s, *hostporturl, *base = NULL; + char *ttl, *defaultttl; + LDAP *ld; + char *fltr = NULL; + LDAPMessage *res, *e; + char *a, **ttlvals, **soavals, *serial; + struct berval **vals, **names; + char type[64]; + BerElement *ptr; + int i, j, rc, msgid; + struct assstack_entry *zone = NULL; + + if (argc < 4 || argc > 5) + usage(argv[0]); + + hostporturl = argv[2]; + + if (hostporturl != strstr( hostporturl, "ldap")) + err(argv[0], "Not an LDAP URL"); + + s = strchr(hostporturl, ':'); + + if (!s || strlen(s) < 3 || s[1] != '/' || s[2] != '/') + err(argv[0], "Not an LDAP URL"); + + s = strchr(s+3, '/'); + if (s) { + *s++ = '\0'; + base = s; + s = strchr(base, '?'); + if (s) + err(argv[0], "LDAP URL can only contain host, port and base"); + } + + defaultttl = argv[3]; + + rc = ldap_initialize(&ld, hostporturl); + if (rc != LDAP_SUCCESS) + err(argv[0], "ldap_initialize() failed"); + + if (argc == 5) { + /* serial number specified, check if different from one in SOA */ + fltr = (char *)malloc(strlen(argv[1]) + strlen("(&(relativeDomainName=@)(zoneName=))") + 1); + sprintf(fltr, "(&(relativeDomainName=@)(zoneName=%s))", argv[1]); + msgid = ldap_search(ld, base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0); + if (msgid == -1) + err(argv[0], "ldap_search() failed"); + + while ((rc = ldap_result(ld, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) { + /* not supporting continuation references at present */ + if (rc != LDAP_RES_SEARCH_ENTRY) + err(argv[0], "ldap_result() returned cont.ref? Exiting"); + + /* only one entry per result message */ + e = ldap_first_entry(ld, res); + if (e == NULL) { + ldap_msgfree(res); + err(argv[0], "ldap_first_entry() failed"); + } + + soavals = ldap_get_values(ld, e, "SOARecord"); + if (soavals) + break; + } + + ldap_msgfree(res); + if (!soavals) { + err(argv[0], "No SOA Record found"); + } + + /* We have a SOA, compare serial numbers */ + /* Only checkinf first value, should be only one */ + s = strchr(soavals[0], ' '); + s++; + s = strchr(s, ' '); + s++; + serial = s; + s = strchr(s, ' '); + *s = '\0'; + if (!strcmp(serial, argv[4])) { + ldap_value_free(soavals); + err(argv[0], "serial numbers match"); + } + ldap_value_free(soavals); + } + + if (!fltr) + fltr = (char *)malloc(strlen(argv[1]) + strlen("(zoneName=)") + 1); + if (!fltr) + err(argv[0], "Malloc failed"); + sprintf(fltr, "(zoneName=%s)", argv[1]); + + msgid = ldap_search(ld, base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0); + if (msgid == -1) + err(argv[0], "ldap_search() failed"); + + while ((rc = ldap_result(ld, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) { + /* not supporting continuation references at present */ + if (rc != LDAP_RES_SEARCH_ENTRY) + err(argv[0], "ldap_result() returned cont.ref? Exiting"); + + /* only one entry per result message */ + e = ldap_first_entry(ld, res); + if (e == NULL) { + ldap_msgfree(res); + err(argv[0], "ldap_first_entry() failed"); + } + + names = ldap_get_values_len(ld, e, "relativeDomainName"); + if (!names) + continue; + + ttlvals = ldap_get_values(ld, e, "dNSTTL"); + ttl = ttlvals ? ttlvals[0] : defaultttl; + + for (a = ldap_first_attribute(ld, e, &ptr); a != NULL; a = ldap_next_attribute(ld, e, ptr)) { + char *s; + + for (s = a; *s; s++) + *s = toupper(*s); + s = strstr(a, "RECORD"); + if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) { + ldap_memfree(a); + continue; + } + + strncpy(type, a, s - a); + type[s - a] = '\0'; + vals = ldap_get_values_len(ld, e, a); + if (vals) { + for (i = 0; vals[i]; i++) + for (j = 0; names[j]; j++) + if (putrr(&zone, names[j], type, ttl, vals[i])) + err(argv[0], "malloc failed"); + ldap_value_free_len(vals); + } + ldap_memfree(a); + } + + if (ptr) + ber_free(ptr, 0); + if (ttlvals) + ldap_value_free(ttlvals); + ldap_value_free_len(names); + /* free this result */ + ldap_msgfree(res); + } + + /* free final result */ + ldap_msgfree(res); + + print_zone(defaultttl, zone); + return 0; +} diff --git a/sources b/sources index 635f76a..65197a3 100644 --- a/sources +++ b/sources @@ -1,5 +1,5 @@ -beb3f6e7e8e1f804d1fb79dd11319e1e bind-9.5.0a5.tar.gz +c5e5434487c69841c868bbbeb5cf2dec bind-9.5.0a6.tar.gz 4faa4395b955e5f8a3d50f308b9fabc8 bind-chroot.tar.bz2 bdea8168751a29e61525f11e8195ad48 config.tar 13fef79f99fcefebb51d84b08805de51 libbind-man.tar.gz -ab617c4f99feb2af6e384df8ebe5a9ec bind-9.5.0a5-autotools.tar.bz2 +1def666df0055b00be36c9afe8bbabf5 bind-9.5.0a6-autotools.tar.bz2