]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Sync with trunk
authorYuri Schaeffer <yuri@nlnetlabs.nl>
Thu, 30 Aug 2012 13:36:45 +0000 (13:36 +0000)
committerYuri Schaeffer <yuri@nlnetlabs.nl>
Thu, 30 Aug 2012 13:36:45 +0000 (13:36 +0000)
git-svn-id: file:///svn/unbound/branches/edns-subnet@2756 be551aaa-1e26-0410-a405-d3ace91eadb9

58 files changed:
Makefile.in
config.h.in
configure
configure.ac
contrib/README
contrib/unbound_munin_
contrib/unbound_unixsock.diff [new file with mode: 0644]
daemon/cachedump.c
daemon/daemon.c
daemon/remote.c
daemon/remote.h
daemon/unbound.c
daemon/worker.c
doc/Changelog
doc/example.conf.in
doc/libunbound.3.in
doc/unbound-control.8.in
doc/unbound.conf.5.in
iterator/iter_fwd.c
iterator/iter_hints.c
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c
libunbound/libworker.c
services/cache/infra.c
services/listen_dnsport.c
services/mesh.c
services/outside_network.c
services/outside_network.h
smallapp/unbound-control.c
smallapp/unbound-host.c
testcode/fake_event.c
testcode/testbound.c
testcode/unitmain.c
testcode/unitverify.c
testdata/iter_ds_locate_ns_detach.rpl [new file with mode: 0644]
testdata/val_cnametonodata_nonsec.rpl [new file with mode: 0644]
util/alloc.h
util/config_file.c
util/data/msgparse.c
util/iana_ports.inc
util/log.c
util/net_help.c
util/net_help.h
util/netevent.c
util/random.c
util/rtt.c
util/tube.c
validator/autotrust.c
validator/val_anchor.c
validator/val_neg.c
validator/val_nsec3.c
validator/val_secalgo.c [new file with mode: 0644]
validator/val_secalgo.h [new file with mode: 0644]
validator/val_sigcrypt.c
validator/val_utils.c
validator/validator.c
validator/validator.h

index 7e47bada6dd4a46f825381c51a712333ef244e1e..47057335ab009e9e7462e60b383330755b1779b1 100644 (file)
@@ -30,6 +30,7 @@ PYTHONMOD_INSTALL=@PYTHONMOD_INSTALL@
 PYTHONMOD_UNINSTALL=@PYTHONMOD_UNINSTALL@
 PYUNBOUND_INSTALL=@PYUNBOUND_INSTALL@
 PYUNBOUND_UNINSTALL=@PYUNBOUND_UNINSTALL@
+ALLTARGET=@ALLTARGET@
 
 # _unbound.la if pyunbound enabled.
 PYUNBOUND_TARGET=@PYUNBOUND_TARGET@
@@ -99,8 +100,8 @@ util/storage/lruhash.c util/storage/slabhash.c util/timehist.c util/tube.c \
 util/winsock_event.c validator/autotrust.c validator/val_anchor.c \
 validator/validator.c validator/val_kcache.c validator/val_kentry.c \
 validator/val_neg.c validator/val_nsec3.c validator/val_nsec.c \
-validator/val_sigcrypt.c validator/val_utils.c edns-subnet/edns-subnet.c \
-$(CHECKLOCK_SRC)
+validator/val_secalgo.c validator/val_sigcrypt.c \
+validator/val_utils.c edns-subnet/edns-subnet.c $(CHECKLOCK_SRC)
 COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
 msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
 iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
@@ -110,7 +111,8 @@ fptr_wlist.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
 random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
 slabhash.lo timehist.lo tube.lo winsock_event.lo autotrust.lo val_anchor.lo \
 validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
-val_sigcrypt.lo val_utils.lo edns-subnet.lo $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ)
+val_secalgo.lo val_sigcrypt.lo val_utils.lo edns-subnet.lo $(PYTHONMOD_OBJ) \
+$(CHECKLOCK_OBJ)
 COMMON_OBJ=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
 outside_network.lo
 # set to $COMMON_OBJ or to "" if --enableallsymbols
@@ -228,9 +230,11 @@ COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS)
 LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
 LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(staticexe) -version-info @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined
 
-.PHONY:        clean realclean doc lint all install uninstall tests test strip lib longtest longcheck check
+.PHONY:        clean realclean doc lint all install uninstall tests test strip lib longtest longcheck check alltargets
 
-all:   $(COMMON_OBJ) unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS) $(PYUNBOUND_TARGET)
+all:   $(COMMON_OBJ) $(ALLTARGET)
+
+alltargets:    unbound$(EXEEXT) unbound-checkconf$(EXEEXT) lib unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup $(WINAPPS) $(PYUNBOUND_TARGET)
 
 # compat with BSD make, register suffix, and an implicit rule to actualise it.
 .SUFFIXES: .lo
@@ -465,6 +469,16 @@ install:   all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL)
        $(INSTALL) -c -m 644 doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5
        $(INSTALL) -c -m 644 $(srcdir)/doc/unbound-host.1 $(DESTDIR)$(mandir)/man1
        $(INSTALL) -c -m 644 doc/libunbound.3 $(DESTDIR)$(mandir)/man3
+       for mpage in ub_ctx ub_result ub_ctx_create ub_ctx_delete \
+               ub_ctx_set_option ub_ctx_get_option ub_ctx_config ub_ctx_set_fwd \
+               ub_ctx_resolvconf ub_ctx_hosts ub_ctx_add_ta ub_ctx_add_ta_file \
+               ub_ctx_trustedkeys ub_ctx_debugout ub_ctx_debuglevel ub_ctx_async \
+               ub_poll ub_wait ub_fd ub_process ub_resolve ub_resolve_async ub_cancel \
+               ub_resolve_free ub_strerror ub_ctx_print_local_zones ub_ctx_zone_add \
+               ub_ctx_zone_remove ub_ctx_data_add ub_ctx_data_remove; \
+       do \
+               echo ".so man3/libunbound.3" > $(DESTDIR)$(mandir)/man3/$$mpage.3 ; \
+       done
        $(INSTALL) -c -m 755 unbound-control-setup $(DESTDIR)$(sbindir)/unbound-control-setup
        if test ! -e $(DESTDIR)$(configfile); then $(INSTALL) -d `dirname $(DESTDIR)$(configfile)`; $(INSTALL) -c -m 644 doc/example.conf $(DESTDIR)$(configfile); fi
        $(LIBTOOL) --mode=install cp $(srcdir)/libunbound/unbound.h $(DESTDIR)$(includedir)/unbound.h
@@ -482,6 +496,16 @@ uninstall: $(PYTHONMOD_UNINSTALL) $(PYUNBOUND_UNINSTALL)
        rm -f -- $(DESTDIR)$(sbindir)/unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-host$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-anchor$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control-setup
        rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5 $(DESTDIR)$(mandir)/man8/unbound-control.8 $(DESTDIR)$(mandir)/man8/unbound-anchor.8
        rm -f -- $(DESTDIR)$(mandir)/man1/unbound-host.1 $(DESTDIR)$(mandir)/man3/libunbound.3
+       for mpage in ub_ctx ub_result ub_ctx_create ub_ctx_delete \
+               ub_ctx_set_option ub_ctx_get_option ub_ctx_config ub_ctx_set_fwd \
+               ub_ctx_resolvconf ub_ctx_hosts ub_ctx_add_ta ub_ctx_add_ta_file \
+               ub_ctx_trustedkeys ub_ctx_debugout ub_ctx_debuglevel ub_ctx_async \
+               ub_poll ub_wait ub_fd ub_process ub_resolve ub_resolve_async ub_cancel \
+               ub_resolve_free ub_strerror ub_ctx_print_local_zones ub_ctx_zone_add \
+               ub_ctx_zone_remove ub_ctx_data_add ub_ctx_data_remove; \
+       do \
+               rm -f -- $(DESTDIR)$(mandir)/man3/$$mpage.3 ; \
+       done
        rm -f -- $(DESTDIR)$(includedir)/unbound.h
        $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libunbound.la
        @echo
@@ -563,9 +587,8 @@ msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h \
  $(srcdir)/util/regional.h $(srcdir)/util/net_help.h
 msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h \
  $(srcdir)/util/data/msgparse.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lookup3.h \
- $(srcdir)/util/regional.h
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h
 msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h \
  $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
