PYTHONMOD_UNINSTALL=@PYTHONMOD_UNINSTALL@
PYUNBOUND_INSTALL=@PYUNBOUND_INSTALL@
PYUNBOUND_UNINSTALL=@PYUNBOUND_UNINSTALL@
+ALLTARGET=@ALLTARGET@
# _unbound.la if pyunbound enabled.
PYUNBOUND_TARGET=@PYUNBOUND_TARGET@
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 \
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
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
$(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
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
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
$(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 \
/* 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
#! /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>.
#
# 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=''
ac_subst_vars='LTLIBOBJS
ldnsdir
+ALLTARGET
SOURCEFILE
SOURCEDETERMINE
UBSYMS
with_solaris_threads
with_pyunbound
with_pythonmodule
+with_nss
with_ssl
enable_sha2
enable_gost
enable_static_exe
enable_lock_checks
enable_allsymbols
+with_libunbound_only
with_ldns
'
ac_precious_vars='build_alias
# 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]...
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
(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)
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:
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.
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 $@
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
# 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
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
fi
+fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
# 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 :
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"
#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 :
fi
use_gost="no"
+if test $USE_NSS = "no"; then
case "$enable_gost" in
no)
;;
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
{ $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
fi
;;
esac
-
+fi
# Check whether --enable-ecdsa was given.
if test "${enable_ecdsa+set}" = set; then :
enableval=$enable_ecdsa;
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>
"
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.
+# 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.
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 :
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 :
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" "
# 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
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\\"
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
# 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
# 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
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
#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
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"
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.])
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],
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
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.
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"
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
--- /dev/null
+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
#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"
#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"
#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. */
#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();
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) {
(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)
}
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;
}
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;
}
}
}
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;
}
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;
}
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);
}
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;
};
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
};
/**
/** 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
* @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);
# 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;
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);
* 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]) {
}
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 */
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,
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;
}
+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).
# 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.
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
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
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
.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
.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
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;
}
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 */
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;
}
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
* @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);
/* 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);
}
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) {
/* 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++;
* 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");
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;
)) {
/* 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);
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))
/* 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;
* 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;
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);
}
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,
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;
}
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)
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)
&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 */
#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;
}
#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;
}
(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;
}
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);
/* 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;
*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--;
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;
}
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;
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;
}
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);
}
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);
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) {
};
/** 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.
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.
*/
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.
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");
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));
#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;
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;
}
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);
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
#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"
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();
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);
#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"
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");
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");
--- /dev/null
+; 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
--- /dev/null
+; 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
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__)
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;
}
#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"
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:
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,
#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);
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);
#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 */
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;
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");
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");
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");
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");
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 */
+}
+
*/
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 */
#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 */
{
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) {
}
/** continue ssl handshake */
+#ifdef HAVE_SSL
static int
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))
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))
tcp_callback_writer(c);
}
return 1;
+#else
+ (void)c;
+ return 0;
+#endif /* HAVE_SSL */
}
/** handle ssl tcp connection with dns contents */
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) {
#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.
/** 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)
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);
/*
return NULL;
}
ub_systemseed(seed);
+#ifdef HAVE_FIPS_MODE
+ if(!FIPS_mode())
+#endif
ub_arc4random_stir(s, from);
return s;
}
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);
}
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)
{
*/
#include "config.h"
#include "util/rtt.h"
-#include "util/log.h"
/** calculate RTO from rtt information */
static int
}
d += r;
}
+ log_assert(*len < 65536*2);
*buf = (uint8_t*)malloc(*len);
if(!*buf) {
log_err("tube read out of memory");
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;
/* 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);
}
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;
#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"
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;
{
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;
#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"
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;
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;
* 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;
--- /dev/null
+/*
+ * 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, ¶ms)) {
+ 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 */
--- /dev/null
+/*
+ * 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 */
#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"
#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
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.
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,
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)
(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;
}
}
}
-
-/**
- * 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,
#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,
/* 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
* 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