@@ -674,7 +697,7 @@ modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/service
  $(srcdir)/util/fptr_wlist.h \
  $(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
  $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \
- $(srcdir)/validator/val_utils.h $(PYTHONMOD_HEADER)
+ $(srcdir)/validator/val_utils.h
 outbound_list.lo outbound_list.o: $(srcdir)/services/outbound_list.c config.h \
  $(srcdir)/services/outbound_list.h $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/netevent.h \
@@ -716,8 +739,8 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
  $(srcdir)/util/data/msgparse.h \
  $(srcdir)/util/tube.h \
  $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h \
- $(srcdir)/util/rbtree.h $(srcdir)/daemon/worker.h $(srcdir)/util/alloc.h $(srcdir)/daemon/stats.h \
- $(srcdir)/util/timehist.h $(srcdir)/daemon/remote.h \
+ $(srcdir)/daemon/worker.h $(srcdir)/util/alloc.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/daemon/remote.h \
  $(srcdir)/services/outside_network.h $(srcdir)/services/localzone.h $(srcdir)/services/cache/infra.h \
  $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
  $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
@@ -725,19 +748,12 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
  $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
  $(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/util/storage/dnstree.h \
  $(srcdir)/libunbound/libworker.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/util/config_file.h $(PYTHONMOD_HEADER)
+ $(srcdir)/util/config_file.h
 locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  
 log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h \
  $(srcdir)/util/locks.h
-mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
- $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h \
- $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h
 module.lo module.o: $(srcdir)/util/module.c config.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/data/msgreply.h \
@@ -750,7 +766,7 @@ netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h \
  $(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
  $(srcdir)/services/modstack.h \
- $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
 net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h \
  $(srcdir)/util/net_help.h \
  $(srcdir)/util/log.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
@@ -768,8 +784,7 @@ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h \
  $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
 regional.lo regional.o: $(srcdir)/util/regional.c config.h $(srcdir)/util/log.h \
  $(srcdir)/util/regional.h
-rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.h $(srcdir)/util/log.h \
+rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.h
 dnstree.lo dnstree.o: $(srcdir)/util/storage/dnstree.c config.h $(srcdir)/util/storage/dnstree.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
  $(srcdir)/util/log.h \
@@ -854,12 +869,16 @@ val_nsec.lo val_nsec.o: $(srcdir)/validator/val_nsec.c config.h \
  $(srcdir)/validator/val_utils.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/dname.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
  $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h
+val_secalgo.lo val_secalgo.o: $(srcdir)/validator/val_secalgo.c config.h \
+ $(srcdir)/validator/val_secalgo.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
 val_sigcrypt.lo val_sigcrypt.o: $(srcdir)/validator/val_sigcrypt.c config.h \
  $(srcdir)/validator/val_sigcrypt.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/validator/val_utils.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/rbtree.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
+ $(srcdir)/validator/val_secalgo.h $(srcdir)/validator/validator.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/rbtree.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
  
 val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/validator/val_utils.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
@@ -869,7 +888,7 @@ val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/val
  $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h \
  $(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h
+ $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
 checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/testcode/checklocks.h
 unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h \
@@ -910,11 +929,11 @@ unitverify.lo unitverify.o: $(srcdir)/testcode/unitverify.c config.h $(srcdir)/u
  $(srcdir)/testcode/unitmain.h \
  $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/locks.h \
- $(srcdir)/validator/val_nsec.h \
- $(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h $(srcdir)/validator/validator.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/validator/val_utils.h \
- $(srcdir)/testcode/ldns-testpkts.h \
+ $(srcdir)/validator/val_secalgo.h \
+ $(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/validator/val_utils.h $(srcdir)/testcode/ldns-testpkts.h \
  $(srcdir)/util/data/dname.h \
  $(srcdir)/util/regional.h $(srcdir)/util/alloc.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h
 readhex.lo readhex.o: $(srcdir)/testcode/readhex.c config.h $(srcdir)/testcode/readhex.h \
@@ -930,13 +949,12 @@ cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h \
  $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/util/netevent.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/daemon/stats.h \
- $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
- $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h \
- $(srcdir)/iterator/iter_fwd.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h \
- $(srcdir)/util/storage/dnstree.h
+ $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/rtt.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_delegpt.h \
+ $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_fwd.h \
+ $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h
 daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h \
  $(srcdir)/daemon/daemon.h \
  $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h $(srcdir)/daemon/worker.h \
@@ -946,7 +964,8 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h \
  $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
  $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/localzone.h $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/edns-subnet/edns-subnet.h
+ $(srcdir)/services/localzone.h $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/edns-subnet/edns-subnet.h \
+ $(srcdir)/util/net_help.h
 remote.lo remote.o: $(srcdir)/daemon/remote.c config.h \
  $(srcdir)/daemon/remote.h \
  $(srcdir)/daemon/worker.h $(srcdir)/util/netevent.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h \
@@ -977,8 +996,7 @@ unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h \
  $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/services/cache/infra.h \
  $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/util/net_help.h \
- $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
+ $(srcdir)/util/net_help.h
 worker.lo worker.o: $(srcdir)/daemon/worker.c config.h \
  $(srcdir)/util/log.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/util/netevent.h \
@@ -1001,8 +1019,7 @@ testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/test
  $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h $(srcdir)/util/storage/slabhash.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/net_help.h
 ldns-testpkts.lo ldns-testpkts.o: $(srcdir)/testcode/ldns-testpkts.c config.h \
  $(srcdir)/testcode/ldns-testpkts.h
 worker.lo worker.o: $(srcdir)/daemon/worker.c config.h \
@@ -1033,7 +1050,7 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h \
  $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
  $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/localzone.h $(srcdir)/util/random.h $(srcdir)/util/tube.h
+ $(srcdir)/services/localzone.h $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h
 stats.lo stats.o: $(srcdir)/daemon/stats.c config.h \
  $(srcdir)/daemon/stats.h \
  $(srcdir)/util/timehist.h $(srcdir)/daemon/worker.h $(srcdir)/util/netevent.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
@@ -1091,7 +1108,7 @@ unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c
  $(srcdir)/util/regional.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
  $(srcdir)/iterator/iter_fwd.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
- $(srcdir)/services/localzone.h $(PYTHONMOD_HEADER)
+ $(srcdir)/services/localzone.h
 worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/util/log.h \
  $(srcdir)/services/mesh.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h $(srcdir)/util/data/msgparse.h \
@@ -1166,8 +1183,7 @@ pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c conf
  $(srcdir)/util/data/msgparse.h \
  $(srcdir)/util/netevent.h \
  $(srcdir)/util/net_help.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h
 win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc.h $(srcdir)/winrc/w_inst.h \
  $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/alloc.h \
index cacf294b9089ce6da6c7d4437c11f15f489c6532..bfadf52da3c155d1b3cbec8421cbf094cb976eda 100644 (file)
 /* Define to 1 if you have the `fcntl' function. */
 #undef HAVE_FCNTL
 
+/* Define to 1 if you have the `FIPS_mode' function. */
+#undef HAVE_FIPS_MODE
+
 /* Define to 1 if you have the `fork' function. */
 #undef HAVE_FORK
 
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #undef HAVE_NETINET_IN_H
 
+/* Use libnss for crypto */
+#undef HAVE_NSS
+
 /* Define to 1 if you have the `OPENSSL_config' function. */
 #undef HAVE_OPENSSL_CONFIG
 
index a40f76bd3f08deb4ad28ddcb9e85093fdcb52992..29a05111a562cdd04e72e3c24320aff3a3a3d65a 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for unbound 1.4.18.
+# Generated by GNU Autoconf 2.68 for unbound 1.4.19.
 #
 # Report bugs to <unbound-bugs@nlnetlabs.nl>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='unbound'
 PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.4.18'
-PACKAGE_STRING='unbound 1.4.18'
+PACKAGE_VERSION='1.4.19'
+PACKAGE_STRING='unbound 1.4.19'
 PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
 PACKAGE_URL=''
 
@@ -613,6 +613,7 @@ ac_includes_default="\
 
 ac_subst_vars='LTLIBOBJS
 ldnsdir
+ALLTARGET
 SOURCEFILE
 SOURCEDETERMINE
 UBSYMS
@@ -789,6 +790,7 @@ with_pthreads
 with_solaris_threads
 with_pyunbound
 with_pythonmodule
+with_nss
 with_ssl
 enable_sha2
 enable_gost
@@ -798,6 +800,7 @@ with_libexpat
 enable_static_exe
 enable_lock_checks
 enable_allsymbols
+with_libunbound_only
 with_ldns
 '
       ac_precious_vars='build_alias
@@ -1354,7 +1357,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures unbound 1.4.18 to adapt to many kinds of systems.
+\`configure' configures unbound 1.4.19 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1420,7 +1423,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of unbound 1.4.18:";;
+     short | recursive ) echo "Configuration of unbound 1.4.19:";;
    esac
   cat <<\_ACEOF
 
@@ -1489,6 +1492,7 @@ Optional Packages:
                           (default=no)
   --with-pythonmodule     build Python module, or --without-pythonmodule to
                           disable script engine. (default=no)
+  --with-nss=path         use libnss instead of openssl, installed at path.
   --with-ssl=pathname     enable SSL (will check /usr/local/ssl /usr/lib/ssl
                           /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw
                           /usr)
@@ -1498,6 +1502,7 @@ Optional Packages:
                           an explicit path). Slower, but allows use of large
                           outgoing port ranges.
   --with-libexpat=path    specify explicit path for libexpat.
+  --with-libunbound-only  do not build daemon and tool programs
   --with-ldns=PATH        specify prefix of path of ldns library to use
 
 Some influential environment variables:
@@ -1586,7 +1591,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-unbound configure 1.4.18
+unbound configure 1.4.19
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2112,7 +2117,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by unbound $as_me 1.4.18, which was
+It was created by unbound $as_me 1.4.19, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -2462,7 +2467,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 LIBUNBOUND_CURRENT=3
-LIBUNBOUND_REVISION=3
+LIBUNBOUND_REVISION=4
 LIBUNBOUND_AGE=1
 # 1.0.0 had 0:12:0
 # 1.0.1 had 0:13:0
@@ -2497,6 +2502,7 @@ LIBUNBOUND_AGE=1
 # 1.4.16 had 3:1:1
 # 1.4.17 had 3:2:1
 # 1.4.18 had 3:3:1
+# 1.4.19 had 3:4:1
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
@@ -4210,6 +4216,8 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
+# allow user to override the -g -O2 flags.
+if test "x$CFLAGS" = "x" ; then
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -g" >&5
@@ -4272,6 +4280,7 @@ $as_echo "no" >&6; }
 
 fi
 
+fi
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -15989,6 +15998,39 @@ CONFIG_DATE=`date +%Y%m%d`
 
 # Checks for libraries.
 
+# libnss
+USE_NSS="no"
+
+# Check whether --with-nss was given.
+if test "${with_nss+set}" = set; then :
+  withval=$with_nss;
+       USE_NSS="yes"
+
+$as_echo "#define HAVE_NSS 1" >>confdefs.h
+
+       if test "$withval" != "/usr" -a "$withval" != "" -a "$withval" != "yes"; then
+               CPPFLAGS="$CPPFLAGS -I$withval/include"
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+
+       if test "x$enable_rpath" = xyes; then
+               if echo "$withval/lib" | grep "^/" >/dev/null; then
+                       RUNTIME_PATH="$RUNTIME_PATH -R$withval/lib"
+               fi
+       fi
+
+               CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS"
+       else
+               CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
+       fi
+        LIBS="$LIBS -lnss3 -lnspr4"
+
+
+fi
+
+
+# openssl
+if test $USE_NSS = "no"; then
+
 
 # Check whether --with-ssl was given.
 if test "${with_ssl+set}" = set; then :
@@ -16380,7 +16422,7 @@ fi
 
 done
 
-for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512
+for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -16453,6 +16495,8 @@ cat >>confdefs.h <<_ACEOF
 #define HAVE_DECL_SK_SSL_COMP_POP_FREE $ac_have_decl
 _ACEOF
 
+fi
+
 
 # Check whether --enable-sha2 was given.
 if test "${enable_sha2+set}" = set; then :
@@ -16477,6 +16521,7 @@ if test "${enable_gost+set}" = set; then :
 fi
 
 use_gost="no"
+if test $USE_NSS = "no"; then
 case "$enable_gost" in
        no)
        ;;
@@ -16488,7 +16533,7 @@ else
   as_fn_error $? "OpenSSL 1.0.0 is needed for GOST support" "$LINENO" 5
 fi
 
-        ac_fn_c_check_func "$LINENO" "EC_KEY_new" "ac_cv_func_EC_KEY_new"
+       ac_fn_c_check_func "$LINENO" "EC_KEY_new" "ac_cv_func_EC_KEY_new"
 if test "x$ac_cv_func_EC_KEY_new" = xyes; then :
 
 else
@@ -16610,7 +16655,7 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_gost_works" >&5
 $as_echo "$ac_cv_c_gost_works" >&6; }
 
-       if test $ac_cv_c_gost_works != no; then
+       if test "$ac_cv_c_gost_works" != no; then
                use_gost="yes"
 
 $as_echo "#define USE_GOST 1" >>confdefs.h
@@ -16618,7 +16663,7 @@ $as_echo "#define USE_GOST 1" >>confdefs.h
        fi
        ;;
 esac
-
+fi
 # Check whether --enable-ecdsa was given.
 if test "${enable_ecdsa+set}" = set; then :
   enableval=$enable_ecdsa;
@@ -16629,21 +16674,22 @@ case "$enable_ecdsa" in
     no)
       ;;
     *)
-      ac_fn_c_check_func "$LINENO" "ECDSA_sign" "ac_cv_func_ECDSA_sign"
+      if test $USE_NSS = "no"; then
+             ac_fn_c_check_func "$LINENO" "ECDSA_sign" "ac_cv_func_ECDSA_sign"
 if test "x$ac_cv_func_ECDSA_sign" = xyes; then :
 
 else
   as_fn_error $? "OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa" "$LINENO" 5
 fi
 
-      ac_fn_c_check_func "$LINENO" "SHA384_Init" "ac_cv_func_SHA384_Init"
+             ac_fn_c_check_func "$LINENO" "SHA384_Init" "ac_cv_func_SHA384_Init"
 if test "x$ac_cv_func_SHA384_Init" = xyes; then :
 
 else
   as_fn_error $? "OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa" "$LINENO" 5
 fi
 
-      ac_fn_c_check_decl "$LINENO" "NID_X9_62_prime256v1" "ac_cv_have_decl_NID_X9_62_prime256v1" "$ac_includes_default
+             ac_fn_c_check_decl "$LINENO" "NID_X9_62_prime256v1" "ac_cv_have_decl_NID_X9_62_prime256v1" "$ac_includes_default
 #include <openssl/evp.h>
 
 "
@@ -16680,20 +16726,21 @@ else
   as_fn_error $? "OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa" "$LINENO" 5
 fi
 
-      # see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
-      { $as_echo "$as_me:${as_lineno-$LINENO}: checking if openssl supports SHA2 and ECDSA with EVP" >&5
+             # see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
+             { $as_echo "$as_me:${as_lineno-$LINENO}: checking if openssl supports SHA2 and ECDSA with EVP" >&5
 $as_echo_n "checking if openssl supports SHA2 and ECDSA with EVP... " >&6; }
-      if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+             if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 
 cat >>confdefs.h <<_ACEOF
 #define USE_ECDSA_EVP_WORKAROUND 1
 _ACEOF
 
-      else
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+             else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
+             fi
       fi
       # we now know we have ECDSA and the required curves.
 
@@ -17778,6 +17825,20 @@ rm -f conftest.lo
 
 
 
+# see if we want to build the library or everything
+ALLTARGET="alltargets"
+
+# Check whether --with-libunbound-only was given.
+if test "${with_libunbound_only+set}" = set; then :
+  withval=$with_libunbound_only;
+       if test "$withval" = "yes"; then
+               ALLTARGET="lib"
+       fi
+
+fi
+
+
+
 # check this after all other compilation checks, since the linking of the lib
 # may break checks after this.
 
@@ -17858,11 +17919,15 @@ if test "x$ac_cv_func_ldns_buffer_copy" = xyes; then :
 
 fi
 
-ac_fn_c_check_func "$LINENO" "ldns_key_buf2rsa_raw" "ac_cv_func_ldns_key_buf2rsa_raw"
+if test $USE_NSS = "no"; then
+    ac_fn_c_check_func "$LINENO" "ldns_key_buf2rsa_raw" "ac_cv_func_ldns_key_buf2rsa_raw"
 if test "x$ac_cv_func_ldns_key_buf2rsa_raw" = xyes; then :
 
 fi
 
+else
+        ac_cv_func_ldns_key_buf2rsa_raw="yes"
+fi
 ac_fn_c_check_func "$LINENO" "ldns_get_random" "ac_cv_func_ldns_get_random"
 if test "x$ac_cv_func_ldns_get_random" = xyes; then :
 
@@ -17873,7 +17938,7 @@ if test "x$ac_cv_func_ldns_b32_ntop_extended_hex" = xyes; then :
 
 fi
 
-if test x$use_gost = xyes; then
+if test x$use_gost = xyes -a x$USE_NSS = xno; then
     ac_fn_c_check_func "$LINENO" "ldns_key_EVP_load_gost_id" "ac_cv_func_ldns_key_EVP_load_gost_id"
 if test "x$ac_cv_func_ldns_key_EVP_load_gost_id" = xyes; then :
 
@@ -17891,7 +17956,7 @@ fi
 done
 
 else
-    ac_cv_func_ldns_key_EVP_load_gost_id="yes"
+        ac_cv_func_ldns_key_EVP_load_gost_id="yes"
 fi
 if test x$use_ecdsa = xyes; then
     ac_fn_c_check_decl "$LINENO" "LDNS_ECDSAP384SHA384" "ac_cv_have_decl_LDNS_ECDSAP384SHA384" "
@@ -18561,7 +18626,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by unbound $as_me 1.4.18, which was
+This file was extended by unbound $as_me 1.4.19, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -18627,7 +18692,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-unbound config.status 1.4.18
+unbound config.status 1.4.19
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
index fd00961a720b392b69959f3b624aaedff60e0953..9d5d9c7388c60721229a9fb15b527eb801ff950a 100644 (file)
@@ -6,10 +6,10 @@ sinclude(acx_pthread.m4)
 sinclude(acx_python.m4)
 sinclude(ac_pkg_swig.m4)
 
-AC_INIT(unbound, 1.4.18, unbound-bugs@nlnetlabs.nl, unbound)
+AC_INIT(unbound, 1.4.19, unbound-bugs@nlnetlabs.nl, unbound)
 
 LIBUNBOUND_CURRENT=3
-LIBUNBOUND_REVISION=3
+LIBUNBOUND_REVISION=4
 LIBUNBOUND_AGE=1
 # 1.0.0 had 0:12:0
 # 1.0.1 had 0:13:0
@@ -44,6 +44,7 @@ LIBUNBOUND_AGE=1
 # 1.4.16 had 3:1:1
 # 1.4.17 had 3:2:1
 # 1.4.18 had 3:3:1
+# 1.4.19 had 3:4:1
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
@@ -209,8 +210,11 @@ AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource f
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
 AC_LANG_C
+# allow user to override the -g -O2 flags.
+if test "x$CFLAGS" = "x" ; then
 ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
 ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
+fi
 AC_PROG_CC
 ACX_DEPFLAG
 ACX_DETERMINE_EXT_FLAGS_UNBOUND
@@ -512,11 +516,33 @@ CONFIG_DATE=`date +%Y%m%d`
 AC_SUBST(CONFIG_DATE)
 
 # Checks for libraries.
+
+# libnss
+USE_NSS="no"
+AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path],
+       [use libnss instead of openssl, installed at path.]),
+       [
+       USE_NSS="yes"
+       AC_DEFINE(HAVE_NSS, 1, [Use libnss for crypto])
+       if test "$withval" != "/usr" -a "$withval" != "" -a "$withval" != "yes"; then
+               CPPFLAGS="$CPPFLAGS -I$withval/include"
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               ACX_RUNTIME_PATH_ADD([$withval/lib])
+               CPPFLAGS="-I$withval/include/nspr4 $CPPFLAGS"
+       else
+               CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
+       fi
+        LIBS="$LIBS -lnss3 -lnspr4"
+       ]
+)
+
+# openssl
+if test $USE_NSS = "no"; then
 ACX_WITH_SSL
 ACX_LIB_SSL
 AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
 AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
-AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512])
+AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode])
 AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free], [], [], [
 AC_INCLUDES_DEFAULT
 #ifdef HAVE_OPENSSL_ERR_H
@@ -537,6 +563,8 @@ AC_INCLUDES_DEFAULT
 #include <openssl/ssl.h>
 #include <openssl/evp.h>
 ])
+fi
+
 
 AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
 case "$enable_sha2" in
@@ -647,19 +675,21 @@ AC_MSG_RESULT($ac_cv_c_gost_works)
 
 AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support]))
 use_gost="no"
+if test $USE_NSS = "no"; then
 case "$enable_gost" in
        no)
        ;;
        *)
        AC_CHECK_FUNC(EVP_PKEY_set_type_str, [:],[AC_MSG_ERROR([OpenSSL 1.0.0 is needed for GOST support])])
-        AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([OpenSSL does not support ECC, needed for GOST support])])
+       AC_CHECK_FUNC(EC_KEY_new, [], [AC_MSG_ERROR([OpenSSL does not support ECC, needed for GOST support])])
        AC_CHECK_GOST_WORKS
-       if test $ac_cv_c_gost_works != no; then
+       if test "$ac_cv_c_gost_works" != no; then
                use_gost="yes"
                AC_DEFINE([USE_GOST], [1], [Define this to enable GOST support.])
        fi
        ;;
 esac
+fi dnl !USE_NSS
 
 AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support]))
 use_ecdsa="no"
@@ -667,18 +697,20 @@ case "$enable_ecdsa" in
     no)
       ;;
     *)
-      AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
-      AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
-      AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
+      if test $USE_NSS = "no"; then
+             AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
+             AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
+             AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
 #include <openssl/evp.h>
-      ])
-      # see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
-      AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP])
-      if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then
-       AC_MSG_RESULT([no])
-       AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl])
-      else
-       AC_MSG_RESULT([yes])
+             ])
+             # see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
+             AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP])
+             if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then
+               AC_MSG_RESULT([no])
+               AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl])
+             else
+               AC_MSG_RESULT([yes])
+             fi
       fi
       # we now know we have ECDSA and the required curves.
       AC_DEFINE_UNQUOTED([USE_ECDSA], [1], [Define this to enable ECDSA support.])
@@ -970,6 +1002,17 @@ rm -f conftest.lo
 AC_SUBST(SOURCEDETERMINE)
 AC_SUBST(SOURCEFILE)
 
+# see if we want to build the library or everything
+ALLTARGET="alltargets"
+AC_ARG_WITH(libunbound-only, AC_HELP_STRING([--with-libunbound-only],
+       [do not build daemon and tool programs]),
+       [
+       if test "$withval" = "yes"; then
+               ALLTARGET="lib"
+       fi
+])
+AC_SUBST(ALLTARGET)
+
 # check this after all other compilation checks, since the linking of the lib
 # may break checks after this.
 AC_ARG_WITH(ldns, AC_HELP_STRING([--with-ldns=PATH], 
@@ -991,13 +1034,19 @@ AC_CHECK_LIB(ldns, ldns_rr_new,,[
        AC_MSG_ERROR([No ldns library found, install the ldns library into system lib dir or use --with-ldns=path to other location.  The --with-ldns can point to the make-dir of ldns.  Install the package ldns or download source http://www.nlnetlabs.nl/projects/ldns])
 ])
 AC_CHECK_FUNC(ldns_buffer_copy)
-AC_CHECK_FUNC(ldns_key_buf2rsa_raw)
+if test $USE_NSS = "no"; then
+    AC_CHECK_FUNC(ldns_key_buf2rsa_raw)
+else
+    dnl ignore test
+    ac_cv_func_ldns_key_buf2rsa_raw="yes"
+fi
 AC_CHECK_FUNC(ldns_get_random)
 AC_CHECK_FUNC(ldns_b32_ntop_extended_hex)
-if test x$use_gost = xyes; then
+if test x$use_gost = xyes -a x$USE_NSS = xno; then
     AC_CHECK_FUNC(ldns_key_EVP_load_gost_id)
     AC_CHECK_FUNCS([ldns_key_EVP_unload_gost])
 else
+    dnl ignore test
     ac_cv_func_ldns_key_EVP_load_gost_id="yes"
 fi
 if test x$use_ecdsa = xyes; then
index f5123fc6c8a1e5d4826b66dd0f2a2454cdb37a66..19abd054401a9cb8745820e1ef2f712ee5abdcfe 100644 (file)
@@ -15,3 +15,5 @@ distribution but may be helpful.
        a local-zone and local-data include file for unbound.conf.
 * unbound-host.nagios.patch: makes unbound-host return status that fits right
        in with the nagios monitoring framework.  Contributed by Migiel de Vos.
+* unbound_unixsock.diff: Add Unix socket support for unbound-control. 
+       Contributed by Ilya Bakulin, 2012-08-28.
index db6c33f38af4e2663ea2f8a7e87926a79a404f52..5c047323cae273ea0c41597623ca3082049f9446 100755 (executable)
@@ -230,9 +230,8 @@ if test "$1" = "config" ; then
                echo "graph_args --base 1000 -l 0"
                echo "graph_vlabel queries / second"
                echo "graph_category DNS"
-               for x in thread0.num.queries thread1.num.queries \
-               thread2.num.queries thread3.num.queries thread4.num.queries \
-               thread5.num.queries thread6.num.queries thread7.num.queries; do
+               for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
+                       sed -e 's/=.*//'`; do
                        exist_config $x "queries handled by `basename $x .num.queries`"
                done
                p_config "total.num.queries" "total queries from clients"
@@ -423,9 +422,8 @@ print_value ( ) {
 
 case $id in
 hits)
-       for x in thread0.num.queries thread1.num.queries thread2.num.queries \
-               thread3.num.queries thread4.num.queries thread5.num.queries \
-               thread6.num.queries thread7.num.queries total.num.queries \
+       for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
+               sed -e 's/=.*//'` total.num.queries \
                total.num.cachehits total.num.prefetch num.query.tcp \
                num.query.ipv6 unwanted.queries unwanted.replies; do
                if grep "^"$x"=" $state >/dev/null 2>&1; then
diff --git a/contrib/unbound_unixsock.diff b/contrib/unbound_unixsock.diff
new file mode 100644 (file)
index 0000000..09d05d3
--- /dev/null
@@ -0,0 +1,305 @@
+diff --git a/daemon/remote.c b/daemon/remote.c
+index a2b2204..b6990f3 100644
+--- a/daemon/remote.c
++++ b/daemon/remote.c
+@@ -81,6 +81,11 @@
+ #ifdef HAVE_NETDB_H
+ #include <netdb.h>
+ #endif
++#ifdef HAVE_PWD_H
++#include <pwd.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#endif
+ /* just for portability */
+ #ifdef SQ
+@@ -235,7 +240,8 @@ void daemon_remote_delete(struct daemon_remote* rc)
+  * @return false on failure.
+  */
+ static int
+-add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
++add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
++      struct config_file* cfg)
+ {
+       struct addrinfo hints;
+       struct addrinfo* res;
+@@ -246,29 +252,74 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err)
+       snprintf(port, sizeof(port), "%d", nr);
+       port[sizeof(port)-1]=0;
+       memset(&hints, 0, sizeof(hints));
+-      hints.ai_socktype = SOCK_STREAM;
+-      hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+-      if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
+-#ifdef USE_WINSOCK
+-              if(!noproto_is_err && r == EAI_NONAME) {
+-                      /* tried to lookup the address as name */
+-                      return 1; /* return success, but do nothing */
++
++      if(ip[0] == '/') {
++              /* This looks like UNIX socket! */
++              fd = create_domain_accept_sock(ip);
++/*
++ * When unbound starts, it first creates a socket and then
++ * drops privs, so the socket is created as root user.
++ * This is fine, but we would like to set _unbound user group
++ * for this socket, and permissions should be 0660 so only
++ * root and _unbound group members can invoke unbound-control.
++ * The username used here is the same as username that unbound
++ * uses for its worker processes.
++ */
++
++/*
++ * Note: this code is an exact copy of code from daemon.c
++ * Normally this should be either wrapped into a function,
++ * or gui/gid values should be retrieved at config parsing time
++ * and then stored in configfile structure.
++ * This requires action from unbound developers!
++*/
++#ifdef HAVE_GETPWNAM
++              struct passwd *pwd = NULL;
++              uid_t uid;
++              gid_t gid;
++              /* initialize, but not to 0 (root) */
++              memset(&uid, 112, sizeof(uid));
++              memset(&gid, 112, sizeof(gid));
++              log_assert(cfg);
++
++              if(cfg->username && cfg->username[0]) {
++                      if((pwd = getpwnam(cfg->username)) == NULL)
++                              fatal_exit("user '%s' does not exist.",
++                                      cfg->username);
++                      uid = pwd->pw_uid;
++                      gid = pwd->pw_gid;
++                      endpwent();
+               }
++
++              chown(ip, 0, gid);
++              chmod(ip, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
++#endif
++      } else {
++              hints.ai_socktype = SOCK_STREAM;
++              hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
++              if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
++#ifdef USE_WINSOCK
++                      if(!noproto_is_err && r == EAI_NONAME) {
++                              /* tried to lookup the address as name */
++                              return 1; /* return success, but do nothing */
++                      }
+ #endif /* USE_WINSOCK */
+-                log_err("control interface %s:%s getaddrinfo: %s %s",
+-                      ip?ip:"default", port, gai_strerror(r),
++                      log_err("control interface %s:%s getaddrinfo: %s %s",
++                              ip?ip:"default", port, gai_strerror(r),
+ #ifdef EAI_SYSTEM
+                       r==EAI_SYSTEM?(char*)strerror(errno):""
+ #else
+                       ""
+ #endif
+                       );
+-              return 0;
++                      return 0;
++              }
++
++              /* open fd */
++              fd = create_tcp_accept_sock(res, 1, &noproto);
++              freeaddrinfo(res);
+       }
+-      /* open fd */
+-      fd = create_tcp_accept_sock(res, 1, &noproto);
+-      freeaddrinfo(res);
+       if(fd == -1 && noproto) {
+               if(!noproto_is_err)
+                       return 1; /* return success, but do nothing */
+@@ -305,7 +356,7 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
+       if(cfg->control_ifs) {
+               struct config_strlist* p;
+               for(p = cfg->control_ifs; p; p = p->next) {
+-                      if(!add_open(p->str, cfg->control_port, &l, 1)) {
++                      if(!add_open(p->str, cfg->control_port, &l, 1, cfg)) {
+                               listening_ports_free(l);
+                               return NULL;
+                       }
+@@ -313,12 +364,12 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
+       } else {
+               /* defaults */
+               if(cfg->do_ip6 &&
+-                      !add_open("::1", cfg->control_port, &l, 0)) {
++                      !add_open("::1", cfg->control_port, &l, 0, cfg)) {
+                       listening_ports_free(l);
+                       return NULL;
+               }
+               if(cfg->do_ip4 &&
+-                      !add_open("127.0.0.1", cfg->control_port, &l, 1)) {
++                      !add_open("127.0.0.1", cfg->control_port, &l, 1, cfg)) {
+                       listening_ports_free(l);
+                       return NULL;
+               }
+diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c
+index ea7ec3a..4cb04e2 100644
+--- a/services/listen_dnsport.c
++++ b/services/listen_dnsport.c
+@@ -55,6 +55,10 @@
+ #endif
+ #include <fcntl.h>
++#ifndef USE_WINSOCK
++#include <sys/un.h>
++#endif
++
+ /** number of queued TCP connections for listen() */
+ #define TCP_BACKLOG 5 
+@@ -376,6 +380,53 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
+ }
+ int
++create_domain_accept_sock(char *path) {
++      int s;
++      struct sockaddr_un unixaddr;
++
++#ifndef USE_WINSOCK
++      unixaddr.sun_len = sizeof(unixaddr);
++      unixaddr.sun_family = AF_UNIX;
++      strlcpy(unixaddr.sun_path, path, 104);
++
++      if((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
++              log_err("Cannot create UNIX socket %s (%s)",
++                      path, strerror(errno));
++              return -1;
++      }
++
++      if(unlink(path) && errno != ENOENT) {
++              /* The socket already exists and cannot be removed */
++              log_err("Cannot remove old UNIX socket %s (%s)",
++                      path, strerror(errno));
++              return -1;
++      }
++
++      if(bind(s, (struct sockaddr *) &unixaddr,
++              sizeof(struct sockaddr_un)) == -1) {
++              log_err("Cannot bind UNIX socket %s (%s)",
++                      path, strerror(errno));
++              return -1;
++      }
++
++      if(!fd_set_nonblock(s)) {
++              log_err("Cannot set non-blocking mode");
++              return -1;
++      }
++
++      if(listen(s, TCP_BACKLOG) == -1) {
++              log_err("can't listen: %s", strerror(errno));
++              return -1;
++      }
++
++      return s;
++#else
++      log_err("UNIX sockets are not supported");
++      return -1;
++#endif
++}
++
++int
+ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
+ {
+       int s;
+diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c
+index a872f92..10631fd 100644
+--- a/smallapp/unbound-control.c
++++ b/smallapp/unbound-control.c
+@@ -59,6 +59,8 @@
+ #include "util/locks.h"
+ #include "util/net_help.h"
++#include <sys/un.h>
++
+ /** Give unbound-control usage, and exit (1). */
+ static void
+ usage()
+@@ -158,6 +160,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
+ {
+       struct sockaddr_storage addr;
+       socklen_t addrlen;
++      int addrfamily = 0;
+       int fd;
+       /* use svr or the first config entry */
+       if(!svr) {
+@@ -176,12 +179,21 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
+       if(strchr(svr, '@')) {
+               if(!extstrtoaddr(svr, &addr, &addrlen))
+                       fatal_exit("could not parse IP@port: %s", svr);
++      } else if(svr[0] == '/') {
++              struct sockaddr_un* unixsock = (struct sockaddr_un *) &addr;
++              unixsock->sun_family = AF_UNIX;
++              unixsock->sun_len = sizeof(unixsock);
++              strlcpy(unixsock->sun_path, svr, 104);
++              addrlen = sizeof(struct sockaddr_un);
++              addrfamily = AF_UNIX;
+       } else {
+               if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
+                       fatal_exit("could not parse IP: %s", svr);
+       }
+-      fd = socket(addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET, 
+-              SOCK_STREAM, 0);
++
++      if(addrfamily != AF_UNIX)
++              addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
++      fd = socket(addrfamily, SOCK_STREAM, 0);
+       if(fd == -1) {
+ #ifndef USE_WINSOCK
+               fatal_exit("socket: %s", strerror(errno));
+diff --git a/util/net_help.c b/util/net_help.c
+index b3136a3..5b5b4a3 100644
+--- a/util/net_help.c
++++ b/util/net_help.c
+@@ -45,6 +45,7 @@
+ #include "util/module.h"
+ #include "util/regional.h"
+ #include <fcntl.h>
++#include <sys/un.h>
+ #include <openssl/ssl.h>
+ #include <openssl/err.h>
+@@ -135,7 +136,7 @@ log_addr(enum verbosity_value v, const char* str,
+ {
+       uint16_t port;
+       const char* family = "unknown";
+-      char dest[100];
++      char dest[108];
+       int af = (int)((struct sockaddr_in*)addr)->sin_family;
+       void* sinaddr = &((struct sockaddr_in*)addr)->sin_addr;
+       if(verbosity < v)
+@@ -148,15 +149,23 @@ log_addr(enum verbosity_value v, const char* str,
+               case AF_UNIX: family="unix"; break;
+               default: break;
+       }
+-      if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
+-              strncpy(dest, "(inet_ntop error)", sizeof(dest));
++
++      if(af != AF_UNIX) {
++              if(inet_ntop(af, sinaddr, dest, (socklen_t)sizeof(dest)) == 0) {
++                      strncpy(dest, "(inet_ntop error)", sizeof(dest));
++              }
++              dest[sizeof(dest)-1] = 0;
++              port = ntohs(((struct sockaddr_in*)addr)->sin_port);
++              if(verbosity >= 4)
++                      verbose(v, "%s %s %s port %d (len %d)", str, family,
++                              dest, (int)port, (int)addrlen);
++              else    verbose(v, "%s %s port %d", str, dest, (int)port);
++      } else {
++              struct sockaddr_un* unixsock;
++              unixsock = (struct sockaddr_un *) addr;
++              strlcpy(dest, unixsock->sun_path, sizeof(dest));
++              verbose(v, "%s %s %s", str, family, dest);
+       }
+-      dest[sizeof(dest)-1] = 0;
+-      port = ntohs(((struct sockaddr_in*)addr)->sin_port);
+-      if(verbosity >= 4)
+-              verbose(v, "%s %s %s port %d (len %d)", str, family, dest, 
+-                      (int)port, (int)addrlen);
+-      else    verbose(v, "%s %s port %d", str, dest, (int)port);
+ }
+ int 
index 988e247352e56a310c4f95d3340ae13739d0e5d5..46c625f061af01822760931ecbc188c900c5eb97 100644 (file)
 #include "daemon/cachedump.h"
 #include "daemon/remote.h"
 #include "daemon/worker.h"
-#include "daemon/daemon.h"
 #include "services/cache/rrset.h"
 #include "services/cache/dns.h"
 #include "services/cache/infra.h"
-#include "services/modstack.h"
 #include "util/data/msgreply.h"
 #include "util/regional.h"
 #include "util/net_help.h"
index fd75c23c60df20cc744b2cd1c7bef6b85b84b6bf..2871f32afe7dd47d28a31e50eba2a9fe36760a96 100644 (file)
 #ifdef HAVE_OPENSSL_ENGINE_H
 #include <openssl/engine.h>
 #endif
+
+#ifdef HAVE_NSS
+#include <nss3/nss.h>
+#endif
+
 #include <ldns/ldns.h>
 #include "daemon/daemon.h"
 #include "daemon/worker.h"
@@ -74,6 +79,7 @@
 #include "util/random.h"
 #include "util/tube.h"
 #include "edns-subnet/edns-subnet.h"
+#include "util/net_help.h"
 #include <signal.h>
 
 /** How many quit requests happened. */
@@ -190,20 +196,29 @@ daemon_init(void)
 #endif /* USE_WINSOCK */
        signal_handling_record();
        checklock_start();
+#ifdef HAVE_SSL
        ERR_load_crypto_strings();
        ERR_load_SSL_strings();
-#ifdef HAVE_OPENSSL_CONFIG
+#  ifdef HAVE_OPENSSL_CONFIG
        OPENSSL_config("unbound");
-#endif
-#ifdef USE_GOST
+#  endif
+#  ifdef USE_GOST
        (void)ldns_key_EVP_load_gost_id();
-#endif
+#  endif
        OpenSSL_add_all_algorithms();
-#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
+#  if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
        /* grab the COMP method ptr because openssl leaks it */
        comp_meth = (void*)SSL_COMP_get_compression_methods();
-#endif
+#  endif
        (void)SSL_library_init();
+#  if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+       if(!ub_openssl_lock_init())
+               fatal_exit("could not init openssl locks");
+#  endif
+#elif defined(HAVE_NSS)
+       if(NSS_NoDB_Init(NULL) != SECSuccess)
+               fatal_exit("could not init NSS");
+#endif /* HAVE_SSL or HAVE_NSS */
 #ifdef HAVE_TZSET
        /* init timezone info while we are not chrooted yet */
        tzset();
@@ -541,31 +556,40 @@ daemon_delete(struct daemon* daemon)
        free(daemon->chroot);
        free(daemon->pidfile);
        free(daemon->env);
+#ifdef HAVE_SSL
        SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
        SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
+#endif
        free(daemon);
 #ifdef LEX_HAS_YYLEX_DESTROY
        /* lex cleanup */
        ub_c_lex_destroy();
 #endif
        /* libcrypto cleanup */
-#if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
+#ifdef HAVE_SSL
+#  if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
        ldns_key_EVP_unload_gost();
-#endif
-#if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
-#ifndef S_SPLINT_S
+#  endif
+#  if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
+#    ifndef S_SPLINT_S
        sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free);
-#endif
-#endif
-#ifdef HAVE_OPENSSL_CONFIG
+#    endif
+#  endif
+#  ifdef HAVE_OPENSSL_CONFIG
        EVP_cleanup();
        ENGINE_cleanup();
        CONF_modules_free();
-#endif
+#  endif
        CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
        ERR_remove_state(0);
        ERR_free_strings();
        RAND_cleanup();
+#  if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+       ub_openssl_lock_delete();
+#  endif
+#elif defined(HAVE_NSS)
+       NSS_Shutdown();
+#endif /* HAVE_SSL or HAVE_NSS */
        checklock_stop();
 #ifdef USE_WINSOCK
        if(WSACleanup() != 0) {
index 38ca15c85cdbb4f2b64bf523090c981d3be9c890..5dc05c5fa49fcd58dcaf9207b3d1b8c741147494 100644 (file)
@@ -1286,6 +1286,74 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
                (unsigned)inf.num_msgs, (unsigned)inf.num_keys);
 }
 
+/** callback to delete bogus rrsets */
+static void
+bogus_del_rrset(struct lruhash_entry* e, void* arg)
+{
+       /* entry is locked */
+       struct del_info* inf = (struct del_info*)arg;
+       struct packed_rrset_data* d = (struct packed_rrset_data*)e->data;
+       if(d->security == sec_status_bogus) {
+               d->ttl = inf->expired;
+               inf->num_rrsets++;
+       }
+}
+
+/** callback to delete bogus messages */
+static void
+bogus_del_msg(struct lruhash_entry* e, void* arg)
+{
+       /* entry is locked */
+       struct del_info* inf = (struct del_info*)arg;
+       struct reply_info* d = (struct reply_info*)e->data;
+       if(d->security == sec_status_bogus) {
+               d->ttl = inf->expired;
+               inf->num_msgs++;
+       }
+}
+
+/** callback to delete bogus keys */
+static void
+bogus_del_kcache(struct lruhash_entry* e, void* arg)
+{
+       /* entry is locked */
+       struct del_info* inf = (struct del_info*)arg;
+       struct key_entry_data* d = (struct key_entry_data*)e->data;
+       if(d->isbad) {
+               d->ttl = inf->expired;
+               inf->num_keys++;
+       }
+}
+
+/** remove all rrsets and keys from zone from cache */
+static void
+do_flush_bogus(SSL* ssl, struct worker* worker)
+{
+       struct del_info inf;
+       /* what we do is to set them all expired */
+       inf.worker = worker;
+       inf.now = *worker->env.now;
+       inf.expired = *worker->env.now;
+       inf.expired -= 3; /* handle 3 seconds skew between threads */
+       inf.num_rrsets = 0;
+       inf.num_msgs = 0;
+       inf.num_keys = 0;
+       slabhash_traverse(&worker->env.rrset_cache->table, 1, 
+               &bogus_del_rrset, &inf);
+
+       slabhash_traverse(worker->env.msg_cache, 1, &bogus_del_msg, &inf);
+
+       /* and validator cache */
+       if(worker->env.key_cache) {
+               slabhash_traverse(worker->env.key_cache->slab, 1, 
+                       &bogus_del_kcache, &inf);
+       }
+
+       (void)ssl_printf(ssl, "ok removed %u rrsets, %u messages "
+               "and %u key entries\n", (unsigned)inf.num_rrsets, 
+               (unsigned)inf.num_msgs, (unsigned)inf.num_keys);
+}
+
 /** remove name rrset from cache */
 static void
 do_flush_name(SSL* ssl, struct worker* w, char* arg)
@@ -1393,6 +1461,7 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
                                }
                                if(!delegpt_add_ns_mlc(dp, n, 0)) {
                                        (void)ssl_printf(ssl, "error out of memory\n");
+                                       free(n);
                                        delegpt_free_mlc(dp);
                                        return NULL;
                                }
@@ -1442,7 +1511,6 @@ do_forward(SSL* ssl, struct worker* worker, char* args)
                        return;
                if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
                        (void)ssl_printf(ssl, "error out of memory\n");
-                       delegpt_free_mlc(dp);
                        return;
                }
        }
@@ -1514,7 +1582,6 @@ do_forward_add(SSL* ssl, struct worker* worker, char* args)
        }
        if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
                (void)ssl_printf(ssl, "error out of memory\n");
-               delegpt_free_mlc(dp);
                free(nm);
                return;
        }
@@ -1571,7 +1638,6 @@ do_stub_add(SSL* ssl, struct worker* worker, char* args)
                forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
                if(insecure) anchors_delete_insecure(worker->env.anchors,
                        LDNS_RR_CLASS_IN, nm);
-               delegpt_free_mlc(dp);
                free(nm);
                return;
        }
@@ -2040,6 +2106,8 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
                do_set_option(ssl, worker, skipwhite(p+10));
        } else if(cmdcmp(p, "get_option", 10)) {
                do_get_option(ssl, worker, skipwhite(p+10));
+       } else if(cmdcmp(p, "flush_bogus", 11)) {
+               do_flush_bogus(ssl, worker);
        } else {
                (void)ssl_printf(ssl, "error unknown command '%s'\n", p);
        }
index 5919be4f2a3e2c484aad869e3b534fe92475d7b7..8d5b4125743366cd338b592da5a06a3cbdc0313e 100644 (file)
@@ -69,8 +69,10 @@ struct rc_state {
        struct comm_point* c;
        /** in the handshake part */
        enum { rc_none, rc_hs_read, rc_hs_write } shake_state;
+#ifdef HAVE_SSL
        /** the ssl state */
        SSL* ssl;
+#endif
        /** the rc this is part of */
        struct daemon_remote* rc;
 };
@@ -93,8 +95,10 @@ struct daemon_remote {
        int max_active;
        /** current commpoints busy; should be a short list, malloced */
        struct rc_state* busy_list;
+#ifdef HAVE_SSL
        /** the SSL context for creating new SSL streams */
        SSL_CTX* ctx;
+#endif
 };
 
 /**
@@ -159,6 +163,7 @@ int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*);
 /** handle remote control data callbacks */
 int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*);
 
+#ifdef HAVE_SSL
 /** 
  * Print fixed line of text over ssl connection in blocking mode
  * @param ssl: print to
@@ -185,6 +190,7 @@ int ssl_printf(SSL* ssl, const char* format, ...)
  * @return false on connection failure.
  */
 int ssl_read_line(SSL* ssl, char* buf, size_t max);
+#endif /* HAVE_SSL */
 
 /** routine to printout option values over SSL */
 void remote_get_opt_ssl(char* line, void* arg);
index 6d87a4f6d5c4ace99b2850f82f293edb4ba98a16..d64751ab57a4755f92268718906d8050bd29b563 100644 (file)
 #  include "winrc/win_svc.h"
 #endif
 
+#ifdef HAVE_NSS
+#  include <nss3/nss.h>
+#endif
+
 /** global debug value to keep track of heap memory allocation */
 void* unbound_start_brk = 0;
 
@@ -159,7 +163,12 @@ static void usage()
        get_event_sys(&evnm, &evsys, &evmethod);
        printf("linked libs: %s %s (it uses %s), ldns %s, %s\n", 
                evnm, evsys, evmethod, ldns_version(), 
-               SSLeay_version(SSLEAY_VERSION));
+#ifdef HAVE_SSL
+               SSLeay_version(SSLEAY_VERSION)
+#elif defined(HAVE_NSS)
+               NSS_GetVersion()
+#endif
+               );
        printf("linked modules:");
        for(m = module_list_avail(); *m; m++)
                printf(" %s", *m);
@@ -445,6 +454,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
         * given to unbound on the commandline. */
 
        /* read ssl keys while superuser and outside chroot */
+#ifdef HAVE_SSL
        if(!(daemon->rc = daemon_remote_create(cfg)))
                fatal_exit("could not set up remote-control");
        if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
@@ -454,6 +464,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
        }
        if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL)))
                fatal_exit("could not set up connect SSL_CTX");
+#endif
 
 #ifdef HAVE_KILL
        /* check old pid file before forking */
index 9a6960ed59605df85889df0af41ce0ef91cd8f79..82dfb93fec182e029e492df652363216b8d35213 100644 (file)
@@ -1250,17 +1250,6 @@ worker_delete(struct worker* worker)
        free(worker);
 }
 
-/** compare outbound entry qstates */
-static int
-outbound_entry_compare(void* a, void* b)
-{
-       struct outbound_entry* e1 = (struct outbound_entry*)a;
-       struct outbound_entry* e2 = (struct outbound_entry*)b;
-       if(e1->qstate == e2->qstate)
-               return 1;
-       return 0;
-}
-
 struct outbound_entry*
 worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
        uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
@@ -1277,7 +1266,7 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
                qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
                q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
                addrlen, zone, zonelen, worker_handle_service_reply, e,
-               worker->back->udp_buff, &outbound_entry_compare);
+               worker->back->udp_buff);
        if(!e->qsent) {
                return NULL;
        }
index 046a9947dce983ae37d16023af8aa43aff0413bc..f655cb697b07890c3a10bd9a0c0ba8b438477d56 100644 (file)
@@ -1,3 +1,130 @@
+30 August 2012: Wouter
+       - RFC6725 deprecates RSAMD5: this DNSKEY algorithm is disabled.
+       - iana portlist updated.
+
+29 August 2012: Wouter
+       - Nicer comments outgoing-port-avoid, thanks Stu (bug #465).
+
+22 August 2012: Wouter
+       - Fallback to 1472 and 1232, one fragment size without headers.
+
+21 August 2012: Wouter
+       - Fix timeouts so that when a server has been offline for a while
+         and is probed to see it works, it becomes fully available for
+         server selection again.
+
+17 August 2012: Wouter
+       - Add documentation to libunbound for default nonuse of resolv.conf.
+
+2 August 2012: Wouter
+       - trunk has 1.4.19 under development (fixes from 1 aug and 31 july
+       are for 1.4.19).
+       - iana portlist updated.
+
+1 August 2012: Wouter
+       - Fix openssl race condition, initializes openssl locks, reported
+         by Einar Lonn and Patrik Wallstrom.
+
+31 July 2012: Wouter
+       - Improved forward-first and stub-first documentation.
+       - Fix that enables modules to register twice for the same
+         serviced_query, without race conditions or administration issues.
+         This should not happen with the current codebase, but it is robust.
+       - Fix forward-first option where it sets the RD flag wrongly.
+       - added manpage links for libunbound calls (Thanks Paul Wouters).
+
+30 July 2012: Wouter
+       - tag 1.4.18rc2 (became 1.4.18 release at 2 august 2012).
+
+27 July 2012: Wouter
+       - unbound-host works with libNSS
+       - fix bogus nodata cname chain not reported as bogus by validator,
+         (Thanks Peter van Dijk).
+
+26 July 2012: Wouter
+       - iana portlist updated.
+       - tag 1.4.18rc1.
+
+25 July 2012: Wouter
+       - review fix for libnss, check hash prefix allocation size.
+
+23 July 2012: Wouter
+       - fix missing break for GOST DS hash function.
+       - implemented forward_first for the root.
+
+20 July 2012: Wouter
+       - Fix bug#452 and another assertion failure in mesh.c, makes
+         assertions in mesh.c resist duplicates.  Fixes DS NS search to
+         not generate duplicate sub queries.
+
+19 July 2012: Willem
+       - Fix bug#454: Remove ACX_CHECK_COMPILER_FLAG from configure.ac,
+         if CFLAGS is specified at configure time then '-g -O2' is not
+         appended to CFLAGS, so that the user can override them.
+
+18 July 2012: Willem
+       - Fix libunbound report of errors when in background mode.
+
+11 July 2012: Willem
+       - updated iana ports list.
+
+9 July 2012: Willem
+       - Add flush_bogus option for unbound-control
+
+6 July 2012: Wouter
+       - Fix validation of qtype DS queries that result in no data for
+         non-optout NSEC3 zones.
+
+4 July 2012: Wouter
+       - compile libunbound with libnss on Suse, passes regression tests.
+
+3 July 2012: Wouter
+       - FIPS_mode openssl does not use arc4random but RAND_pseudo_bytes.
+
+2 July 2012: Wouter
+       - updated iana ports list.
+
+29 June 2012: Wouter
+       - patch for unbound_munin_ script to handle arbitrary thread count by
+         Sven Ulland.
+
+28 June 2012: Wouter
+       - detect if openssl has FIPS_mode.
+       - code review: return value of cache_store can be ignored for better
+         performance in out of memory conditions.
+       - fix edns-buffer-size and msg-buffer-size manpage documentation.
+       - updated iana ports list.
+
+25 June 2012: Wouter
+       - disable RSAMD5 if in FIPS mode (for openssl and for libnss).
+
+22 June 2012: Wouter
+       - implement DS records, NSEC3 and ECDSA for compile with libnss.
+
+21 June 2012: Wouter
+       - fix error handling of alloc failure during rrsig verification.
+       - nss check for verification failure.
+       - nss crypto works for RSA and DSA.
+
+20 June 2012: Wouter
+       - work on --with-nss build option (for now, --with-libunbound-only).
+
+19 June 2012: Wouter
+       - --with-libunbound-only build option, only builds the library and
+         not the daemon and other tools.
+
+18 June 2012: Wouter
+       - code review.
+
+15 June 2012: Wouter
+       - implement log-time-ascii on windows.
+       - The key-cache bad key ttl is now 60 seconds.
+       - updated iana ports list.
+       - code review.
+
+11 June 2012: Wouter
+       - bug #452: fix crash on assert in mesh_state_attachment.
+
 30 May 2012: Wouter
        - silence warning from swig-generated code (md set but not used in
          swig initmodule, due to ifdefs in swig-generated code).
index f21a657d65b30ee8308647a3c48eb217a2934b2a..5b9bbdb01416ef095de9e4811245ea3381b51e45 100644 (file)
@@ -67,6 +67,8 @@ server:
        # Use this to make sure unbound does not grab a UDP port that some
        # other server on this computer needs. The default is to avoid
        # IANA-assigned port numbers.
+       # If multiple outgoing-port-permit and outgoing-port-avoid options
+       # are present, they are processed in order.
        # outgoing-port-avoid: "3200-3208"
 
        # number of outgoing simultaneous tcp buffers to hold per thread.
index 80041fd44f9b9dc87cc82214df0cbbee75f7eeee..c825c2eb4620fa29d9613363080b9ecfb626c6c3 100644 (file)
@@ -203,7 +203,9 @@ At this time it is only possible to set configuration before the
 first resolve is done.
 .TP
 .B ub_ctx_resolvconf
-Read list of nameservers to use from the filename given.
+By default the root servers are queried and full resolver mode is used, but
+you can use this call to read the list of nameservers to use from the
+filename given.
 Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
 If they do not support DNSSEC, validation may fail.
 Only nameservers are picked up, the searchdomain, ndots and other
index a095eb7a63efb637bc6befccbf7c7adc4e1c0ff9..f458338c126918425ce1c4a6406fdcca8fbefa92 100644 (file)
@@ -127,6 +127,9 @@ Remove all information at or below the name from the cache.
 The rrsets and key entries are removed so that new lookups will be performed.
 This needs to walk and inspect the entire cache, and is a slow operation.
 .TP
+.B flush_bogus
+Remove all bogus data from the cache.
+.TP
 .B flush_stats
 Reset statistics to zero.
 .TP
index e9fa7f953e7044bfb40cc9d00d12831ccbbb44a7..627a848b1a0e21fde04c678f24049dbb470f5ac1 100644 (file)
@@ -176,7 +176,7 @@ to 0, or if do_tcp is "no", no TCP queries from clients are accepted.
 Number of bytes size to advertise as the EDNS reassembly buffer size.
 This is the value put into datagrams over UDP towards peers.  The actual
 buffer size is determined by msg\-buffer\-size (both for TCP and UDP).  Do
-not set lower than that value.  Default is 4096 which is RFC recommended.
+not set higher than that value.  Default is 4096 which is RFC recommended.
 If you have fragmentation reassembly problems, usually seen as timeouts,
 then a value of 1480 can fix it.  Setting to 512 bypasses even the most
 stringent path MTU problems, but is seen as extreme, since the amount
@@ -994,6 +994,8 @@ the resolver picks up a correct list online.
 .TP
 .B stub\-first: \fI<yes or no>
 If enabled, a query is attempted without the stub clause if it fails.
+The data could not be retrieved and would have caused SERVFAIL because
+the servers are unreachable, instead it is tried without this clause.
 The default is no.
 .SS "Forward Zone Options"
 .LP
@@ -1022,6 +1024,8 @@ To use a nondefault port for DNS communication append '@' with the port number.
 .TP
 .B forward\-first: \fI<yes or no>
 If enabled, a query is attempted without the forward clause if it fails.
+The data could not be retrieved and would have caused SERVFAIL because
+the servers are unreachable, instead it is tried without this clause.
 The default is no.
 .SS "Python Module Options"
 .LP
index 04976db18b8fa931cd19f9fa6f9061db545f8d53..17ca566746de2afa7f3804cb2593a3f69c601f18 100644 (file)
@@ -250,20 +250,22 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
        struct config_stub* s;
        for(s = cfg->forwards; s; s = s->next) {
                struct delegpt* dp;
-               if(!(dp=read_fwds_name(s)) ||
-                       !read_fwds_host(s, dp) ||
-                       !read_fwds_addr(s, dp))
+               if(!(dp=read_fwds_name(s)))
                        return 0;
+               if(!read_fwds_host(s, dp) || !read_fwds_addr(s, dp)) {
+                       delegpt_free_mlc(dp);
+                       return 0;
+               }
                /* set flag that parent side NS information is included.
                 * Asking a (higher up) server on the internet is not useful */
                /* the flag is turned off for 'forward-first' so that the
                 * last resort will ask for parent-side NS record and thus
                 * fallback to the internet name servers on a failure */
                dp->has_parent_side_NS = (uint8_t)!s->isfirst;
-               if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
-                       return 0;
                verbose(VERB_QUERY, "Forward zone server list:");
                delegpt_log(VERB_QUERY, dp);
+               if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
+                       return 0;
        }
        return 1;
 }
index cfb9db7abb8cf420db6f22d536ceb3c253346397..09e4731135dd4b80bdb9f5ec974f8b3c671f2a99 100644 (file)
@@ -126,32 +126,35 @@ compile_time_root_prime(int do_ip4, int do_ip6)
                return NULL;
        dp->has_parent_side_NS = 1;
       if(do_ip4) {
-       if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4"))        return 0;
-       if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
-       if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12"))       return 0;
-       if(!ah(dp, "D.ROOT-SERVERS.NET.", "128.8.10.90"))       return 0;
-       if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
-       if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241"))       return 0;
-       if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4"))      return 0;
-       if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53"))       return 0;
-       if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17"))     return 0;
-       if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30"))     return 0;
-       if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129"))      return 0;
-       if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42"))       return 0;
-       if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33"))      return 0;
+       if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4"))        goto failed;
+       if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) goto failed;
+       if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12"))       goto failed;
+       if(!ah(dp, "D.ROOT-SERVERS.NET.", "128.8.10.90"))       goto failed;
+       if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
+       if(!ah(dp, "F.ROOT-SERVERS.NET.", "192.5.5.241"))       goto failed;
+       if(!ah(dp, "G.ROOT-SERVERS.NET.", "192.112.36.4"))      goto failed;
+       if(!ah(dp, "H.ROOT-SERVERS.NET.", "128.63.2.53"))       goto failed;
+       if(!ah(dp, "I.ROOT-SERVERS.NET.", "192.36.148.17"))     goto failed;
+       if(!ah(dp, "J.ROOT-SERVERS.NET.", "192.58.128.30"))     goto failed;
+       if(!ah(dp, "K.ROOT-SERVERS.NET.", "193.0.14.129"))      goto failed;
+       if(!ah(dp, "L.ROOT-SERVERS.NET.", "199.7.83.42"))       goto failed;
+       if(!ah(dp, "M.ROOT-SERVERS.NET.", "202.12.27.33"))      goto failed;
       }
       if(do_ip6) {
-       if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) return 0;
-       if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) return 0;
-       if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) return 0;
-       if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) return 0;
-       if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) return 0;
-       if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0;
-       if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0;
-       if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) return 0;
-       if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0;
+       if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
+       if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
+       if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed;
+       if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) goto failed;
+       if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed;
+       if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) goto failed;
+       if(!ah(dp, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) goto failed;
+       if(!ah(dp, "L.ROOT-SERVERS.NET.", "2001:500:3::42")) goto failed;
+       if(!ah(dp, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) goto failed;
       }
        return dp;
+failed:
+       delegpt_free_mlc(dp);
+       return 0;
 }
 
 /** insert new hint info into hint structure */
@@ -253,17 +256,19 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg)
        struct config_stub* s;
        struct delegpt* dp;
        for(s = cfg->stubs; s; s = s->next) {
-               if(!(dp=read_stubs_name(s)) ||
-                       !read_stubs_host(s, dp) ||
-                       !read_stubs_addr(s, dp))
+               if(!(dp=read_stubs_name(s)))
+                       return 0;
+               if(!read_stubs_host(s, dp) || !read_stubs_addr(s, dp)) {
+                       delegpt_free_mlc(dp);
                        return 0;
+               }
                /* the flag is turned off for 'stub-first' so that the
                 * last resort will ask for parent-side NS record and thus
                 * fallback to the internet name servers on a failure */
                dp->has_parent_side_NS = (uint8_t)!s->isfirst;
+               delegpt_log(VERB_QUERY, dp);
                if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime))
                        return 0;
-               delegpt_log(VERB_QUERY, dp);
        }
        return 1;
 }
index c7a3f4f529522db09fb8346182442d729de72bdb..a500c75e786ab1ec17709aefebdb74ca1f6e8056 100644 (file)
@@ -418,13 +418,14 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
        return m;
 }
 
-int 
+void 
 iter_dns_store(struct module_env* env, struct query_info* msgqinf,
        struct reply_info* msgrep, int is_referral, uint32_t leeway, int pside,
        struct regional* region)
 {
-       return dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
-               pside, region);
+       if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
+               pside, region))
+               log_err("out of memory: cannot store data in cache");
 }
 
 int 
index 4fb8b005c1971201ab36a0e6b28be9aa2b4bf2e0..8f5a291af6781362d86413c006850b8c0f6f5539 100644 (file)
@@ -124,9 +124,13 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
  * @param pside: true if dp is parentside, thus message is 'fresh' and NS
  *     can be prefetch-updates.
  * @param region: to copy modified (cache is better) rrs back to.
- * @return 0 on alloc error (out of memory).
+ * @return void, because we are not interested in alloc errors,
+ *     the iterator and validator can operate on the results in their
+ *     scratch space (the qstate.region) and are not dependent on the cache.
+ *     It is useful to log the alloc failure (for the server operator),
+ *     but the query resolution can continue without cache storage.
  */
-int iter_dns_store(struct module_env* env, struct query_info* qinf,
+void iter_dns_store(struct module_env* env, struct query_info* qinf,
        struct reply_info* rep, int is_referral, uint32_t leeway, int pside,
        struct regional* region);
 
index af20c4261b7dbcb39ad335353239ef724bd998a6..e3f058fe51229d8cfe672a910df1007a5f1d0a5d 100644 (file)
@@ -259,9 +259,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
        /* do not waste time trying to validate this servfail */
        err.security = sec_status_indeterminate;
        verbose(VERB_ALGO, "store error response in message cache");
-       if(!iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL)) {
-               log_err("error_response_cache: could not store error (nomem)");
-       }
+       iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL);
        return error_response(qstate, id, rcode);
 }
 
@@ -1432,7 +1430,25 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
        verbose(VERB_ALGO, "No more query targets, attempting last resort");
        log_assert(iq->dp);
 
-       if(!iq->dp->has_parent_side_NS) {
+       if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
+               struct delegpt* p = hints_lookup_root(qstate->env->hints,
+                       iq->qchase.qclass);
+               if(p) {
+                       struct delegpt_ns* ns;
+                       struct delegpt_addr* a;
+                       iq->chase_flags &= ~BIT_RD; /* go to authorities */
+                       for(ns = p->nslist; ns; ns=ns->next) {
+                               (void)delegpt_add_ns(iq->dp, qstate->region,
+                                       ns->name, (int)ns->lame);
+                       }
+                       for(a = p->target_list; a; a=a->next_target) {
+                               (void)delegpt_add_addr(iq->dp, qstate->region,
+                                       &a->addr, a->addrlen, a->bogus,
+                                       a->lame);
+                       }
+               }
+               iq->dp->has_parent_side_NS = 1;
+       } else if(!iq->dp->has_parent_side_NS) {
                if(!iter_lookup_parent_NS_from_cache(qstate->env, iq->dp,
                        qstate->region, &qstate->qinfo) 
                        || !iq->dp->has_parent_side_NS) {
@@ -1440,6 +1456,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
                        /* if: no parent NS in cache - go up one level */
                        verbose(VERB_ALGO, "try to grab parent NS");
                        iq->store_parent_NS = iq->dp;
+                       iq->chase_flags &= ~BIT_RD; /* go to authorities */
                        iq->deleg_msg = NULL;
                        iq->refetch_glue = 1;
                        iq->query_restart_count++;
@@ -1541,8 +1558,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
  *         the final state (i.e., on answer).
  */
 static int
-processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq,
-       int id)
+processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
 {
        struct module_qstate* subq = NULL;
        verbose(VERB_ALGO, "processDSNSFind");
@@ -1906,13 +1922,20 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point
                        && !(iq->chase_flags&BIT_RD)
                        && iter_ds_toolow(iq->response, iq->dp)
-                       && iter_dp_cangodown(&iq->qchase, iq->dp))
+                       && iter_dp_cangodown(&iq->qchase, iq->dp)) {
+                       /* close down outstanding requests to be discarded */
+                       outbound_list_clear(&iq->outlist);
+                       iq->num_current_queries = 0;
+                       fptr_ok(fptr_whitelist_modenv_detach_subs(
+                               qstate->env->detach_subs));
+                       (*qstate->env->detach_subs)(qstate);
+                       iq->num_target_queries = 0;
                        return processDSNSFind(qstate, iq, id);
-               if(!iter_dns_store(qstate->env, &iq->response->qinfo,
+               }
+               iter_dns_store(qstate->env, &iq->response->qinfo,
                        iq->response->rep, 0, qstate->prefetch_leeway,
                        iq->dp&&iq->dp->has_parent_side_NS,
-                       qstate->region))
-                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       qstate->region);
                /* close down outstanding requests to be discarded */
                outbound_list_clear(&iq->outlist);
                iq->num_current_queries = 0;
@@ -1949,10 +1972,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                    )) {
                        /* Store the referral under the current query */
                        /* no prefetch-leeway, since its not the answer */
-                       if(!iter_dns_store(qstate->env, &iq->response->qinfo,
-                               iq->response->rep, 1, 0, 0, NULL))
-                               return error_response(qstate, id, 
-                                       LDNS_RCODE_SERVFAIL);
+                       iter_dns_store(qstate->env, &iq->response->qinfo,
+                               iq->response->rep, 1, 0, 0, NULL);
                        if(iq->store_parent_NS)
                                iter_store_parentside_NS(qstate->env, 
                                        iq->response->rep);
@@ -2032,8 +2053,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                if(iq->qchase.qtype == LDNS_RR_TYPE_DS && !iq->dsns_point
                        && !(iq->chase_flags&BIT_RD)
                        && iter_ds_toolow(iq->response, iq->dp)
-                       && iter_dp_cangodown(&iq->qchase, iq->dp))
+                       && iter_dp_cangodown(&iq->qchase, iq->dp)) {
+                       outbound_list_clear(&iq->outlist);
+                       iq->num_current_queries = 0;
+                       fptr_ok(fptr_whitelist_modenv_detach_subs(
+                               qstate->env->detach_subs));
+                       (*qstate->env->detach_subs)(qstate);
+                       iq->num_target_queries = 0;
                        return processDSNSFind(qstate, iq, id);
+               }
                /* Process the CNAME response. */
                if(!handle_cname_response(qstate, iq, iq->response, 
                        &sname, &snamelen))
@@ -2042,10 +2070,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                /* NOTE : set referral=1, so that rrsets get stored but not 
                 * the partial query answer (CNAME only). */
                /* prefetchleeway applied because this updates answer parts */
-               if(!iter_dns_store(qstate->env, &iq->response->qinfo,
+               iter_dns_store(qstate->env, &iq->response->qinfo,
                        iq->response->rep, 1, qstate->prefetch_leeway,
-                       iq->dp&&iq->dp->has_parent_side_NS, NULL))
-                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       iq->dp&&iq->dp->has_parent_side_NS, NULL);
                /* set the current request's qname to the new value. */
                iq->qchase.qname = sname;
                iq->qchase.qname_len = snamelen;
@@ -2555,12 +2582,10 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
                 * but only if we did recursion. The nonrecursion referral
                 * from cache does not need to be stored in the msg cache. */
                if(qstate->query_flags&BIT_RD) {
-                       if(!iter_dns_store(qstate->env, &qstate->qinfo, 
+                       iter_dns_store(qstate->env, &qstate->qinfo, 
                                iq->response->rep, 0, qstate->prefetch_leeway,
                                iq->dp&&iq->dp->has_parent_side_NS,
-                               qstate->region))
-                               return error_response(qstate, id, 
-                                       LDNS_RCODE_SERVFAIL);
+                               qstate->region);
                }
        }
        qstate->return_rcode = LDNS_RCODE_NOERROR;
index 047cd1d0544d9c31837088f66c8c9c30294bbb41..3848cf034fa495fd22a30c09f382871402518597 100644 (file)
@@ -644,6 +644,8 @@ libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s,
                return;
        }
        q->msg_security = s;
+       if(!buf)
+               buf = q->w->env->scratch_buffer;
        if(rcode != 0) {
                error_encode(buf, rcode, NULL, 0, BIT_RD, NULL);
        }
@@ -704,17 +706,6 @@ void libworker_alloc_cleanup(void* arg)
         slabhash_clear(w->env->msg_cache);
 }
 
-/** compare outbound entry qstates */
-static int
-outbound_entry_compare(void* a, void* b)
-{
-        struct outbound_entry* e1 = (struct outbound_entry*)a;
-        struct outbound_entry* e2 = (struct outbound_entry*)b;
-        if(e1->qstate == e2->qstate)
-                return 1;
-        return 0;
-}
-
 struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
         uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
        int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
@@ -730,7 +721,7 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
                qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
                q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
                addrlen, zone, zonelen, libworker_handle_service_reply, e,
-               w->back->udp_buff, &outbound_entry_compare);
+               w->back->udp_buff);
        if(!e->qsent) {
                return NULL;
        }
index dbbd50326e591e8fc5fb6f2e4219ec47d5b53247..c674aca6675477eb37c6250a2ac3eab2f36d860e 100644 (file)
@@ -403,6 +403,11 @@ infra_rtt_update(struct infra_cache* infra, struct sockaddr_storage* addr,
                                data->timeout_other++;
                }
        } else {
+               /* if we got a reply, but the old timeout was above server
+                * selection height, delete the timeout so the server is
+                * fully available again */
+               if(rtt_unclamped(&data->rtt) >= USEFUL_SERVER_TOP_TIMEOUT)
+                       rtt_init(&data->rtt);
                rtt_update(&data->rtt, roundtrip);
                data->probedelay = 0;
                if(qtype == LDNS_RR_TYPE_A)
index 59ca1991eb12141cfc9fd1b442f546bc907c11ff..647cbe07ebd9841b668de96445fe64ea0b2a9b9c 100644 (file)
@@ -323,6 +323,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
                        log_err("setsockopt(..., IP_MTU_DISCOVER, "
                                "IP_PMTUDISC_DONT...) failed: %s",
                                strerror(errno));
+#    ifndef USE_WINSOCK
+                       close(s);
+#    else
+                       closesocket(s);
+#    endif
                        return -1;
                }
 #  elif defined(IP_DONTFRAG)
@@ -331,6 +336,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
                        &off, (socklen_t)sizeof(off)) < 0) {
                        log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
                                strerror(errno));
+#    ifndef USE_WINSOCK
+                       close(s);
+#    else
+                       closesocket(s);
+#    endif
                        return -1;
                }
 #  endif /* IPv4 MTU */
@@ -408,9 +418,11 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
 #ifndef USE_WINSOCK
                log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
                        strerror(errno));
+               close(s);
 #else
                log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
                        wsa_strerror(WSAGetLastError()));
+               closesocket(s);
 #endif
                return -1;
        }
@@ -422,9 +434,11 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
 #ifndef USE_WINSOCK
                        log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
                                strerror(errno));
+                       close(s);
 #else
                        log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
                                wsa_strerror(WSAGetLastError()));
+                       closesocket(s);
 #endif
                        return -1;
                }
@@ -443,23 +457,32 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
                                (struct sockaddr_storage*)addr->ai_addr,
                                addr->ai_addrlen);
                }
+               close(s);
 #else
                log_err("can't bind socket: %s", 
                        wsa_strerror(WSAGetLastError()));
                log_addr(0, "failed address",
                        (struct sockaddr_storage*)addr->ai_addr,
                        addr->ai_addrlen);
+               closesocket(s);
 #endif
                return -1;
        }
        if(!fd_set_nonblock(s)) {
+#ifndef USE_WINSOCK
+               close(s);
+#else
+               closesocket(s);
+#endif
                return -1;
        }
        if(listen(s, TCP_BACKLOG) == -1) {
 #ifndef USE_WINSOCK
                log_err("can't listen: %s", strerror(errno));
+               close(s);
 #else
                log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
+               closesocket(s);
 #endif
                return -1;
        }
@@ -653,8 +676,14 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
                        return 0;
                }
                /* getting source addr packet info is highly non-portable */
-               if(!set_recvpktinfo(s, hints->ai_family))
+               if(!set_recvpktinfo(s, hints->ai_family)) {
+#ifndef USE_WINSOCK
+                       close(s);
+#else
+                       closesocket(s);
+#endif
                        return 0;
+               }
                if(!port_insert(list, s, listen_type_udpancil)) {
 #ifndef USE_WINSOCK
                        close(s);
index 6d16412abb520ed0a430b7f78e1731d05836133e..fdbdc6e5d95c127875b3a61d75c9ed88d6aa79e0 100644 (file)
@@ -676,6 +676,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
        /* find it, if not, create it */
        struct mesh_area* mesh = qstate->env->mesh;
        struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime);
+       int was_detached;
        if(mesh_detect_cycle_found(qstate, sub)) {
                verbose(VERB_ALGO, "attach failed, cycle detected");
                return 0;
@@ -706,9 +707,12 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
                *newq = &sub->s;
        } else
                *newq = NULL;
+       was_detached = (sub->super_set.count == 0);
        if(!mesh_state_attachment(qstate->mesh_info, sub))
                return 0;
-       if(!sub->reply_list && !sub->cb_list && sub->super_set.count == 1) {
+       /* if it was a duplicate  attachment, the count was not zero before */
+       if(!sub->reply_list && !sub->cb_list && was_detached && 
+               sub->super_set.count == 1) {
                /* it used to be detached, before this one got added */
                log_assert(mesh->num_detached_states > 0);
                mesh->num_detached_states--;
@@ -735,16 +739,20 @@ int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub)
        superref->s = super;
        subref->node.key = subref;
        subref->s = sub;
-#ifdef UNBOUND_DEBUG
-       n =
-#endif
-       rbtree_insert(&sub->super_set, &superref->node);
-       log_assert(n != NULL);
+       if(!rbtree_insert(&sub->super_set, &superref->node)) {
+               /* this should not happen, iterator and validator do not
+                * attach subqueries that are identical. */
+               /* already attached, we are done, nothing todo.
+                * since superref and subref already allocated in region,
+                * we cannot free them */
+               return 1;
+       }
 #ifdef UNBOUND_DEBUG
        n =
 #endif
        rbtree_insert(&super->sub_set, &subref->node);
-       log_assert(n != NULL);
+       log_assert(n != NULL); /* we checked above if statement, the reverse
+         administration should not fail now, unless they are out of sync */
        return 1;
 }
 
index e1f51108f06e91b3fc91899f1731eb9b21a268db..10c25a897b32d47d32612b967987302dae0a64ac 100644 (file)
@@ -299,9 +299,11 @@ decomission_pending_tcp(struct outside_network* outnet,
        struct pending_tcp* pend)
 {
        if(pend->c->ssl) {
+#ifdef HAVE_SSL
                SSL_shutdown(pend->c->ssl);
                SSL_free(pend->c->ssl);
                pend->c->ssl = NULL;
+#endif
        }
        comm_point_close(pend->c);
        pend->next_free = outnet->tcp_free;
@@ -1470,7 +1472,7 @@ static void
 serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
        struct comm_reply* rep)
 {
-       struct service_callback* p = sq->cblist, *n;
+       struct service_callback* p;
        int dobackup = (sq->cblist && sq->cblist->next); /* >1 cb*/
        uint8_t *backup_p = NULL;
        size_t backlen = 0;
@@ -1529,8 +1531,9 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
                }
                sq->outnet->svcd_overhead = backlen;
        }
-       while(p) {
-               n = p->next;
+       /* test the actual sq->cblist, because the next elem could be deleted*/
+       while((p=sq->cblist) != NULL) {
+               sq->cblist = p->next; /* remove this element */
                if(dobackup && c) {
                        ldns_buffer_clear(c->buffer);
                        ldns_buffer_write(c->buffer, backup_p, backlen);
@@ -1538,7 +1541,7 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
                }
                fptr_ok(fptr_whitelist_serviced_query(p->cb));
                (void)(*p->cb)(c, p->cb_arg, error, rep);
-               p = n;
+               free(p);
        }
        if(backup_p) {
                free(backup_p);
@@ -1812,38 +1815,22 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
        return 0;
 }
 
-/** find callback in list */
-static struct service_callback*
-callback_list_find(struct serviced_query* sq, void* cb_arg, 
-       int (*arg_compare)(void*,void*))
-{
-       struct service_callback* p;
-       for(p = sq->cblist; p; p = p->next) {
-               if(arg_compare(p->cb_arg, cb_arg))
-                       return p;
-       }
-       return NULL;
-}
-
 struct serviced_query* 
 outnet_serviced_query(struct outside_network* outnet,
        uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
        uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
        int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
        uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
-       void* callback_arg, ldns_buffer* buff, int (*arg_compare)(void*,void*))
+       void* callback_arg, ldns_buffer* buff)
 {
        struct serviced_query* sq;
        struct service_callback* cb;
        struct mesh_reply* reply_list;
        serviced_gen_query(buff, qname, qnamelen, qtype, qclass, flags);
        sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen);
-       if(sq) {
-               /* see if it is a duplicate notification request for cb_arg */
-               if(callback_list_find(sq, callback_arg, arg_compare)) {
-                       return sq;
-               }
-       }
+       /* duplicate entries are inclded in the callback list, because
+        * there is a counterpart registration by our caller that needs to
+        * be doubly-removed (with callbacks perhaps). */
        if(!(cb = (struct service_callback*)malloc(sizeof(*cb))))
                return NULL;
        if(!sq) {
index 57c2ba81f06d3cb68df9172bf9aac9b1db9e98c2..74208441b411fb4cc9b2a08e0951d480af4aa5bb 100644 (file)
@@ -281,9 +281,9 @@ struct service_callback {
 };
 
 /** fallback size for fragmentation for EDNS in IPv4 */
-#define EDNS_FRAG_SIZE_IP4 1480
+#define EDNS_FRAG_SIZE_IP4 1472
 /** fallback size for EDNS in IPv6, fits one fragment with ip6-tunnel-ids */
-#define EDNS_FRAG_SIZE_IP6 1260
+#define EDNS_FRAG_SIZE_IP6 1232
 
 /**
  * Query service record.
@@ -473,8 +473,6 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
        authoritative.
  * @param zonelen: length of zone.
  * @param buff: scratch buffer to create query contents in. Empty on exit.
- * @param arg_compare: function to compare callback args, return true if 
- *     identical. It is given the callback_arg and args that are listed.
  * @return 0 on error, or pointer to serviced query that is used to answer
  *     this serviced query may be shared with other callbacks as well.
  */
@@ -483,8 +481,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
        uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
        int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
        uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
-       void* callback_arg, ldns_buffer* buff,
-       int (*arg_compare)(void*,void*));
+       void* callback_arg, ldns_buffer* buff);
 
 /**
  * Remove service query callback.
index 58be7b7abfc02ea27b961e8d1e35debdb7828ef3..e438b3d20a1b28cd33a13014cf1b0d20c570f5d7 100644 (file)
@@ -93,6 +93,7 @@ usage()
        printf("  flush_type <name> <type>      flush name, type from cache\n");
        printf("  flush_zone <name>             flush everything at or under name\n");
        printf("                                from rr and dnssec caches\n");
+       printf("  flush_bogus                   flush all bogus data\n");
        printf("  flush_stats                   flush statistics, make zero\n");
        printf("  flush_requestlist             drop queries that are worked on\n");
        printf("  dump_requestlist              show what is worked on\n");
@@ -379,7 +380,8 @@ int main(int argc, char* argv[])
        if(!RAND_status()) {
                 /* try to seed it */
                 unsigned char buf[256];
-                unsigned int v, seed=(unsigned)time(NULL) ^ (unsigned)getpid();
+                unsigned int seed=(unsigned)time(NULL) ^ (unsigned)getpid();
+               unsigned int v = seed;
                 size_t i;
                 for(i=0; i<256/sizeof(v); i++) {
                         memmove(buf+i*sizeof(v), &v, sizeof(v));
index 095396749ff114e57aec582cb142ebfe6caef802..ed52a551f9fc1c24af20e2a392b26e7338e20615 100644 (file)
@@ -61,6 +61,9 @@
 #endif
 #include "libunbound/unbound.h"
 #include <ldns/ldns.h>
+#ifdef HAVE_NSS
+#include <nss3/nss.h>
+#endif
 
 /** verbosity for unbound-host app */
 static int verb = 0;
@@ -509,6 +512,12 @@ int main(int argc, char* argv[])
        if(argc != 1)
                usage();
 
+#ifdef HAVE_NSS
+        if(NSS_NoDB_Init(".") != SECSuccess) {
+               fprintf(stderr, "could not init NSS\n");
+               return 1;
+       }
+#endif
        lookup(ctx, argv[0], qtype, qclass);
        return 0;
 }
index 69dc871e51491bbad2108b3bb879edb0cffbb12e..c736fba4b9e6259c88c3a18a82eac64d77da0632 100644 (file)
@@ -1042,14 +1042,13 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
        int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
        struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
        size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
-       ldns_buffer* ATTR_UNUSED(buff), int (*arg_compare)(void*,void*))
+       ldns_buffer* ATTR_UNUSED(buff))
 {
        struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
        struct fake_pending* pend = (struct fake_pending*)calloc(1,
                sizeof(struct fake_pending));
        char z[256];
        ldns_status status;
-       (void)arg_compare;
        log_assert(pend);
        log_nametypeclass(VERB_OPS, "pending serviced query", 
                qname, qtype, qclass);
index 05982849cc29ce596f3f3255e6e843838178ccb1..6e88edf22e625a9cd7c4d3dd32dabda02b3fafdb 100644 (file)
@@ -281,7 +281,7 @@ main(int argc, char* argv[])
                        printf("selftest successful\n");
                        exit(0);
                case '2':
-#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
+#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
                        printf("SHA256 supported\n");
                        exit(0);
 #else
index f381b0b03e2351d34ea9d29a7a7cde03d21d4566..6dcb95eb9f0e6c29c7dc1f0717879f4a9daef1a4 100644 (file)
 #ifdef HAVE_OPENSSL_ENGINE_H
 #include <openssl/engine.h>
 #endif
+
+#ifdef HAVE_NSS
+#include "nss3/nss.h"
+#endif
+
 #include <ldns/ldns.h>
 #include "util/log.h"
 #include "testcode/unitmain.h"
@@ -555,13 +560,18 @@ main(int argc, char* argv[])
                return 1;
        }
        printf("Start of %s unit test.\n", PACKAGE_STRING);
+#ifdef HAVE_SSL
        ERR_load_crypto_strings();
-#ifdef HAVE_OPENSSL_CONFIG
+#  ifdef HAVE_OPENSSL_CONFIG
        OPENSSL_config("unbound");
-#endif
-#ifdef USE_GOST
+#  endif
+#  ifdef USE_GOST
        (void)ldns_key_EVP_load_gost_id();
-#endif
+#  endif
+#elif defined(HAVE_NSS)
+       if(NSS_NoDB_Init(".") != SECSuccess)
+               fatal_exit("could not init NSS");
+#endif /* HAVE_SSL or HAVE_NSS*/
        checklock_start();
        neg_test();
        rnd_test();
@@ -579,18 +589,23 @@ main(int argc, char* argv[])
        msgparse_test();
        checklock_stop();
        printf("%d checks ok.\n", testcount);
-#if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
+#ifdef HAVE_SSL
+#  if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
        ldns_key_EVP_unload_gost();
-#endif
-#ifdef HAVE_OPENSSL_CONFIG
+#  endif
+#  ifdef HAVE_OPENSSL_CONFIG
        EVP_cleanup();
        ENGINE_cleanup();
        CONF_modules_free();
-#endif
+#  endif
        CRYPTO_cleanup_all_ex_data();
        ERR_remove_state(0);
        ERR_free_strings();
        RAND_cleanup();
+#elif defined(HAVE_NSS)
+       if(NSS_Shutdown() != SECSuccess)
+               fatal_exit("could not shutdown NSS");
+#endif /* HAVE_SSL or HAVE_NSS */
 #ifdef HAVE_PTHREAD
        /* dlopen frees its thread specific state */
        pthread_exit(NULL);
index 2bc842c75374165f0880c10a35d29ff96695e26e..5da66496820666c991f035e3eec5fe061a869917 100644 (file)
@@ -42,6 +42,7 @@
 #include "util/log.h"
 #include "testcode/unitmain.h"
 #include "validator/val_sigcrypt.h"
+#include "validator/val_secalgo.h"
 #include "validator/val_nsec.h"
 #include "validator/val_nsec3.h"
 #include "validator/validator.h"
@@ -505,12 +506,12 @@ verify_test(void)
        verifytest_file("testdata/test_signatures.6", "20080416005004");
        verifytest_file("testdata/test_signatures.7", "20070829144150");
        verifytest_file("testdata/test_signatures.8", "20070829144150");
-#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
+#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
        verifytest_file("testdata/test_sigs.rsasha256", "20070829144150");
        verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150");
        verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000");
 #endif
-#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
+#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS)) && defined(USE_SHA2)
        verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150");
 #endif
        verifytest_file("testdata/test_sigs.hinfo", "20090107100022");
@@ -521,8 +522,11 @@ verify_test(void)
        else printf("Warning: skipped GOST, openssl does not provide gost.\n");
 #endif
 #ifdef USE_ECDSA
-       verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439");
-       verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439");
+       /* test for support in case we use libNSS and ECC is removed */
+       if(dnskey_algo_id_is_supported(LDNS_ECDSAP256SHA256)) {
+               verifytest_file("testdata/test_sigs.ecdsa_p256", "20100908100439");
+               verifytest_file("testdata/test_sigs.ecdsa_p384", "20100908100439");
+       }
        dstest_file("testdata/test_ds.sha384");
 #endif
        dstest_file("testdata/test_ds.sha1");
diff --git a/testdata/iter_ds_locate_ns_detach.rpl b/testdata/iter_ds_locate_ns_detach.rpl
new file mode 100644 (file)
index 0000000..9288fe5
--- /dev/null
@@ -0,0 +1,296 @@
+; config options
+server:
+       target-fetch-policy: "3 2 1 0 0"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test locate of NS records for DS and with detached queries
+; the additional targets looked up cause detached queries.
+; hence the target fetch policy is increased above.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+       ADDRESS 193.0.14.129 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS        K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id 
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN A
+SECTION ANSWER
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+SECTION AUTHORITY
+root-servers.net. IN NS        K.ROOT-SERVERS.NET.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id 
+REPLY QR AA NOERROR
+SECTION QUESTION
+k.root-servers.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+root-servers.net. IN SOA       K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id 
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+. IN SOA       K.ROOT-SERVERS.NET. hostmaster. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net.   IN NS   a.server.net.
+net.   IN NS   b.server.net.
+net.   IN NS   c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.server.net.
+; The b.server.net and c.server.net servers are here to cause
+; extra lookups to be generated (to create detached queries in the
+; iterator), there is no IP address that answers for them set up.
+; force DSNSFind, we host a grandchild zone.
+; also, this range of steps is without responses for b and c, so that
+; they can be force to happen later (after the DSNS is activated).
+RANGE_BEGIN 0 20
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net.   IN NS   a.server.net.
+net.   IN NS   b.server.net.
+net.   IN NS   c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.server.net. IN A
+SECTION ANSWER
+a.server.net. IN A 192.5.6.30
+SECTION AUTHORITY
+net.   IN NS   a.server.net.
+net.   IN NS   b.server.net.
+net.   IN NS   c.server.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.sub.example.net. IN DS
+SECTION AUTHORITY
+sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.net. IN NS
+SECTION ANSWER
+sub.example.net. IN NS a.server.net.
+sub.example.net. IN NS b.server.net.
+sub.example.net. IN NS c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.sub.example.net. IN A
+SECTION AUTHORITY
+sub.example.net. IN NS a.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.server.net range with all the answers (to finish the test).
+RANGE_BEGIN 30 100
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net.   IN NS   a.server.net.
+net.   IN NS   b.server.net.
+net.   IN NS   c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.server.net. IN A
+SECTION ANSWER
+a.server.net. IN A 192.5.6.30
+SECTION AUTHORITY
+net.   IN NS   a.server.net.
+net.   IN NS   b.server.net.
+net.   IN NS   c.server.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.server.net. IN AAAA
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+b.server.net. IN A
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+b.server.net. IN AAAA
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.server.net. IN A
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+c.server.net. IN AAAA
+SECTION AUTHORITY
+net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.sub.example.net. IN DS
+SECTION AUTHORITY
+sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.net. IN NS
+SECTION ANSWER
+sub.example.net. IN NS a.server.net.
+sub.example.net. IN NS b.server.net.
+sub.example.net. IN NS c.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+a.sub.example.net. IN A
+SECTION AUTHORITY
+sub.example.net. IN NS a.server.net.
+SECTION ADDITIONAL
+a.server.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+a.sub.example.net. IN DS
+ENTRY_END
+
+; make traffic flow at this time
+STEP 15 TRAFFIC
+
+STEP 20 TRAFFIC
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+a.sub.example.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.net. IN SOA a.gtld-servers.net. hostmaster. 2 3 4 5 6
+SECTION ADDITIONAL
+ENTRY_END
+
+STEP 50 TRAFFIC
+
+SCENARIO_END
diff --git a/testdata/val_cnametonodata_nonsec.rpl b/testdata/val_cnametonodata_nonsec.rpl
new file mode 100644 (file)
index 0000000..5a26363
--- /dev/null
@@ -0,0 +1,262 @@
+; config options
+; The island of trust is at example.com
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+       trust-anchor: "example.net.    3600    IN      DNSKEY  256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}"
+       val-override-date: "20070916134226"
+       target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with cname to nodata
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+       ADDRESS 193.0.14.129 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS        K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION AUTHORITY
+net.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com.    IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.     IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net.    IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.     IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com.    IN NS   ns.example.com.
+example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com.         IN      A       1.2.3.4
+ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com.    3600    IN      DNSKEY  256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600    IN      RRSIG   DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+; NSEC here ...
+SECTION ADDITIONAL
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com.  3600    IN      CNAME   www.example.net.
+www.example.com.        3600    IN      RRSIG   CNAME 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFGtYzScyRnHV8U/jOIPYwrlI9t3oAhRF0PIf+IthUR7uCWIvskWp5CfReQ== ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net.   IN NS   ns.example.net.
+example.net.    3600    IN      RRSIG   NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.5
+ns.example.net. 3600    IN      RRSIG   A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN DNSKEY
+SECTION ANSWER
+example.net.    3600    IN      DNSKEY  256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+example.net.    3600    IN      RRSIG   DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899}
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+example.net.    3600    IN      RRSIG   NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.5
+ns.example.net. 3600    IN      RRSIG   A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+; NSEC here
+SECTION ADDITIONAL
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+;www.example.net. IN NSEC      example.net. MX NSEC RRSIG
+;www.example.net.        3600    IN      RRSIG   NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. Z+3/WKJEqhWoMOQLC7Yb1dTVGaqzmU0bZ2cH9jSfNQZiT0O37yzCNNUmMsW4gsJOh3o61iZ+hxpze3aO3aedqQ== ;{id = 30899}
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+www.example.net. IN NSEC       example.net. MX NSEC RRSIG
+www.example.net.        3600    IN      RRSIG   NSEC 5 3 3600 20070926134150 20070829134150 30899 example.net. Z+3/WKJEqhWoMOQLC7Yb1dTVGaqzmU0bZ2cH9jSfNQZiT0O37yzCNNUmMsW4gsJOh3o61iZ+hxpze3aO3aedqQ== ;{id = 30899}
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
index 4ed0053e2b4afab0fd1ba201b61280acd42bd5a3..cb8d6b1bceb7dde4e49650533f851c702e6752e3 100644 (file)
@@ -177,8 +177,11 @@ void alloc_set_id_cleanup(struct alloc_cache* alloc, void (*cleanup)(void*),
        void* arg);
 
 #ifdef UNBOUND_ALLOC_LITE
+#  include <ldns/ldns.h>
 #  include <ldns/packet.h>
-#  include <openssl/ssl.h>
+#  ifdef HAVE_OPENSSL_SSL_H
+#    include <openssl/ssl.h>
+#  endif
 #  define malloc(s) unbound_stat_malloc_lite(s, __FILE__, __LINE__, __func__)
 #  define calloc(n,s) unbound_stat_calloc_lite(n, s, __FILE__, __LINE__, __func__)
 #  define free(p) unbound_stat_free_lite(p, __FILE__, __LINE__, __func__)
index cf95092581a638fdca95eb1ad018d209b5da1950..f4053d5786c8fd19ce697fd65efc7fa418de1e06 100644 (file)
@@ -1053,9 +1053,9 @@ static int isalldigit(const char* str, size_t l)
 int 
 cfg_parse_memsize(const char* str, size_t* res)
 {
-       size_t len = (size_t)strlen(str);
+       size_t len;
        size_t mult = 1;
-       if(!str || len == 0) {
+       if(!str || (len=(size_t)strlen(str)) == 0) {
                log_err("not a size: '%s'", str);
                return 0;
        }
index 7af3fc0fdad43093497ba652ca8ff5a4f1f7cdee..e5f00551b1f5c289c538dbedbf0f3cd8f1083796 100644 (file)
@@ -39,7 +39,6 @@
 #include "config.h"
 #include <ldns/ldns.h>
 #include "util/data/msgparse.h"
-#include "util/net_help.h"
 #include "util/data/dname.h"
 #include "util/data/packed_rrset.h"
 #include "util/storage/lookup3.h"
@@ -655,8 +654,10 @@ calc_size(ldns_buffer* pkt, uint16_t type, struct rr_parse* rr)
                                len = 0;
                                break;
                        case LDNS_RDF_TYPE_STR:
-                               if(pkt_len < 1)
+                               if(pkt_len < 1) {
+                                       /* NOTREACHED, due to 'while(>0)' */
                                        return 0; /* len byte exceeds rdata */
+                               }
                                len = ldns_buffer_current(pkt)[0] + 1;
                                break;
                        default:
index 58a571cf4f8d7800886011517e62b123e48a4417..8260326ed0fdd8d5b74c9782aceacd0c4d971d60 100644 (file)
 1022,
 1025,
 1026,
-1028,
+1027,
 1029,
 1030,
 1031,
 4425,
 4426,
 4430,
+4432,
 4441,
 4442,
 4443,
 5556,
 5567,
 5568,
+5569,
 5573,
 5580,
 5581,
 6085,
 6086,
 6087,
+6088,
 6100,
 6101,
 6102,
 6162,
 6163,
 6200,
+6201,
 6222,
 6241,
 6242,
 6626,
 6627,
 6628,
+6633,
 6657,
 6670,
 6671,
 8057,
 8058,
 8059,
+8060,
 8074,
 8080,
 8081,
 8555,
 8567,
 8600,
+8609,
 8610,
 8611,
 8612,
 9801,
 9802,
 9875,
-9876,
+9878,
 9888,
 9889,
 9898,
 24677,
 24678,
 24680,
+24850,
 24922,
 25000,
 25001,
 25901,
 25902,
 25903,
+25954,
+25955,
 26000,
 26133,
 26208,
 43188,
 43189,
 43190,
+43210,
 43439,
 43440,
 43441,
index fc07dc6a9cba253c86e9d698ce10a291b504ca45..8c09c7ce3122652bae293d3eabade15df377e593 100644 (file)
@@ -171,6 +171,8 @@ log_vmsg(int pri, const char* type,
 #if defined(HAVE_STRFTIME) && defined(HAVE_LOCALTIME_R) 
        char tmbuf[32];
        struct tm tm;
+#elif defined(UB_ON_WINDOWS)
+       char tmbuf[128], dtbuf[128];
 #endif
        (void)pri;
        vsnprintf(message, sizeof(message), format, args);
@@ -218,6 +220,13 @@ log_vmsg(int pri, const char* type,
                fprintf(logfile, "%s %s[%d:%x] %s: %s\n", tmbuf, 
                        ident, (int)getpid(), tid?*tid:0, type, message);
        } else
+#elif defined(UB_ON_WINDOWS)
+       if(log_time_asc && GetTimeFormat(LOCALE_USER_DEFAULT, 0, NULL, NULL,
+               tmbuf, sizeof(tmbuf)) && GetDateFormat(LOCALE_USER_DEFAULT, 0,
+               NULL, NULL, dtbuf, sizeof(dtbuf))) {
+               fprintf(logfile, "%s %s %s[%d:%x] %s: %s\n", dtbuf, tmbuf, 
+                       ident, (int)getpid(), tid?*tid:0, type, message);
+       } else
 #endif
        fprintf(logfile, "[%u] %s[%d:%x] %s: %s\n", (unsigned)now, 
                ident, (int)getpid(), tid?*tid:0, type, message);
index 948c241c4506cc3167209719e99b5099bc171cc1..d89cd647de9a73e7ab6ea840fee9b1dfbb214ba3 100644 (file)
 #include "util/module.h"
 #include "util/regional.h"
 #include <fcntl.h>
+#ifdef HAVE_OPENSSL_SSL_H
 #include <openssl/ssl.h>
+#endif
+#ifdef HAVE_OPENSSL_ERR_H
 #include <openssl/err.h>
+#endif
 
 /** max length of an IP address (the address portion) that we allow */
 #define MAX_ADDR_STRLEN 128 /* characters */
@@ -569,6 +573,7 @@ void sock_list_merge(struct sock_list** list, struct regional* region,
 void
 log_crypto_err(const char* str)
 {
+#ifdef HAVE_SSL
        /* error:[error code]:[library name]:[function name]:[reason string] */
        char buf[128];
        unsigned long e;
@@ -578,10 +583,14 @@ log_crypto_err(const char* str)
                ERR_error_string_n(e, buf, sizeof(buf));
                log_err("and additionally crypto %s", buf);
        }
+#else
+       (void)str;
+#endif /* HAVE_SSL */
 }
 
 void* listen_sslctx_create(char* key, char* pem, char* verifypem)
 {
+#ifdef HAVE_SSL
        SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
        if(!ctx) {
                log_crypto_err("could not SSL_CTX_new");
@@ -623,10 +632,15 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem)
                SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
        }
        return ctx;
+#else
+       (void)key; (void)pem; (void)verifypem;
+       return NULL;
+#endif
 }
 
 void* connect_sslctx_create(char* key, char* pem, char* verifypem)
 {
+#ifdef HAVE_SSL
        SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
        if(!ctx) {
                log_crypto_err("could not allocate SSL_CTX pointer");
@@ -666,10 +680,15 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem)
                SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
        }
        return ctx;
+#else
+       (void)key; (void)pem; (void)verifypem;
+       return NULL;
+#endif
 }
 
 void* incoming_ssl_fd(void* sslctx, int fd)
 {
+#ifdef HAVE_SSL
        SSL* ssl = SSL_new((SSL_CTX*)sslctx);
        if(!ssl) {
                log_crypto_err("could not SSL_new");
@@ -683,10 +702,15 @@ void* incoming_ssl_fd(void* sslctx, int fd)
                return NULL;
        }
        return ssl;
+#else
+       (void)sslctx; (void)fd;
+       return NULL;
+#endif
 }
 
 void* outgoing_ssl_fd(void* sslctx, int fd)
 {
+#ifdef HAVE_SSL
        SSL* ssl = SSL_new((SSL_CTX*)sslctx);
        if(!ssl) {
                log_crypto_err("could not SSL_new");
@@ -700,4 +724,61 @@ void* outgoing_ssl_fd(void* sslctx, int fd)
                return NULL;
        }
        return ssl;
+#else
+       (void)sslctx; (void)fd;
+       return NULL;
+#endif
+}
+
+#if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+/** global lock list for openssl locks */
+static lock_basic_t *ub_openssl_locks = NULL;
+
+/** callback that gets thread id for openssl */
+static unsigned long
+ub_crypto_id_cb(void)
+{
+       return (unsigned long)ub_thread_self();
 }
+
+static void
+ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
+       int ATTR_UNUSED(line))
+{
+       if((mode&CRYPTO_LOCK)) {
+               lock_basic_lock(&ub_openssl_locks[type]);
+       } else {
+               lock_basic_unlock(&ub_openssl_locks[type]);
+       }
+}
+#endif /* OPENSSL_THREADS */
+
+int ub_openssl_lock_init(void)
+{
+#if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+       int i;
+       ub_openssl_locks = (lock_basic_t*)malloc(
+               sizeof(lock_basic_t)*CRYPTO_num_locks());
+       if(!ub_openssl_locks)
+               return 0;
+       for(i=0; i<CRYPTO_num_locks(); i++) {
+               lock_basic_init(&ub_openssl_locks[i]);
+       }
+       CRYPTO_set_id_callback(&ub_crypto_id_cb);
+       CRYPTO_set_locking_callback(&ub_crypto_lock_cb);
+#endif /* OPENSSL_THREADS */
+       return 1;
+}
+
+void ub_openssl_lock_delete(void)
+{
+#if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+       int i;
+       if(!ub_openssl_locks)
+               return;
+       for(i=0; i<CRYPTO_num_locks(); i++) {
+               lock_basic_destroy(&ub_openssl_locks[i]);
+       }
+#endif /* OPENSSL_THREADS */
+}
+
index f8cad67a4b5ac5b20061dfc7e706492af0475996..518383ada8e774ace3de8ae3c00b094bfa27265c 100644 (file)
@@ -374,4 +374,15 @@ void* incoming_ssl_fd(void* sslctx, int fd);
  */
 void* outgoing_ssl_fd(void* sslctx, int fd);
 
+/**
+ * Initialize openssl locking for thread safety
+ * @return false on failure (alloc failure).
+ */
+int ub_openssl_lock_init(void);
+
+/**
+ * De-init the allocated openssl locks
+ */
+void ub_openssl_lock_delete(void);
+
 #endif /* NET_HELP_H */
index 5b869765cc324d1441e4e52acdf4706ccfeed586..3c1c69d7e1b837861550466510b04f7ced0ce8ea 100644 (file)
 #include "util/log.h"
 #include "util/net_help.h"
 #include "util/fptr_wlist.h"
+#ifdef HAVE_OPENSSL_SSL_H
 #include <openssl/ssl.h>
+#endif
+#ifdef HAVE_OPENSSL_ERR_H
 #include <openssl/err.h>
+#endif
 
 /* -------- Start of local definitions -------- */
 /** if CMSG_ALIGN is not defined on this platform, a workaround */
@@ -846,9 +850,11 @@ reclaim_tcp_handler(struct comm_point* c)
 {
        log_assert(c->type == comm_tcp);
        if(c->ssl) {
+#ifdef HAVE_SSL
                SSL_shutdown(c->ssl);
                SSL_free(c->ssl);
                c->ssl = NULL;
+#endif
        }
        comm_point_close(c);
        if(c->tcp_parent) {
@@ -893,6 +899,7 @@ tcp_callback_reader(struct comm_point* c)
 }
 
 /** continue ssl handshake */
+#ifdef HAVE_SSL
 static int
 ssl_handshake(struct comm_point* c)
 {
@@ -955,11 +962,13 @@ ssl_handshake(struct comm_point* c)
        c->ssl_shake_state = comm_ssl_shake_none;
        return 1;
 }
+#endif /* HAVE_SSL */
 
 /** ssl read callback on TCP */
 static int
 ssl_handle_read(struct comm_point* c)
 {
+#ifdef HAVE_SSL
        int r;
        if(c->ssl_shake_state != comm_ssl_shake_none) {
                if(!ssl_handshake(c))
@@ -1036,12 +1045,17 @@ ssl_handle_read(struct comm_point* c)
                tcp_callback_reader(c);
        }
        return 1;
+#else
+       (void)c;
+       return 0;
+#endif /* HAVE_SSL */
 }
 
 /** ssl write callback on TCP */
 static int
 ssl_handle_write(struct comm_point* c)
 {
+#ifdef HAVE_SSL
        int r;
        if(c->ssl_shake_state != comm_ssl_shake_none) {
                if(!ssl_handshake(c))
@@ -1115,6 +1129,10 @@ ssl_handle_write(struct comm_point* c)
                tcp_callback_writer(c);
        }
        return 1;
+#else
+       (void)c;
+       return 0;
+#endif /* HAVE_SSL */
 }
 
 /** handle ssl tcp connection with dns contents */
@@ -1844,8 +1862,10 @@ comm_point_delete(struct comm_point* c)
        if(!c) 
                return;
        if(c->type == comm_tcp && c->ssl) {
+#ifdef HAVE_SSL
                SSL_shutdown(c->ssl);
                SSL_free(c->ssl);
+#endif
        }
        comm_point_close(c);
        if(c->tcp_handlers) {
index 72c58a2b4df5d90fcd53d44c9581fea1b71421ad..5b61aef7f3bdbedfb94bd7d53fa37e4cd1f48f7e 100644 (file)
 #include "config.h"
 #include "util/random.h"
 #include "util/log.h"
+#ifdef HAVE_SSL
 #include <openssl/rand.h>
 #include <openssl/rc4.h>
 #include <openssl/err.h>
+#elif defined(HAVE_NSS)
+#include <nspr4/prerror.h>
+#include <nss3/secport.h>
+#include <nss3/pk11pub.h>
+#endif
 
+/** 
+ * Max random value.  Similar to RAND_MAX, but more portable
+ * (mingw uses only 15 bits random).
+ */
+#define MAX_VALUE 0x7fffffff
+
+#ifdef HAVE_SSL
 /**
  * Struct with per-thread random state.
  * Keeps SSL types away from the header file.
@@ -78,12 +91,6 @@ struct ub_randstate {
 /** Size of key to use (must be multiple of 8) */
 #define SEED_SIZE 24
 
-/** 
- * Max random value.  Similar to RAND_MAX, but more portable
- * (mingw uses only 15 bits random).
- */
-#define MAX_VALUE 0x7fffffff
-
 /** Number of bytes to reseed after */
 #define REKEY_BYTES    (1 << 24)
 
@@ -140,6 +147,16 @@ ub_arc4random_stir(struct ub_randstate* s, struct ub_randstate* from)
                        return;
                }
        }
+#ifdef HAVE_FIPS_MODE
+       if(FIPS_mode()) {
+               /* RC4 is not allowed, get some trustworthy randomness */
+               /* double certainty here, this routine should not be
+                * called in FIPS_mode */
+               memset(rand_buf, 0, sizeof(rand_buf));
+               s->rc4_ready = REKEY_BYTES;
+               return;
+       }
+#endif /* FIPS_MODE */
        RC4_set_key(&s->rc4, SEED_SIZE, (unsigned char*)rand_buf);
 
        /*
@@ -164,6 +181,9 @@ ub_initstate(unsigned int seed, struct ub_randstate* from)
                return NULL;
        }
        ub_systemseed(seed);
+#ifdef HAVE_FIPS_MODE
+       if(!FIPS_mode())
+#endif
        ub_arc4random_stir(s, from);
        return s;
 }
@@ -172,6 +192,20 @@ long int
 ub_random(struct ub_randstate* s)
 {
        unsigned int r = 0;
+#ifdef HAVE_FIPS_MODE
+       if(FIPS_mode()) {
+               /* RC4 is not allowed, get some trustworthy randomness */
+               /* we use pseudo bytes: it tries to return secure randomness
+                * but returns 'something' if that fails.  We need something
+                * else if it fails, because we cannot block here */
+               if(RAND_pseudo_bytes((unsigned char*)&r, (int)sizeof(r))
+                       == -1) {
+                       log_err("FIPSmode, no arc4random but RAND failed "
+                               "(error %ld)", ERR_get_error());
+               }
+               return (long int)((r) % (((unsigned)MAX_VALUE + 1)));
+       }
+#endif /* FIPS_MODE */
        if (s->rc4_ready <= 0) {
                ub_arc4random_stir(s, NULL);
        }
@@ -182,6 +216,42 @@ ub_random(struct ub_randstate* s)
        return (long int)((r) % (((unsigned)MAX_VALUE + 1)));
 }
 
+#elif defined(HAVE_NSS)
+
+/* not much to remember for NSS since we use its pk11_random, placeholder */
+struct ub_randstate {
+       int ready;
+};
+
+void ub_systemseed(unsigned int ATTR_UNUSED(seed))
+{
+}
+
+struct ub_randstate* ub_initstate(unsigned int ATTR_UNUSED(seed), 
+       struct ub_randstate* ATTR_UNUSED(from))
+{
+       struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));
+       if(!s) {
+               log_err("malloc failure in random init");
+               return NULL;
+       }
+       return s;
+}
+
+long int ub_random(struct ub_randstate* ATTR_UNUSED(state))
+{
+       long int x;
+       /* random 31 bit value. */
+       SECStatus s = PK11_GenerateRandom((unsigned char*)&x, (int)sizeof(x));
+       if(s != SECSuccess) {
+               log_err("PK11_GenerateRandom error: %s",
+                       PORT_ErrorToString(PORT_GetError()));
+       }
+       return x & MAX_VALUE;
+}
+
+#endif /* HAVE_SSL or HAVE_NSS */
+
 long int
 ub_random_max(struct ub_randstate* state, long int x)
 {
index df1d437e4791775225ace7d7047ed3cfd3f8f706..c888b0864f06c3d83356b6a20ee88b15f2d979a7 100644 (file)
@@ -41,7 +41,6 @@
  */
 #include "config.h"
 #include "util/rtt.h"
-#include "util/log.h"
 
 /** calculate RTO from rtt information */
 static int
index 67294e056c4b5c2fab364645b930e5f43cb65367..28c51d79d16d22e05b881e13a42a6ccad72ba291 100644 (file)
@@ -360,6 +360,7 @@ int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len,
                }
                d += r;
        }
+       log_assert(*len < 65536*2);
        *buf = (uint8_t*)malloc(*len);
        if(!*buf) {
                log_err("tube read out of memory");
index 4e59fdf3b07b964b6c77d27f376381c6cbcbd2b1..149f3f889b1ec4749400d13c010d8dfd34bf412f 100644 (file)
@@ -1851,6 +1851,7 @@ static void
 autr_tp_remove(struct module_env* env, struct trust_anchor* tp,
        struct ub_packed_rrset_key* dnskey_rrset)
 {
+       struct trust_anchor* del_tp;
        struct trust_anchor key;
        struct autr_point_data pd;
        time_t mold, mnew;
@@ -1876,19 +1877,24 @@ autr_tp_remove(struct module_env* env, struct trust_anchor* tp,
 
        /* take from tree. It could be deleted by someone else,hence (void). */
        lock_basic_lock(&env->anchors->lock);
-       (void)rbtree_delete(env->anchors->tree, &key);
+       del_tp = (struct trust_anchor*)rbtree_delete(env->anchors->tree, &key);
        mold = wait_probe_time(env->anchors);
        (void)rbtree_delete(&env->anchors->autr->probe, &key);
        mnew = wait_probe_time(env->anchors);
        anchors_init_parents_locked(env->anchors);
        lock_basic_unlock(&env->anchors->lock);
 
-       /* save on disk */
-       tp->autr->next_probe_time = 0; /* no more probing for it */
-       autr_write_file(env, tp);
+       /* if !del_tp then the trust point is no longer present in the tree,
+        * it was deleted by someone else, who will write the zonefile and
+        * clean up the structure */
+       if(del_tp) {
+               /* save on disk */
+               del_tp->autr->next_probe_time = 0; /* no more probing for it */
+               autr_write_file(env, del_tp);
 
-       /* delete */
-       autr_point_delete(tp);
+               /* delete */
+               autr_point_delete(del_tp);
+       }
        if(mold != mnew) {
                reset_worker_timer(env);
        }
index 200bf5d97be610edcaeba285a6a4c56c1bf8f654..fa69df52d6807bf5e90cf3e7d435af43c197bddb 100644 (file)
@@ -1246,6 +1246,7 @@ anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
        lock_basic_lock(&ta->lock);
        /* see if its really an insecure point */
        if(ta->keylist || ta->autr || ta->numDS || ta->numDNSKEY) {
+               lock_basic_unlock(&anchors->lock);
                lock_basic_unlock(&ta->lock);
                /* its not an insecure point, do not remove it */
                return;
index 60434db0338585713c1b80e670c9f72a2f63f479..eec2eb1b6bb75ddc5e494f2208a0a03edceb29bf 100644 (file)
@@ -44,6 +44,9 @@
 #include "config.h"
 #ifdef HAVE_OPENSSL_SSL_H
 #include "openssl/ssl.h"
+#define NSEC3_SHA_LEN SHA_DIGEST_LENGTH
+#else
+#define NSEC3_SHA_LEN 20
 #endif
 #include "validator/val_neg.h"
 #include "validator/val_nsec.h"
@@ -1174,7 +1177,7 @@ neg_find_nsec3_ce(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
                int qlabs, ldns_buffer* buf, uint8_t* hashnc, size_t* nclen)
 {
        struct val_neg_data* data;
-       uint8_t hashce[SHA_DIGEST_LENGTH];
+       uint8_t hashce[NSEC3_SHA_LEN];
        uint8_t b32[257];
        size_t celen, b32len;
 
@@ -1259,7 +1262,7 @@ neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
 {
        struct dns_msg* msg;
        struct val_neg_data* data;
-       uint8_t hashnc[SHA_DIGEST_LENGTH];
+       uint8_t hashnc[NSEC3_SHA_LEN];
        size_t nclen;
        struct ub_packed_rrset_key* ce_rrset, *nc_rrset;
        struct nsec3_cached_hash c;
index a18e3ab31d068ea7ce7518c12a652c4adca542e0..2a2cfcf9b2d5c1a14831b49277d6d53e70b7c978 100644 (file)
@@ -45,6 +45,9 @@
 #ifdef HAVE_OPENSSL_SSL_H
 #include "openssl/ssl.h"
 #endif
+#ifdef HAVE_NSS
+#include <nss3/sechash.h>
+#endif
 #include "validator/val_nsec3.h"
 #include "validator/validator.h"
 #include "validator/val_kentry.h"
@@ -541,26 +544,43 @@ nsec3_get_hashed(ldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo,
        ldns_buffer_write(buf, salt, saltlen);
        ldns_buffer_flip(buf);
        switch(algo) {
-#ifdef HAVE_EVP_SHA1
+#if defined(HAVE_EVP_SHA1) || defined(HAVE_NSS)
                case NSEC3_HASH_SHA1:
+#ifdef HAVE_SSL
                        hash_len = SHA_DIGEST_LENGTH;
+#else
+                       hash_len = SHA1_LENGTH;
+#endif
                        if(hash_len > max)
                                return 0;
+#  ifdef HAVE_SSL
                        (void)SHA1((unsigned char*)ldns_buffer_begin(buf),
                                (unsigned long)ldns_buffer_limit(buf),
                                (unsigned char*)res);
+#  else
+                       (void)HASH_HashBuf(HASH_AlgSHA1, (unsigned char*)res,
+                               (unsigned char*)ldns_buffer_begin(buf),
+                               (unsigned long)ldns_buffer_limit(buf));
+#  endif
                        for(i=0; i<iter; i++) {
                                ldns_buffer_clear(buf);
                                ldns_buffer_write(buf, res, hash_len);
                                ldns_buffer_write(buf, salt, saltlen);
                                ldns_buffer_flip(buf);
+#  ifdef HAVE_SSL
                                (void)SHA1(
                                        (unsigned char*)ldns_buffer_begin(buf),
                                        (unsigned long)ldns_buffer_limit(buf),
                                        (unsigned char*)res);
+#  else
+                               (void)HASH_HashBuf(HASH_AlgSHA1,
+                                       (unsigned char*)res,
+                                       (unsigned char*)ldns_buffer_begin(buf),
+                                       (unsigned long)ldns_buffer_limit(buf));
+#  endif
                        }
                        break;
-#endif /* HAVE_EVP_SHA1 */
+#endif /* HAVE_EVP_SHA1 or NSS */
                default:
                        log_err("nsec3 hash of unknown algo %d", algo);
                        return 0;
@@ -586,28 +606,46 @@ nsec3_calc_hash(struct regional* region, ldns_buffer* buf,
        ldns_buffer_write(buf, salt, saltlen);
        ldns_buffer_flip(buf);
        switch(algo) {
-#ifdef HAVE_EVP_SHA1
+#if defined(HAVE_EVP_SHA1) || defined(HAVE_NSS)
                case NSEC3_HASH_SHA1:
+#ifdef HAVE_SSL
                        c->hash_len = SHA_DIGEST_LENGTH;
+#else
+                       c->hash_len = SHA1_LENGTH;
+#endif
                        c->hash = (uint8_t*)regional_alloc(region, 
                                c->hash_len);
                        if(!c->hash)
                                return 0;
+#  ifdef HAVE_SSL
                        (void)SHA1((unsigned char*)ldns_buffer_begin(buf),
                                (unsigned long)ldns_buffer_limit(buf),
                                (unsigned char*)c->hash);
+#  else
+                       (void)HASH_HashBuf(HASH_AlgSHA1,
+                               (unsigned char*)c->hash,
+                               (unsigned char*)ldns_buffer_begin(buf),
+                               (unsigned long)ldns_buffer_limit(buf));
+#  endif
                        for(i=0; i<iter; i++) {
                                ldns_buffer_clear(buf);
                                ldns_buffer_write(buf, c->hash, c->hash_len);
                                ldns_buffer_write(buf, salt, saltlen);
                                ldns_buffer_flip(buf);
+#  ifdef HAVE_SSL
                                (void)SHA1(
                                        (unsigned char*)ldns_buffer_begin(buf),
                                        (unsigned long)ldns_buffer_limit(buf),
                                        (unsigned char*)c->hash);
+#  else
+                               (void)HASH_HashBuf(HASH_AlgSHA1,
+                                       (unsigned char*)c->hash,
+                                       (unsigned char*)ldns_buffer_begin(buf),
+                                       (unsigned long)ldns_buffer_limit(buf));
+#  endif
                        }
                        break;
-#endif /* HAVE_EVP_SHA1 */
+#endif /* HAVE_EVP_SHA1 or NSS */
                default:
                        log_err("nsec3 hash of unknown algo %d", algo);
                        return -1;
@@ -1133,8 +1171,8 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
                 * If not type DS: matching nsec3 must not be a delegation.
                 */
                if(qinfo->qtype == LDNS_RR_TYPE_DS && qinfo->qname_len != 1 
-                       && nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA &&
-                       !dname_is_root(qinfo->qname))) {
+                       && nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA) &&
+                       !dname_is_root(qinfo->qname)) {
                        verbose(VERB_ALGO, "proveNodata: apex NSEC3 "
                                "abused for no DS proof, bogus");
                        return sec_status_bogus;
diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c
new file mode 100644 (file)
index 0000000..6763997
--- /dev/null
@@ -0,0 +1,1068 @@
+/*
+ * validator/val_secalgo.c - validator security algorithm functions.
+ *
+ * Copyright (c) 2012, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains helper functions for the validator module.
+ * These functions take raw data buffers, formatted for crypto verification,
+ * and do the library calls (for the crypto library in use).
+ */
+#include "config.h"
+#include <ldns/ldns.h>
+#include "validator/val_secalgo.h"
+#include "util/data/packed_rrset.h"
+#include "util/log.h"
+
+#if !defined(HAVE_SSL) && !defined(HAVE_NSS)
+#error "Need crypto library to do digital signature cryptography"
+#endif
+
+/* OpenSSL implementation */
+#ifdef HAVE_SSL
+#ifdef HAVE_OPENSSL_ERR_H
+#include <openssl/err.h>
+#endif
+
+#ifdef HAVE_OPENSSL_RAND_H
+#include <openssl/rand.h>
+#endif
+
+#ifdef HAVE_OPENSSL_CONF_H
+#include <openssl/conf.h>
+#endif
+
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
+
+/**
+ * Return size of DS digest according to its hash algorithm.
+ * @param algo: DS digest algo.
+ * @return size in bytes of digest, or 0 if not supported. 
+ */
+size_t
+ds_digest_size_supported(int algo)
+{
+       switch(algo) {
+#ifdef HAVE_EVP_SHA1
+               case LDNS_SHA1:
+                       return SHA_DIGEST_LENGTH;
+#endif
+#ifdef HAVE_EVP_SHA256
+               case LDNS_SHA256:
+                       return SHA256_DIGEST_LENGTH;
+#endif
+#ifdef USE_GOST
+               case LDNS_HASH_GOST:
+                       if(EVP_get_digestbyname("md_gost94"))
+                               return 32;
+                       else    return 0;
+#endif
+#ifdef USE_ECDSA
+               case LDNS_SHA384:
+                       return SHA384_DIGEST_LENGTH;
+#endif
+               default: break;
+       }
+       return 0;
+}
+
+#ifdef USE_GOST
+/** Perform GOST hash */
+static int
+do_gost94(unsigned char* data, size_t len, unsigned char* dest)
+{
+       const EVP_MD* md = EVP_get_digestbyname("md_gost94");
+       if(!md) 
+               return 0;
+       return ldns_digest_evp(data, (unsigned int)len, dest, md);
+}
+#endif
+
+int
+secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
+       unsigned char* res)
+{
+       switch(algo) {
+#ifdef HAVE_EVP_SHA1
+               case LDNS_SHA1:
+                       (void)SHA1(buf, len, res);
+                       return 1;
+#endif
+#ifdef HAVE_EVP_SHA256
+               case LDNS_SHA256:
+                       (void)SHA256(buf, len, res);
+                       return 1;
+#endif
+#ifdef USE_GOST
+               case LDNS_HASH_GOST:
+                       if(do_gost94(buf, len, res))
+                               return 1;
+                       break;
+#endif
+#ifdef USE_ECDSA
+               case LDNS_SHA384:
+                       (void)SHA384(buf, len, res);
+                       return 1;
+#endif
+               default: 
+                       verbose(VERB_QUERY, "unknown DS digest algorithm %d", 
+                               algo);
+                       break;
+       }
+       return 0;
+}
+
+/** return true if DNSKEY algorithm id is supported */
+int
+dnskey_algo_id_is_supported(int id)
+{
+       switch(id) {
+       case LDNS_RSAMD5:
+               /* RFC 6725 deprecates RSAMD5 */
+               return 0;
+       case LDNS_DSA:
+       case LDNS_DSA_NSEC3:
+       case LDNS_RSASHA1:
+       case LDNS_RSASHA1_NSEC3:
+#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
+       case LDNS_RSASHA256:
+#endif
+#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
+       case LDNS_RSASHA512:
+#endif
+#ifdef USE_ECDSA
+       case LDNS_ECDSAP256SHA256:
+       case LDNS_ECDSAP384SHA384:
+#endif
+               return 1;
+#ifdef USE_GOST
+       case LDNS_ECC_GOST:
+               /* we support GOST if it can be loaded */
+               return ldns_key_EVP_load_gost_id();
+#endif
+       default:
+               return 0;
+       }
+}
+
+/**
+ * Output a libcrypto openssl error to the logfile.
+ * @param str: string to add to it.
+ * @param e: the error to output, error number from ERR_get_error().
+ */
+static void
+log_crypto_error(const char* str, unsigned long e)
+{
+       char buf[128];
+       /* or use ERR_error_string if ERR_error_string_n is not avail TODO */
+       ERR_error_string_n(e, buf, sizeof(buf));
+       /* buf now contains */
+       /* error:[error code]:[library name]:[function name]:[reason string] */
+       log_err("%s crypto %s", str, buf);
+}
+
+/**
+ * Setup DSA key digest in DER encoding ... 
+ * @param sig: input is signature output alloced ptr (unless failure).
+ *     caller must free alloced ptr if this routine returns true.
+ * @param len: input is initial siglen, output is output len.
+ * @return false on failure.
+ */
+static int
+setup_dsa_sig(unsigned char** sig, unsigned int* len)
+{
+       unsigned char* orig = *sig;
+       unsigned int origlen = *len;
+       int newlen;
+       BIGNUM *R, *S;
+       DSA_SIG *dsasig;
+
+       /* extract the R and S field from the sig buffer */
+       if(origlen < 1 + 2*SHA_DIGEST_LENGTH)
+               return 0;
+       R = BN_new();
+       if(!R) return 0;
+       (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R);
+       S = BN_new();
+       if(!S) return 0;
+       (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S);
+       dsasig = DSA_SIG_new();
+       if(!dsasig) return 0;
+
+       dsasig->r = R;
+       dsasig->s = S;
+       *sig = NULL;
+       newlen = i2d_DSA_SIG(dsasig, sig);
+       if(newlen < 0) {
+               DSA_SIG_free(dsasig);
+               free(*sig);
+               return 0;
+       }
+       *len = (unsigned int)newlen;
+       DSA_SIG_free(dsasig);
+       return 1;
+}
+
+#ifdef USE_ECDSA
+/**
+ * Setup the ECDSA signature in its encoding that the library wants.
+ * Converts from plain numbers to ASN formatted.
+ * @param sig: input is signature, output alloced ptr (unless failure).
+ *     caller must free alloced ptr if this routine returns true.
+ * @param len: input is initial siglen, output is output len.
+ * @return false on failure.
+ */
+static int
+setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
+{
+       ECDSA_SIG* ecdsa_sig;
+       int newlen;
+       int bnsize = (int)((*len)/2);
+       /* if too short or not even length, fails */
+       if(*len < 16 || bnsize*2 != (int)*len)
+               return 0;
+       /* use the raw data to parse two evenly long BIGNUMs, "r | s". */
+       ecdsa_sig = ECDSA_SIG_new();
+       if(!ecdsa_sig) return 0;
+       ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r);
+       ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s);
+       if(!ecdsa_sig->r || !ecdsa_sig->s) {
+               ECDSA_SIG_free(ecdsa_sig);
+               return 0;
+       }
+
+       /* spool it into ASN format */
+       *sig = NULL;
+       newlen = i2d_ECDSA_SIG(ecdsa_sig, sig);
+       if(newlen <= 0) {
+               ECDSA_SIG_free(ecdsa_sig);
+               free(*sig);
+               return 0;
+       }
+       *len = (unsigned int)newlen;
+       ECDSA_SIG_free(ecdsa_sig);
+       return 1;
+}
+#endif /* USE_ECDSA */
+
+/**
+ * Setup key and digest for verification. Adjust sig if necessary.
+ *
+ * @param algo: key algorithm
+ * @param evp_key: EVP PKEY public key to create.
+ * @param digest_type: digest type to use
+ * @param key: key to setup for.
+ * @param keylen: length of key.
+ * @return false on failure.
+ */
+static int
+setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, 
+       unsigned char* key, size_t keylen)
+{
+       DSA* dsa;
+       RSA* rsa;
+
+       switch(algo) {
+               case LDNS_DSA:
+               case LDNS_DSA_NSEC3:
+                       *evp_key = EVP_PKEY_new();
+                       if(!*evp_key) {
+                               log_err("verify: malloc failure in crypto");
+                               return 0;
+                       }
+                       dsa = ldns_key_buf2dsa_raw(key, keylen);
+                       if(!dsa) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "ldns_key_buf2dsa_raw failed");
+                               return 0;
+                       }
+                       if(EVP_PKEY_assign_DSA(*evp_key, dsa) == 0) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "EVP_PKEY_assign_DSA failed");
+                               return 0;
+                       }
+                       *digest_type = EVP_dss1();
+
+                       break;
+               case LDNS_RSASHA1:
+               case LDNS_RSASHA1_NSEC3:
+#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
+               case LDNS_RSASHA256:
+#endif
+#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
+               case LDNS_RSASHA512:
+#endif
+                       *evp_key = EVP_PKEY_new();
+                       if(!*evp_key) {
+                               log_err("verify: malloc failure in crypto");
+                               return 0;
+                       }
+                       rsa = ldns_key_buf2rsa_raw(key, keylen);
+                       if(!rsa) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "ldns_key_buf2rsa_raw SHA failed");
+                               return 0;
+                       }
+                       if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "EVP_PKEY_assign_RSA SHA failed");
+                               return 0;
+                       }
+
+                       /* select SHA version */
+#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
+                       if(algo == LDNS_RSASHA256)
+                               *digest_type = EVP_sha256();
+                       else
+#endif
+#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
+                               if(algo == LDNS_RSASHA512)
+                               *digest_type = EVP_sha512();
+                       else
+#endif
+                               *digest_type = EVP_sha1();
+
+                       break;
+               case LDNS_RSAMD5:
+                       *evp_key = EVP_PKEY_new();
+                       if(!*evp_key) {
+                               log_err("verify: malloc failure in crypto");
+                               return 0;
+                       }
+                       rsa = ldns_key_buf2rsa_raw(key, keylen);
+                       if(!rsa) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "ldns_key_buf2rsa_raw MD5 failed");
+                               return 0;
+                       }
+                       if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "EVP_PKEY_assign_RSA MD5 failed");
+                               return 0;
+                       }
+                       *digest_type = EVP_md5();
+
+                       break;
+#ifdef USE_GOST
+               case LDNS_ECC_GOST:
+                       *evp_key = ldns_gost2pkey_raw(key, keylen);
+                       if(!*evp_key) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "ldns_gost2pkey_raw failed");
+                               return 0;
+                       }
+                       *digest_type = EVP_get_digestbyname("md_gost94");
+                       if(!*digest_type) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "EVP_getdigest md_gost94 failed");
+                               return 0;
+                       }
+                       break;
+#endif
+#ifdef USE_ECDSA
+               case LDNS_ECDSAP256SHA256:
+                       *evp_key = ldns_ecdsa2pkey_raw(key, keylen,
+                               LDNS_ECDSAP256SHA256);
+                       if(!*evp_key) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "ldns_ecdsa2pkey_raw failed");
+                               return 0;
+                       }
+#ifdef USE_ECDSA_EVP_WORKAROUND
+                       /* openssl before 1.0.0 fixes RSA with the SHA256
+                        * hash in EVP.  We create one for ecdsa_sha256 */
+                       {
+                               static int md_ecdsa_256_done = 0;
+                               static EVP_MD md;
+                               if(!md_ecdsa_256_done) {
+                                       EVP_MD m = *EVP_sha256();
+                                       md_ecdsa_256_done = 1;
+                                       m.required_pkey_type[0] = (*evp_key)->type;
+                                       m.verify = (void*)ECDSA_verify;
+                                       md = m;
+                               }
+                               *digest_type = &md;
+                       }
+#else
+                       *digest_type = EVP_sha256();
+#endif
+                       break;
+               case LDNS_ECDSAP384SHA384:
+                       *evp_key = ldns_ecdsa2pkey_raw(key, keylen,
+                               LDNS_ECDSAP384SHA384);
+                       if(!*evp_key) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "ldns_ecdsa2pkey_raw failed");
+                               return 0;
+                       }
+#ifdef USE_ECDSA_EVP_WORKAROUND
+                       /* openssl before 1.0.0 fixes RSA with the SHA384
+                        * hash in EVP.  We create one for ecdsa_sha384 */
+                       {
+                               static int md_ecdsa_384_done = 0;
+                               static EVP_MD md;
+                               if(!md_ecdsa_384_done) {
+                                       EVP_MD m = *EVP_sha384();
+                                       md_ecdsa_384_done = 1;
+                                       m.required_pkey_type[0] = (*evp_key)->type;
+                                       m.verify = (void*)ECDSA_verify;
+                                       md = m;
+                               }
+                               *digest_type = &md;
+                       }
+#else
+                       *digest_type = EVP_sha384();
+#endif
+                       break;
+#endif /* USE_ECDSA */
+               default:
+                       verbose(VERB_QUERY, "verify: unknown algorithm %d", 
+                               algo);
+                       return 0;
+       }
+       return 1;
+}
+
+/**
+ * Check a canonical sig+rrset and signature against a dnskey
+ * @param buf: buffer with data to verify, the first rrsig part and the
+ *     canonicalized rrset.
+ * @param algo: DNSKEY algorithm.
+ * @param sigblock: signature rdata field from RRSIG
+ * @param sigblock_len: length of sigblock data.
+ * @param key: public key data from DNSKEY RR.
+ * @param keylen: length of keydata.
+ * @param reason: bogus reason in more detail.
+ * @return secure if verification succeeded, bogus on crypto failure,
+ *     unchecked on format errors and alloc failures.
+ */
+enum sec_status
+verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, 
+       unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
+       char** reason)
+{
+       const EVP_MD *digest_type;
+       EVP_MD_CTX ctx;
+       int res, dofree = 0;
+       EVP_PKEY *evp_key = NULL;
+       
+       if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
+               verbose(VERB_QUERY, "verify: failed to setup key");
+               *reason = "use of key for crypto failed";
+               EVP_PKEY_free(evp_key);
+               return sec_status_bogus;
+       }
+       /* if it is a DSA signature in bind format, convert to DER format */
+       if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && 
+               sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
+               if(!setup_dsa_sig(&sigblock, &sigblock_len)) {
+                       verbose(VERB_QUERY, "verify: failed to setup DSA sig");
+                       *reason = "use of key for DSA crypto failed";
+                       EVP_PKEY_free(evp_key);
+                       return sec_status_bogus;
+               }
+               dofree = 1;
+       }
+#ifdef USE_ECDSA
+       else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
+               /* EVP uses ASN prefix on sig, which is not in the wire data */
+               if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
+                       verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
+                       *reason = "use of signature for ECDSA crypto failed";
+                       EVP_PKEY_free(evp_key);
+                       return sec_status_bogus;
+               }
+               dofree = 1;
+       }
+#endif /* USE_ECDSA */
+
+       /* do the signature cryptography work */
+       EVP_MD_CTX_init(&ctx);
+       if(EVP_VerifyInit(&ctx, digest_type) == 0) {
+               verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
+               EVP_PKEY_free(evp_key);
+               if(dofree) free(sigblock);
+               return sec_status_unchecked;
+       }
+       if(EVP_VerifyUpdate(&ctx, (unsigned char*)ldns_buffer_begin(buf), 
+               (unsigned int)ldns_buffer_limit(buf)) == 0) {
+               verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed");
+               EVP_PKEY_free(evp_key);
+               if(dofree) free(sigblock);
+               return sec_status_unchecked;
+       }
+
+       res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
+       if(EVP_MD_CTX_cleanup(&ctx) == 0) {
+               verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");
+               EVP_PKEY_free(evp_key);
+               if(dofree) free(sigblock);
+               return sec_status_unchecked;
+       }
+       EVP_PKEY_free(evp_key);
+
+       if(dofree)
+               free(sigblock);
+
+       if(res == 1) {
+               return sec_status_secure;
+       } else if(res == 0) {
+               verbose(VERB_QUERY, "verify: signature mismatch");
+               *reason = "signature crypto failed";
+               return sec_status_bogus;
+       }
+
+       log_crypto_error("verify:", ERR_get_error());
+       return sec_status_unchecked;
+}
+
+/**************************************************/
+#elif defined(HAVE_NSS)
+/* libnss implementation */
+#include <nss3/sechash.h>
+#include <nss3/pk11pub.h>
+#include <nss3/keyhi.h>
+#include <nss3/secerr.h>
+#include <nss3/cryptohi.h>
+#include <nspr4/prerror.h>
+
+size_t
+ds_digest_size_supported(int algo)
+{
+       /* uses libNSS */
+       switch(algo) {
+               case LDNS_SHA1:
+                       return SHA1_LENGTH;
+#ifdef USE_SHA2
+               case LDNS_SHA256:
+                       return SHA256_LENGTH;
+#endif
+#ifdef USE_ECDSA
+               case LDNS_SHA384:
+                       return SHA384_LENGTH;
+#endif
+               /* GOST not supported in NSS */
+               case LDNS_HASH_GOST:
+               default: break;
+       }
+       return 0;
+}
+
+int
+secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
+       unsigned char* res)
+{
+       /* uses libNSS */
+       switch(algo) {
+               case LDNS_SHA1:
+                       return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
+                               == SECSuccess;
+#if defined(USE_SHA2)
+               case LDNS_SHA256:
+                       return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
+                               == SECSuccess;
+#endif
+#ifdef USE_ECDSA
+               case LDNS_SHA384:
+                       return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
+                               == SECSuccess;
+#endif
+               case LDNS_HASH_GOST:
+               default: 
+                       verbose(VERB_QUERY, "unknown DS digest algorithm %d", 
+                               algo);
+                       break;
+       }
+       return 0;
+}
+
+int
+dnskey_algo_id_is_supported(int id)
+{
+       /* uses libNSS */
+       switch(id) {
+       case LDNS_RSAMD5:
+               /* RFC 6725 deprecates RSAMD5 */
+               return 0;
+       case LDNS_DSA:
+       case LDNS_DSA_NSEC3:
+       case LDNS_RSASHA1:
+       case LDNS_RSASHA1_NSEC3:
+#ifdef USE_SHA2
+       case LDNS_RSASHA256:
+#endif
+#ifdef USE_SHA2
+       case LDNS_RSASHA512:
+#endif
+               return 1;
+#ifdef USE_ECDSA
+       case LDNS_ECDSAP256SHA256:
+       case LDNS_ECDSAP384SHA384:
+               return PK11_TokenExists(CKM_ECDSA);
+#endif
+       case LDNS_ECC_GOST:
+       default:
+               return 0;
+       }
+}
+
+/* return a new public key for NSS */
+static SECKEYPublicKey* nss_key_create(KeyType ktype)
+{
+       SECKEYPublicKey* key;
+       PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+       if(!arena) {
+               log_err("out of memory, PORT_NewArena failed");
+               return NULL;
+       }
+       key = PORT_ArenaZNew(arena, SECKEYPublicKey);
+       if(!key) {
+               log_err("out of memory, PORT_ArenaZNew failed");
+               PORT_FreeArena(arena, PR_FALSE);
+               return NULL;
+       }
+       key->arena = arena;
+       key->keyType = ktype;
+       key->pkcs11Slot = NULL;
+       key->pkcs11ID = CK_INVALID_HANDLE;
+       return key;
+}
+
+static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo)
+{
+       SECKEYPublicKey* pk;
+       SECItem pub = {siBuffer, NULL, 0};
+       SECItem params = {siBuffer, NULL, 0};
+       unsigned char param256[] = {
+               /* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256)
+                * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */
+               0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
+       };
+       unsigned char param384[] = {
+               /* OBJECTIDENTIFIER 1.3.132.0.34 (P-384)
+                * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */
+               0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
+       };
+       unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
+
+       /* check length, which uncompressed must be 2 bignums */
+       if(algo == LDNS_ECDSAP256SHA256) {
+               if(len != 2*256/8) return NULL;
+               /* ECCurve_X9_62_PRIME_256V1 */
+       } else if(algo == LDNS_ECDSAP384SHA384) {
+               if(len != 2*384/8) return NULL;
+               /* ECCurve_X9_62_PRIME_384R1 */
+       } else    return NULL;
+
+       buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */
+       memmove(buf+1, key, len);
+       pub.data = buf;
+       pub.len = len+1;
+       if(algo == LDNS_ECDSAP256SHA256) {
+               params.data = param256;
+               params.len = sizeof(param256);
+       } else {
+               params.data = param384;
+               params.len = sizeof(param384);
+       }
+
+       pk = nss_key_create(ecKey);
+       if(!pk)
+               return NULL;
+       pk->u.ec.size = (len/2)*8;
+       if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) {
+               SECKEY_DestroyPublicKey(pk);
+               return NULL;
+       }
+       if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, &params)) {
+               SECKEY_DestroyPublicKey(pk);
+               return NULL;
+       }
+
+       return pk;
+}
+
+static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len)
+{
+       SECKEYPublicKey* pk;
+       uint8_t T;
+       uint16_t length;
+       uint16_t offset;
+       SECItem Q = {siBuffer, NULL, 0};
+       SECItem P = {siBuffer, NULL, 0};
+       SECItem G = {siBuffer, NULL, 0};
+       SECItem Y = {siBuffer, NULL, 0};
+
+       if(len == 0)
+               return NULL;
+       T = (uint8_t)key[0];
+       length = (64 + T * 8);
+       offset = 1;
+
+       if (T > 8) {
+               return NULL;
+       }
+       if(len < (size_t)1 + SHA1_LENGTH + 3*length)
+               return NULL;
+
+       Q.data = key+offset;
+       Q.len = SHA1_LENGTH;
+       offset += SHA1_LENGTH;
+
+       P.data = key+offset;
+       P.len = length;
+       offset += length;
+
+       G.data = key+offset;
+       G.len = length;
+       offset += length;
+
+       Y.data = key+offset;
+       Y.len = length;
+       offset += length;
+
+       pk = nss_key_create(dsaKey);
+       if(!pk)
+               return NULL;
+       if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) {
+               SECKEY_DestroyPublicKey(pk);
+               return NULL;
+       }
+       if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) {
+               SECKEY_DestroyPublicKey(pk);
+               return NULL;
+       }
+       if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) {
+               SECKEY_DestroyPublicKey(pk);
+               return NULL;
+       }
+       if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) {
+               SECKEY_DestroyPublicKey(pk);
+               return NULL;
+       }
+       return pk;
+}
+
+static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len)
+{
+       SECKEYPublicKey* pk;
+       uint16_t exp;
+       uint16_t offset;
+       uint16_t int16;
+       SECItem modulus = {siBuffer, NULL, 0};
+       SECItem exponent = {siBuffer, NULL, 0};
+       if(len == 0)
+               return NULL;
+       if(key[0] == 0) {
+               if(len < 3)
+                       return NULL;
+               /* the exponent is too large so it's places further */
+               memmove(&int16, key+1, 2);
+               exp = ntohs(int16);
+               offset = 3;
+       } else {
+               exp = key[0];
+               offset = 1;
+       }
+
+       /* key length at least one */
+       if(len < (size_t)offset + exp + 1)
+               return NULL;
+       
+       exponent.data = key+offset;
+       exponent.len = exp;
+       offset += exp;
+       modulus.data = key+offset;
+       modulus.len = (len - offset);
+
+       pk = nss_key_create(rsaKey);
+       if(!pk)
+               return NULL;
+       if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) {
+               SECKEY_DestroyPublicKey(pk);
+               return NULL;
+       }
+       if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) {
+               SECKEY_DestroyPublicKey(pk);
+               return NULL;
+       }
+       return pk;
+}
+
+/**
+ * Setup key and digest for verification. Adjust sig if necessary.
+ *
+ * @param algo: key algorithm
+ * @param evp_key: EVP PKEY public key to create.
+ * @param digest_type: digest type to use
+ * @param key: key to setup for.
+ * @param keylen: length of key.
+ * @param prefix: if returned, the ASN prefix for the hashblob.
+ * @param prefixlen: length of the prefix.
+ * @return false on failure.
+ */
+static int
+nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
+       unsigned char* key, size_t keylen, unsigned char** prefix,
+       size_t* prefixlen)
+{
+       /* uses libNSS */
+
+       /* hash prefix for md5, RFC2537 */
+       unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a,
+       0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
+       /* hash prefix to prepend to hash output, from RFC3110 */
+       unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
+               0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
+       /* from RFC5702 */
+       unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
+       0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+       unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
+       0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
+       /* from RFC6234 */
+       /* for future RSASHA384 .. 
+       unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
+       0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
+       */
+
+       switch(algo) {
+               case LDNS_DSA:
+               case LDNS_DSA_NSEC3:
+                       *pubkey = nss_buf2dsa(key, keylen);
+                       if(!*pubkey) {
+                               log_err("verify: malloc failure in crypto");
+                               return 0;
+                       }
+                       *htype = HASH_AlgSHA1;
+                       /* no prefix for DSA verification */
+                       break;
+               case LDNS_RSASHA1:
+               case LDNS_RSASHA1_NSEC3:
+#ifdef USE_SHA2
+               case LDNS_RSASHA256:
+#endif
+#ifdef USE_SHA2
+               case LDNS_RSASHA512:
+#endif
+                       *pubkey = nss_buf2rsa(key, keylen);
+                       if(!*pubkey) {
+                               log_err("verify: malloc failure in crypto");
+                               return 0;
+                       }
+                       /* select SHA version */
+#ifdef USE_SHA2
+                       if(algo == LDNS_RSASHA256) {
+                               *htype = HASH_AlgSHA256;
+                               *prefix = p_sha256;
+                               *prefixlen = sizeof(p_sha256);
+                       } else
+#endif
+#ifdef USE_SHA2
+                               if(algo == LDNS_RSASHA512) {
+                               *htype = HASH_AlgSHA512;
+                               *prefix = p_sha512;
+                               *prefixlen = sizeof(p_sha512);
+                       } else
+#endif
+                       {
+                               *htype = HASH_AlgSHA1;
+                               *prefix = p_sha1;
+                               *prefixlen = sizeof(p_sha1);
+                       }
+
+                       break;
+               case LDNS_RSAMD5:
+                       *pubkey = nss_buf2rsa(key, keylen);
+                       if(!*pubkey) {
+                               log_err("verify: malloc failure in crypto");
+                               return 0;
+                       }
+                       *htype = HASH_AlgMD5;
+                       *prefix = p_md5;
+                       *prefixlen = sizeof(p_md5);
+
+                       break;
+#ifdef USE_ECDSA
+               case LDNS_ECDSAP256SHA256:
+                       *pubkey = nss_buf2ecdsa(key, keylen,
+                               LDNS_ECDSAP256SHA256);
+                       if(!*pubkey) {
+                               log_err("verify: malloc failure in crypto");
+                               return 0;
+                       }
+                       *htype = HASH_AlgSHA256;
+                       /* no prefix for DSA verification */
+                       break;
+               case LDNS_ECDSAP384SHA384:
+                       *pubkey = nss_buf2ecdsa(key, keylen,
+                               LDNS_ECDSAP384SHA384);
+                       if(!*pubkey) {
+                               log_err("verify: malloc failure in crypto");
+                               return 0;
+                       }
+                       *htype = HASH_AlgSHA384;
+                       /* no prefix for DSA verification */
+                       break;
+#endif /* USE_ECDSA */
+               case LDNS_ECC_GOST:
+               default:
+                       verbose(VERB_QUERY, "verify: unknown algorithm %d", 
+                               algo);
+                       return 0;
+       }
+       return 1;
+}
+
+/**
+ * Check a canonical sig+rrset and signature against a dnskey
+ * @param buf: buffer with data to verify, the first rrsig part and the
+ *     canonicalized rrset.
+ * @param algo: DNSKEY algorithm.
+ * @param sigblock: signature rdata field from RRSIG
+ * @param sigblock_len: length of sigblock data.
+ * @param key: public key data from DNSKEY RR.
+ * @param keylen: length of keydata.
+ * @param reason: bogus reason in more detail.
+ * @return secure if verification succeeded, bogus on crypto failure,
+ *     unchecked on format errors and alloc failures.
+ */
+enum sec_status
+verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, 
+       unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
+       char** reason)
+{
+       /* uses libNSS */
+       /* large enough for the different hashes */
+       unsigned char hash[HASH_LENGTH_MAX];
+       unsigned char hash2[HASH_LENGTH_MAX*2];
+       HASH_HashType htype = 0;
+       SECKEYPublicKey* pubkey = NULL;
+       SECItem secsig = {siBuffer, sigblock, sigblock_len};
+       SECItem sechash = {siBuffer, hash, 0};
+       SECStatus res;
+       unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */
+       size_t prefixlen = 0;
+       int err;
+
+       if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen,
+               &prefix, &prefixlen)) {
+               verbose(VERB_QUERY, "verify: failed to setup key");
+               *reason = "use of key for crypto failed";
+               SECKEY_DestroyPublicKey(pubkey);
+               return sec_status_bogus;
+       }
+
+       /* need to convert DSA, ECDSA signatures? */
+       if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
+               if(sigblock_len == 1+2*SHA1_LENGTH) {
+                       secsig.data ++;
+                       secsig.len --;
+               } else {
+                       SECItem* p = DSAU_DecodeDerSig(&secsig);
+                       if(!p) {
+                               verbose(VERB_QUERY, "verify: failed DER decode");
+                               *reason = "signature DER decode failed";
+                               SECKEY_DestroyPublicKey(pubkey);
+                               return sec_status_bogus;
+                       }
+                       if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) {
+                               log_err("alloc failure in DER decode");
+                               SECKEY_DestroyPublicKey(pubkey);
+                               SECITEM_FreeItem(p, PR_TRUE);
+                               return sec_status_unchecked;
+                       }
+                       SECITEM_FreeItem(p, PR_TRUE);
+               }
+       }
+
+       /* do the signature cryptography work */
+       /* hash the data */
+       sechash.len = HASH_ResultLen(htype);
+       if(sechash.len > sizeof(hash)) {
+               verbose(VERB_QUERY, "verify: hash too large for buffer");
+               SECKEY_DestroyPublicKey(pubkey);
+               return sec_status_unchecked;
+       }
+       if(HASH_HashBuf(htype, hash, (unsigned char*)ldns_buffer_begin(buf),
+               (unsigned int)ldns_buffer_limit(buf)) != SECSuccess) {
+               verbose(VERB_QUERY, "verify: HASH_HashBuf failed");
+               SECKEY_DestroyPublicKey(pubkey);
+               return sec_status_unchecked;
+       }
+       if(prefix) {
+               int hashlen = sechash.len;
+               if(prefixlen+hashlen > sizeof(hash2)) {
+                       verbose(VERB_QUERY, "verify: hashprefix too large");
+                       SECKEY_DestroyPublicKey(pubkey);
+                       return sec_status_unchecked;
+               }
+               sechash.data = hash2;
+               sechash.len = prefixlen+hashlen;
+               memcpy(sechash.data, prefix, prefixlen);
+               memmove(sechash.data+prefixlen, hash, hashlen);
+       }
+
+       /* verify the signature */
+       res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/);
+       SECKEY_DestroyPublicKey(pubkey);
+
+       if(res == SECSuccess) {
+               return sec_status_secure;
+       }
+       err = PORT_GetError();
+       if(err != SEC_ERROR_BAD_SIGNATURE) {
+               /* failed to verify */
+               verbose(VERB_QUERY, "verify: PK11_Verify failed: %s",
+                       PORT_ErrorToString(err));
+               /* if it is not supported, like ECC is removed, we get,
+                * SEC_ERROR_NO_MODULE */
+               if(err == SEC_ERROR_NO_MODULE)
+                       return sec_status_unchecked;
+               /* but other errors are commonly returned
+                * for a bad signature from NSS.  Thus we return bogus,
+                * not unchecked */
+               *reason = "signature crypto failed";
+               return sec_status_bogus;
+       }
+       verbose(VERB_QUERY, "verify: signature mismatch: %s",
+               PORT_ErrorToString(err));
+       *reason = "signature crypto failed";
+       return sec_status_bogus;
+}
+
+
+#endif /* HAVE_SSL or HAVE_NSS */
diff --git a/validator/val_secalgo.h b/validator/val_secalgo.h
new file mode 100644 (file)
index 0000000..a5832af
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * validator/val_secalgo.h - validator security algorithm functions.
+ *
+ * Copyright (c) 2012, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains helper functions for the validator module.
+ * The functions take buffers with raw data and convert to library calls.
+ */
+
+#ifndef VALIDATOR_VAL_SECALGO_H
+#define VALIDATOR_VAL_SECALGO_H
+
+/**
+ * Return size of DS digest according to its hash algorithm.
+ * @param algo: DS digest algo.
+ * @return size in bytes of digest, or 0 if not supported. 
+ */
+size_t ds_digest_size_supported(int algo);
+
+/**
+ * @param algo: the DS digest algo
+ * @param buf: the buffer to digest
+ * @param len: length of buffer to digest.
+ * @param res: result stored here (must have sufficient space).
+ * @return false on failure.
+ */
+int secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
+       unsigned char* res);
+
+/** return true if DNSKEY algorithm id is supported */
+int dnskey_algo_id_is_supported(int id);
+
+/**
+ * Check a canonical sig+rrset and signature against a dnskey
+ * @param buf: buffer with data to verify, the first rrsig part and the
+ *     canonicalized rrset.
+ * @param algo: DNSKEY algorithm.
+ * @param sigblock: signature rdata field from RRSIG
+ * @param sigblock_len: length of sigblock data.
+ * @param key: public key data from DNSKEY RR.
+ * @param keylen: length of keydata.
+ * @param reason: bogus reason in more detail.
+ * @return secure if verification succeeded, bogus on crypto failure,
+ *     unchecked on format errors and alloc failures.
+ */
+enum sec_status verify_canonrrset(ldns_buffer* buf, int algo,
+       unsigned char* sigblock, unsigned int sigblock_len,
+       unsigned char* key, unsigned int keylen, char** reason);
+
+#endif /* VALIDATOR_VAL_SECALGO_H */
index 4c79c004d02c90b648d792ced2c5ee0f24326c47..79d5e45a237918caa01c74f2f18c8238314a084e 100644 (file)
@@ -43,6 +43,7 @@
 #include "config.h"
 #include <ldns/ldns.h>
 #include "validator/val_sigcrypt.h"
+#include "validator/val_secalgo.h"
 #include "validator/validator.h"
 #include "util/data/msgreply.h"
 #include "util/data/msgparse.h"
@@ -52,8 +53,8 @@
 #include "util/net_help.h"
 #include "util/regional.h"
 
-#ifndef HAVE_SSL
-#error "Need SSL library to do digital signature cryptography"
+#if !defined(HAVE_SSL) && !defined(HAVE_NSS)
+#error "Need crypto library to do digital signature cryptography"
 #endif
 
 #ifdef HAVE_OPENSSL_ERR_H
@@ -265,41 +266,8 @@ ds_get_sigdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** digest,
 static size_t
 ds_digest_size_algo(struct ub_packed_rrset_key* k, size_t idx)
 {
-       switch(ds_get_digest_algo(k, idx)) {
-#ifdef HAVE_EVP_SHA1
-               case LDNS_SHA1:
-                       return SHA_DIGEST_LENGTH;
-#endif
-#ifdef HAVE_EVP_SHA256
-               case LDNS_SHA256:
-                       return SHA256_DIGEST_LENGTH;
-#endif
-#ifdef USE_GOST
-               case LDNS_HASH_GOST:
-                       if(EVP_get_digestbyname("md_gost94"))
-                               return 32;
-                       else    return 0;
-#endif
-#ifdef USE_ECDSA
-               case LDNS_SHA384:
-                       return SHA384_DIGEST_LENGTH;
-#endif
-               default: break;
-       }
-       return 0;
-}
-
-#ifdef USE_GOST
-/** Perform GOST hash */
-static int
-do_gost94(unsigned char* data, size_t len, unsigned char* dest)
-{
-       const EVP_MD* md = EVP_get_digestbyname("md_gost94");
-       if(!md) 
-               return 0;
-       return ldns_digest_evp(data, (unsigned int)len, dest, md);
+       return ds_digest_size_supported(ds_get_digest_algo(k, idx));
 }
-#endif
 
 /**
  * Create a DS digest for a DNSKEY entry.
@@ -333,37 +301,9 @@ ds_create_dnskey_digest(struct module_env* env,
        ldns_buffer_write(b, dnskey_rdata+2, dnskey_len-2); /* skip rdatalen*/
        ldns_buffer_flip(b);
        
-       switch(ds_get_digest_algo(ds_rrset, ds_idx)) {
-#ifdef HAVE_EVP_SHA1
-               case LDNS_SHA1:
-                       (void)SHA1((unsigned char*)ldns_buffer_begin(b),
-                               ldns_buffer_limit(b), (unsigned char*)digest);
-                       return 1;
-#endif
-#ifdef HAVE_EVP_SHA256
-               case LDNS_SHA256:
-                       (void)SHA256((unsigned char*)ldns_buffer_begin(b),
-                               ldns_buffer_limit(b), (unsigned char*)digest);
-                       return 1;
-#endif
-#ifdef USE_GOST
-               case LDNS_HASH_GOST:
-                       if(do_gost94((unsigned char*)ldns_buffer_begin(b), 
-                               ldns_buffer_limit(b), (unsigned char*)digest))
-                               return 1;
-#endif
-#ifdef USE_ECDSA
-               case LDNS_SHA384:
-                       (void)SHA384((unsigned char*)ldns_buffer_begin(b),
-                               ldns_buffer_limit(b), (unsigned char*)digest);
-                       return 1;
-#endif
-               default: 
-                       verbose(VERB_QUERY, "unknown DS digest algorithm %d", 
-                               (int) ds_get_digest_algo(ds_rrset, ds_idx));
-                       break;
-       }
-       return 0;
+       return secalgo_ds_digest(ds_get_digest_algo(ds_rrset, ds_idx),
+               (unsigned char*)ldns_buffer_begin(b), ldns_buffer_limit(b),
+               (unsigned char*)digest);
 }
 
 int ds_digest_match_dnskey(struct module_env* env,
@@ -412,37 +352,6 @@ ds_digest_algo_is_supported(struct ub_packed_rrset_key* ds_rrset,
        return (ds_digest_size_algo(ds_rrset, ds_idx) != 0);
 }
 
-/** return true if DNSKEY algorithm id is supported */
-static int
-dnskey_algo_id_is_supported(int id)
-{
-       switch(id) {
-       case LDNS_DSA:
-       case LDNS_DSA_NSEC3:
-       case LDNS_RSASHA1:
-       case LDNS_RSASHA1_NSEC3:
-       case LDNS_RSAMD5:
-#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
-       case LDNS_RSASHA256:
-#endif
-#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
-       case LDNS_RSASHA512:
-#endif
-#ifdef USE_ECDSA
-       case LDNS_ECDSAP256SHA256:
-       case LDNS_ECDSAP384SHA384:
-#endif
-               return 1;
-#ifdef USE_GOST
-       case LDNS_ECC_GOST:
-               /* we support GOST if it can be loaded */
-               return ldns_key_EVP_load_gost_id();
-#endif
-       default:
-               return 0;
-       }
-}
-
 int 
 ds_key_algo_is_supported(struct ub_packed_rrset_key* ds_rrset, 
        size_t ds_idx)
@@ -606,10 +515,14 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
                                (uint8_t)rrset_get_sig_algo(rrset, i));
                }
        }
-       verbose(VERB_ALGO, "rrset failed to verify: no valid signatures for "
-               "%d algorithms", (int)algo_needs_num_missing(&needs));
        if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
+               verbose(VERB_ALGO, "rrset failed to verify: "
+                       "no valid signatures for %d algorithms",
+                       (int)algo_needs_num_missing(&needs));
                algo_needs_reason(env, alg, reason, "no signatures");
+       } else {
+               verbose(VERB_ALGO, "rrset failed to verify: "
+                       "no valid signatures");
        }
        return sec_status_bogus;
 }
@@ -1314,378 +1227,6 @@ adjust_ttl(struct val_env* ve, uint32_t unow,
        }
 }
 
-
-/**
- * Output a libcrypto openssl error to the logfile.
- * @param str: string to add to it.
- * @param e: the error to output, error number from ERR_get_error().
- */
-static void
-log_crypto_error(const char* str, unsigned long e)
-{
-       char buf[128];
-       /* or use ERR_error_string if ERR_error_string_n is not avail TODO */
-       ERR_error_string_n(e, buf, sizeof(buf));
-       /* buf now contains */
-       /* error:[error code]:[library name]:[function name]:[reason string] */
-       log_err("%s crypto %s", str, buf);
-}
-
-/**
- * Setup DSA key digest in DER encoding ... 
- * @param sig: input is signature output alloced ptr (unless failure).
- *     caller must free alloced ptr if this routine returns true.
- * @param len: input is initial siglen, output is output len.
- * @return false on failure.
- */
-static int
-setup_dsa_sig(unsigned char** sig, unsigned int* len)
-{
-       unsigned char* orig = *sig;
-       unsigned int origlen = *len;
-       int newlen;
-       BIGNUM *R, *S;
-       DSA_SIG *dsasig;
-
-       /* extract the R and S field from the sig buffer */
-       if(origlen < 1 + 2*SHA_DIGEST_LENGTH)
-               return 0;
-       R = BN_new();
-       if(!R) return 0;
-       (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R);
-       S = BN_new();
-       if(!S) return 0;
-       (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S);
-       dsasig = DSA_SIG_new();
-       if(!dsasig) return 0;
-
-       dsasig->r = R;
-       dsasig->s = S;
-       *sig = NULL;
-       newlen = i2d_DSA_SIG(dsasig, sig);
-       if(newlen < 0) {
-               DSA_SIG_free(dsasig);
-               free(*sig);
-               return 0;
-       }
-       *len = (unsigned int)newlen;
-       DSA_SIG_free(dsasig);
-       return 1;
-}
-
-#ifdef USE_ECDSA
-/**
- * Setup the ECDSA signature in its encoding that the library wants.
- * Converts from plain numbers to ASN formatted.
- * @param sig: input is signature, output alloced ptr (unless failure).
- *     caller must free alloced ptr if this routine returns true.
- * @param len: input is initial siglen, output is output len.
- * @return false on failure.
- */
-static int
-setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
-{
-       ECDSA_SIG* ecdsa_sig;
-       int newlen;
-       int bnsize = (int)((*len)/2);
-       /* if too short or not even length, fails */
-       if(*len < 16 || bnsize*2 != (int)*len)
-               return 0;
-       /* use the raw data to parse two evenly long BIGNUMs, "r | s". */
-       ecdsa_sig = ECDSA_SIG_new();
-       if(!ecdsa_sig) return 0;
-       ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r);
-       ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s);
-       if(!ecdsa_sig->r || !ecdsa_sig->s) {
-               ECDSA_SIG_free(ecdsa_sig);
-               return 0;
-       }
-
-       /* spool it into ASN format */
-       *sig = NULL;
-       newlen = i2d_ECDSA_SIG(ecdsa_sig, sig);
-       if(newlen <= 0) {
-               ECDSA_SIG_free(ecdsa_sig);
-               free(*sig);
-               return 0;
-       }
-       *len = (unsigned int)newlen;
-       ECDSA_SIG_free(ecdsa_sig);
-       return 1;
-}
-#endif /* USE_ECDSA */
-
-/**
- * Setup key and digest for verification. Adjust sig if necessary.
- *
- * @param algo: key algorithm
- * @param evp_key: EVP PKEY public key to create.
- * @param digest_type: digest type to use
- * @param key: key to setup for.
- * @param keylen: length of key.
- * @return false on failure.
- */
-static int
-setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, 
-       unsigned char* key, size_t keylen)
-{
-       DSA* dsa;
-       RSA* rsa;
-
-       switch(algo) {
-               case LDNS_DSA:
-               case LDNS_DSA_NSEC3:
-                       *evp_key = EVP_PKEY_new();
-                       if(!*evp_key) {
-                               log_err("verify: malloc failure in crypto");
-                               return sec_status_unchecked;
-                       }
-                       dsa = ldns_key_buf2dsa_raw(key, keylen);
-                       if(!dsa) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "ldns_key_buf2dsa_raw failed");
-                               return 0;
-                       }
-                       if(EVP_PKEY_assign_DSA(*evp_key, dsa) == 0) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "EVP_PKEY_assign_DSA failed");
-                               return 0;
-                       }
-                       *digest_type = EVP_dss1();
-
-                       break;
-               case LDNS_RSASHA1:
-               case LDNS_RSASHA1_NSEC3:
-#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
-               case LDNS_RSASHA256:
-#endif
-#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
-               case LDNS_RSASHA512:
-#endif
-                       *evp_key = EVP_PKEY_new();
-                       if(!*evp_key) {
-                               log_err("verify: malloc failure in crypto");
-                               return sec_status_unchecked;
-                       }
-                       rsa = ldns_key_buf2rsa_raw(key, keylen);
-                       if(!rsa) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "ldns_key_buf2rsa_raw SHA failed");
-                               return 0;
-                       }
-                       if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "EVP_PKEY_assign_RSA SHA failed");
-                               return 0;
-                       }
-
-                       /* select SHA version */
-#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
-                       if(algo == LDNS_RSASHA256)
-                               *digest_type = EVP_sha256();
-                       else
-#endif
-#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
-                               if(algo == LDNS_RSASHA512)
-                               *digest_type = EVP_sha512();
-                       else
-#endif
-                               *digest_type = EVP_sha1();
-
-                       break;
-               case LDNS_RSAMD5:
-                       *evp_key = EVP_PKEY_new();
-                       if(!*evp_key) {
-                               log_err("verify: malloc failure in crypto");
-                               return sec_status_unchecked;
-                       }
-                       rsa = ldns_key_buf2rsa_raw(key, keylen);
-                       if(!rsa) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "ldns_key_buf2rsa_raw MD5 failed");
-                               return 0;
-                       }
-                       if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "EVP_PKEY_assign_RSA MD5 failed");
-                               return 0;
-                       }
-                       *digest_type = EVP_md5();
-
-                       break;
-#ifdef USE_GOST
-               case LDNS_ECC_GOST:
-                       *evp_key = ldns_gost2pkey_raw(key, keylen);
-                       if(!*evp_key) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "ldns_gost2pkey_raw failed");
-                               return 0;
-                       }
-                       *digest_type = EVP_get_digestbyname("md_gost94");
-                       if(!*digest_type) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "EVP_getdigest md_gost94 failed");
-                               return 0;
-                       }
-                       break;
-#endif
-#ifdef USE_ECDSA
-               case LDNS_ECDSAP256SHA256:
-                       *evp_key = ldns_ecdsa2pkey_raw(key, keylen,
-                               LDNS_ECDSAP256SHA256);
-                       if(!*evp_key) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "ldns_ecdsa2pkey_raw failed");
-                               return 0;
-                       }
-#ifdef USE_ECDSA_EVP_WORKAROUND
-                       /* openssl before 1.0.0 fixes RSA with the SHA256
-                        * hash in EVP.  We create one for ecdsa_sha256 */
-                       {
-                               static int md_ecdsa_256_done = 0;
-                               static EVP_MD md;
-                               if(!md_ecdsa_256_done) {
-                                       EVP_MD m = *EVP_sha256();
-                                       md_ecdsa_256_done = 1;
-                                       m.required_pkey_type[0] = (*evp_key)->type;
-                                       m.verify = (void*)ECDSA_verify;
-                                       md = m;
-                               }
-                               *digest_type = &md;
-                       }
-#else
-                       *digest_type = EVP_sha256();
-#endif
-                       break;
-               case LDNS_ECDSAP384SHA384:
-                       *evp_key = ldns_ecdsa2pkey_raw(key, keylen,
-                               LDNS_ECDSAP384SHA384);
-                       if(!*evp_key) {
-                               verbose(VERB_QUERY, "verify: "
-                                       "ldns_ecdsa2pkey_raw failed");
-                               return 0;
-                       }
-#ifdef USE_ECDSA_EVP_WORKAROUND
-                       /* openssl before 1.0.0 fixes RSA with the SHA384
-                        * hash in EVP.  We create one for ecdsa_sha384 */
-                       {
-                               static int md_ecdsa_384_done = 0;
-                               static EVP_MD md;
-                               if(!md_ecdsa_384_done) {
-                                       EVP_MD m = *EVP_sha384();
-                                       md_ecdsa_384_done = 1;
-                                       m.required_pkey_type[0] = (*evp_key)->type;
-                                       m.verify = (void*)ECDSA_verify;
-                                       md = m;
-                               }
-                               *digest_type = &md;
-                       }
-#else
-                       *digest_type = EVP_sha384();
-#endif
-                       break;
-#endif /* USE_ECDSA */
-               default:
-                       verbose(VERB_QUERY, "verify: unknown algorithm %d", 
-                               algo);
-                       return 0;
-       }
-       return 1;
-}
-
-/**
- * Check a canonical sig+rrset and signature against a dnskey
- * @param buf: buffer with data to verify, the first rrsig part and the
- *     canonicalized rrset.
- * @param algo: DNSKEY algorithm.
- * @param sigblock: signature rdata field from RRSIG
- * @param sigblock_len: length of sigblock data.
- * @param key: public key data from DNSKEY RR.
- * @param keylen: length of keydata.
- * @param reason: bogus reason in more detail.
- * @return secure if verification succeeded, bogus on crypto failure,
- *     unchecked on format errors and alloc failures.
- */
-static enum sec_status
-verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, 
-       unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
-       char** reason)
-{
-       const EVP_MD *digest_type;
-       EVP_MD_CTX ctx;
-       int res, dofree = 0;
-       EVP_PKEY *evp_key = NULL;
-       
-       if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
-               verbose(VERB_QUERY, "verify: failed to setup key");
-               *reason = "use of key for crypto failed";
-               EVP_PKEY_free(evp_key);
-               return sec_status_bogus;
-       }
-       /* if it is a DSA signature in bind format, convert to DER format */
-       if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && 
-               sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
-               if(!setup_dsa_sig(&sigblock, &sigblock_len)) {
-                       verbose(VERB_QUERY, "verify: failed to setup DSA sig");
-                       *reason = "use of key for DSA crypto failed";
-                       EVP_PKEY_free(evp_key);
-                       return sec_status_bogus;
-               }
-               dofree = 1;
-       }
-#ifdef USE_ECDSA
-       else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
-               /* EVP uses ASN prefix on sig, which is not in the wire data */
-               if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
-                       verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
-                       *reason = "use of signature for ECDSA crypto failed";
-                       EVP_PKEY_free(evp_key);
-                       return sec_status_bogus;
-               }
-               dofree = 1;
-       }
-#endif /* USE_ECDSA */
-
-       /* do the signature cryptography work */
-       EVP_MD_CTX_init(&ctx);
-       if(EVP_VerifyInit(&ctx, digest_type) == 0) {
-               verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
-               EVP_PKEY_free(evp_key);
-               if(dofree) free(sigblock);
-               return sec_status_unchecked;
-       }
-       if(EVP_VerifyUpdate(&ctx, (unsigned char*)ldns_buffer_begin(buf), 
-               (unsigned int)ldns_buffer_limit(buf)) == 0) {
-               verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed");
-               EVP_PKEY_free(evp_key);
-               if(dofree) free(sigblock);
-               return sec_status_unchecked;
-       }
-
-       res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
-       if(EVP_MD_CTX_cleanup(&ctx) == 0) {
-               verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");
-               EVP_PKEY_free(evp_key);
-               if(dofree) free(sigblock);
-               return sec_status_unchecked;
-       }
-       EVP_PKEY_free(evp_key);
-
-       if(dofree)
-               free(sigblock);
-
-       if(res == 1) {
-               return sec_status_secure;
-       } else if(res == 0) {
-               verbose(VERB_QUERY, "verify: signature mismatch");
-               *reason = "signature crypto failed";
-               return sec_status_bogus;
-       }
-
-       log_crypto_error("verify:", ERR_get_error());
-       return sec_status_unchecked;
-}
-
 enum sec_status 
 dnskey_verify_rrset_sig(struct regional* region, ldns_buffer* buf, 
        struct val_env* ve, uint32_t now,
index b0475d8031c4b6978a3274742308322e73bb8db2..d4a64464d80873b6f535bd62bc1b9b8d50007708 100644 (file)
@@ -54,7 +54,6 @@
 #include "util/net_help.h"
 #include "util/module.h"
 #include "util/regional.h"
-#include "util/config_file.h"
 
 enum val_classification 
 val_classify_response(uint16_t query_flags, struct query_info* origqinf,
index af1d344a6912684bf01b55262b7d2e5eebc53044..d8f9bbcc4b334a4e3f5a364e30db227cb9c2583d 100644 (file)
@@ -1881,7 +1881,8 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
        /* store overall validation result in orig_msg */
        if(vq->rrset_skip == 0)
                vq->orig_msg->rep->security = vq->chase_reply->security;
-       else if(vq->rrset_skip < vq->orig_msg->rep->an_numrrsets + 
+       else if(subtype != VAL_CLASS_REFERRAL ||
+               vq->rrset_skip < vq->orig_msg->rep->an_numrrsets + 
                vq->orig_msg->rep->ns_numrrsets) {
                /* ignore sec status of additional section if a referral 
                 * type message skips there and
index 18e905efcd2b6afb8f35c08311b7380735377176..1a29c161b9f25e251eb0b1a2c42cef9075d81ce7 100644 (file)
@@ -56,13 +56,13 @@ struct config_strlist;
  * will be primed no more often than this interval.  Used when harden-
  * dnssec-stripped is off and the trust anchor fails.
  */
-#define NULL_KEY_TTL   900 /* seconds */
+#define NULL_KEY_TTL   60 /* seconds */
 
 /**
  * TTL for bogus key entries.  When a DS or DNSKEY fails in the chain of
  * trust the entire zone for that name is blacked out for this TTL.
  */
-#define BOGUS_KEY_TTL  900 /* seconds */
+#define BOGUS_KEY_TTL  60 /* seconds */
 
 /** max number of query restarts, number of IPs to probe */
 #define VAL_MAX_RESTART_COUNT 5