From 3ce7d3ef02661fb7ea3af04c902f14ef00bcffec Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 06 2019 09:43:39 +0000 Subject: import bind-9.11.4-9.P2.el7 --- diff --git a/.bind.metadata b/.bind.metadata index e720302..013caa7 100644 --- a/.bind.metadata +++ b/.bind.metadata @@ -1,3 +1,2 @@ -d7be390e6c2546f37a7280e1975e1cd134565f62 SOURCES/bind-9.9.4.tar.gz -10d75c6d5a9960fb8ef7908dcc14381ee849139c SOURCES/config-16.tar.bz2 -d3c4943f2f2aa1f7c51487af02ff3a52ca51a6d9 SOURCES/geoip-testing-data.tar.xz +f01eada382fb2bd4d1fcab3f6f83bd3ebc35a9ab SOURCES/bind-9.11.4-P2.tar.gz +1dc72fe31e4c84853ea2d016e36f0419d1885fa0 SOURCES/config-18.tar.bz2 diff --git a/.gitignore b/.gitignore index 4d4a123..918743b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -SOURCES/bind-9.9.4.tar.gz -SOURCES/config-16.tar.bz2 -SOURCES/geoip-testing-data.tar.xz +SOURCES/bind-9.11.4-P2.tar.gz +SOURCES/config-18.tar.bz2 diff --git a/SOURCES/bind-9.10-dist-native-pkcs11.patch b/SOURCES/bind-9.10-dist-native-pkcs11.patch new file mode 100644 index 0000000..a700078 --- /dev/null +++ b/SOURCES/bind-9.10-dist-native-pkcs11.patch @@ -0,0 +1,620 @@ +diff --git a/bin/Makefile.in b/bin/Makefile.in +index f0c504a..ce7a2da 100644 +--- a/bin/Makefile.in ++++ b/bin/Makefile.in +@@ -11,8 +11,8 @@ srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ + +-SUBDIRS = named rndc dig delv dnssec tools nsupdate check confgen \ +- @NZD_TOOLS@ @PYTHON_TOOLS@ @PKCS11_TOOLS@ tests ++SUBDIRS = named named-pkcs11 rndc dig delv dnssec dnssec-pkcs11 tools nsupdate \ ++ check confgen @NZD_TOOLS@ @PYTHON_TOOLS@ @PKCS11_TOOLS@ tests + TARGETS = + + @BIND9_MAKE_RULES@ +diff --git a/bin/dnssec-pkcs11/Makefile.in b/bin/dnssec-pkcs11/Makefile.in +index 1d0c4ce..7b7f89b 100644 +--- a/bin/dnssec-pkcs11/Makefile.in ++++ b/bin/dnssec-pkcs11/Makefile.in +@@ -17,18 +17,18 @@ VERSION=@BIND9_VERSION@ + + @BIND9_MAKE_INCLUDES@ + +-CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@ ++CINCLUDES = ${DNS_PKCS11_INCLUDES} ${ISC_PKCS11_INCLUDES} + + CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \ +- @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\" ++ @CRYPTO_PK11@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\" + CWARNINGS = + +-DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ +-ISCLIBS = ../../lib/isc/libisc.@A@ +-ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ ++DNSLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ @DNS_CRYPTO_LIBS@ ++ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ ++ISCNOSYMLIBS = ../../lib/isc-pkcs11/libisc-pkcs11-nosymtbl.@A@ + +-DNSDEPLIBS = ../../lib/dns/libdns.@A@ +-ISCDEPLIBS = ../../lib/isc/libisc.@A@ ++DNSDEPLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ ++ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ + + DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} + +@@ -37,10 +37,10 @@ LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ + NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ + + # Alphabetically +-TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \ +- dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \ +- dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ \ +- dnssec-verify@EXEEXT@ dnssec-importkey@EXEEXT@ ++TARGETS = dnssec-keygen-pkcs11@EXEEXT@ dnssec-signzone-pkcs11@EXEEXT@ \ ++ dnssec-keyfromlabel-pkcs11@EXEEXT@ dnssec-dsfromkey-pkcs11@EXEEXT@ \ ++ dnssec-revoke-pkcs11@EXEEXT@ dnssec-settime-pkcs11@EXEEXT@ \ ++ dnssec-verify-pkcs11@EXEEXT@ dnssec-importkey-pkcs11@EXEEXT@ + + OBJS = dnssectool.@O@ + +@@ -61,15 +61,15 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} + + @BIND9_MAKE_RULES@ + +-dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS} ++dnssec-dsfromkey-pkcs11@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS} + export BASEOBJS="dnssec-dsfromkey.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} + +-dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS} ++dnssec-keyfromlabel-pkcs11@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS} + export BASEOBJS="dnssec-keyfromlabel.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} + +-dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS} ++dnssec-keygen-pkcs11@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS} + export BASEOBJS="dnssec-keygen.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} + +@@ -77,7 +77,7 @@ dnssec-signzone.@O@: dnssec-signzone.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ + -c ${srcdir}/dnssec-signzone.c + +-dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS} ++dnssec-signzone-pkcs11@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS} + export BASEOBJS="dnssec-signzone.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} + +@@ -85,19 +85,19 @@ dnssec-verify.@O@: dnssec-verify.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ + -c ${srcdir}/dnssec-verify.c + +-dnssec-verify@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS} ++dnssec-verify-pkcs11@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS} + export BASEOBJS="dnssec-verify.@O@ ${OBJS}"; \ + ${FINALBUILDCMD} + +-dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS} ++dnssec-revoke-pkcs11@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dnssec-revoke.@O@ ${OBJS} ${LIBS} + +-dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS} ++dnssec-settime-pkcs11@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dnssec-settime.@O@ ${OBJS} ${LIBS} + +-dnssec-importkey@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS} ++dnssec-importkey-pkcs11@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + dnssec-importkey.@O@ ${OBJS} ${LIBS} + +@@ -108,16 +108,14 @@ docclean manclean maintainer-clean:: + + installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} +- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + + install-man8: ${MANPAGES} + ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 + +-install:: ${TARGETS} installdirs install-man8 ++install:: ${TARGETS} installdirs + for t in ${TARGETS}; do ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} $$t ${DESTDIR}${sbindir}; done + + uninstall:: +- for m in ${MANPAGES}; do rm -f ${DESTDIR}${mandir}/man8/$$m ; done + for t in ${TARGETS}; do ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/$$t ; done + + clean distclean:: +diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in +index 1d0c4ce..11538cf 100644 +--- a/bin/dnssec/Makefile.in ++++ b/bin/dnssec/Makefile.in +@@ -19,7 +19,7 @@ VERSION=@BIND9_VERSION@ + + CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@ + +-CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \ ++CDEFINES = -DVERSION=\"${VERSION}\" \ + @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\" + CWARNINGS = + +diff --git a/bin/named-pkcs11/Makefile.in b/bin/named-pkcs11/Makefile.in +index d92bc9a..a8c42a4 100644 +--- a/bin/named-pkcs11/Makefile.in ++++ b/bin/named-pkcs11/Makefile.in +@@ -43,26 +43,26 @@ DLZDRIVER_INCLUDES = @DLZ_DRIVER_INCLUDES@ + DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@ + + CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ +- ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ +- ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ ++ ${LWRES_INCLUDES} ${DNS_PKCS11_INCLUDES} ${BIND9_INCLUDES} \ ++ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_PKCS11_INCLUDES} \ + ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ + +-CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@ ++CDEFINES = @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO_PK11@ + + CWARNINGS = + +-DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ ++DNSLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ @DNS_CRYPTO_LIBS@ + ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ + ISCCCLIBS = ../../lib/isccc/libisccc.@A@ +-ISCLIBS = ../../lib/isc/libisc.@A@ ++ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ + ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ + LWRESLIBS = ../../lib/lwres/liblwres.@A@ + BIND9LIBS = ../../lib/bind9/libbind9.@A@ + +-DNSDEPLIBS = ../../lib/dns/libdns.@A@ ++DNSDEPLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ + ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ + ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ +-ISCDEPLIBS = ../../lib/isc/libisc.@A@ ++ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ + LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ + BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ + +@@ -71,15 +71,15 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ + + LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ + ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ +- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ ++ @LIBS@ + + NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ + ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \ +- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ ++ @LIBS@ + + SUBDIRS = unix + +-TARGETS = named@EXEEXT@ lwresd@EXEEXT@ ++TARGETS = named-pkcs11@EXEEXT@ + + GEOIPLINKOBJS = geoip.@O@ + +@@ -90,8 +90,7 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ + tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ + zoneconf.@O@ \ + lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \ +- lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \ +- ${DLZDRIVER_OBJS} ${DBDRIVER_OBJS} ++ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ + + UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ + +@@ -106,8 +105,7 @@ SRCS = builtin.c client.c config.c control.c \ + tkeyconf.c tsigconf.c update.c xfrout.c \ + zoneconf.c \ + lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ +- lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \ +- ${DLZDRIVER_SRCS} ${DBDRIVER_SRCS} ++ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c + + MANPAGES = named.8 lwresd.8 named.conf.5 + +@@ -146,14 +144,14 @@ server.@O@: server.c + -DPRODUCT=\"${PRODUCT}\" \ + -DVERSION=\"${VERSION}\" -c ${srcdir}/server.c + +-named@EXEEXT@: ${OBJS} ${DEPLIBS} ++named-pkcs11@EXEEXT@: ${OBJS} ${DEPLIBS} + export MAKE_SYMTABLE="yes"; \ + export BASEOBJS="${OBJS} ${UOBJS}"; \ + ${FINALBUILDCMD} + +-lwresd@EXEEXT@: named@EXEEXT@ ++lwresd@EXEEXT@: named-pkcs11@EXEEXT@ + rm -f lwresd@EXEEXT@ +- @LN@ named@EXEEXT@ lwresd@EXEEXT@ ++ @LN@ named-pkcs11@EXEEXT@ lwresd@EXEEXT@ + + doc man:: ${MANOBJS} + +@@ -184,16 +182,11 @@ install-man8: named.8 lwresd.8 + + install-man: install-man5 install-man8 + +-install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs install-man +- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir} +- (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@) ++install:: named-pkcs11@EXEEXT@ installdirs ++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-pkcs11@EXEEXT@ ${DESTDIR}${sbindir} + + uninstall:: +- rm -f ${DESTDIR}${mandir}/man5/named.conf.5 +- rm -f ${DESTDIR}${mandir}/man8/lwresd.8 +- rm -f ${DESTDIR}${mandir}/man8/named.8 +- rm -f ${DESTDIR}${sbindir}/lwresd@EXEEXT@ +- ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named@EXEEXT@ ++ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named-pkcs11@EXEEXT@ + + @DLZ_DRIVER_RULES@ + +diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in +index d92bc9a..6d2bfd1 100644 +--- a/bin/named/Makefile.in ++++ b/bin/named/Makefile.in +@@ -47,7 +47,7 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ + ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ + ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ + +-CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@ ++CDEFINES = @CONTRIB_DLZ@ @CRYPTO@ + + CWARNINGS = + +diff --git a/bin/pkcs11/Makefile.in b/bin/pkcs11/Makefile.in +index 70ee8b5..0fd8644 100644 +--- a/bin/pkcs11/Makefile.in ++++ b/bin/pkcs11/Makefile.in +@@ -15,13 +15,13 @@ top_srcdir = @top_srcdir@ + + @BIND9_MAKE_INCLUDES@ + +-CINCLUDES = ${ISC_INCLUDES} ++CINCLUDES = ${ISC_PKCS11_INCLUDES} + + CDEFINES = + +-ISCLIBS = ../../lib/isc/libisc.@A@ @ISC_OPENSSL_LIBS@ ++ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ @ISC_OPENSSL_LIBS@ + +-ISCDEPLIBS = ../../lib/isc/libisc.@A@ ++ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ + + DEPLIBS = ${ISCDEPLIBS} + +diff --git a/configure.in b/configure.in +index 9a1d16d..2f13059 100644 +--- a/configure.in ++++ b/configure.in +@@ -1164,12 +1164,14 @@ AC_SUBST(USE_GSSAPI) + AC_SUBST(DST_GSSAPI_INC) + AC_SUBST(DNS_GSSAPI_LIBS) + DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS" ++DNS_CRYPTO_PK11_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_PK11_LIBS" + + # + # Applications linking with libdns also need to link with these libraries. + # + + AC_SUBST(DNS_CRYPTO_LIBS) ++AC_SUBST(DNS_CRYPTO_PK11_LIBS) + + # + # was --with-randomdev specified? +@@ -1554,11 +1556,11 @@ fi + AC_MSG_CHECKING(for OpenSSL library) + OPENSSL_WARNING= + openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw" +-if test "yes" = "$want_native_pkcs11" +-then +- use_openssl="native_pkcs11" +- AC_MSG_RESULT(use of native PKCS11 instead) +-fi ++# if test "yes" = "$want_native_pkcs11" ++# then ++# use_openssl="native_pkcs11" ++# AC_MSG_RESULT(use of native PKCS11 instead) ++# fi + + if test "auto" = "$use_openssl" + then +@@ -1571,6 +1573,7 @@ then + fi + done + fi ++CRYPTO_PK11="" + OPENSSL_ECDSA="" + OPENSSL_GOST="" + OPENSSL_ED25519="" +@@ -1592,11 +1595,10 @@ case "$with_gost" in + ;; + esac + +-case "$use_openssl" in +- native_pkcs11) +- AC_MSG_RESULT(disabled because of native PKCS11) ++if test "$want_native_pkcs11" = "yes" ++then + DST_OPENSSL_INC="" +- CRYPTO="-DPKCS11CRYPTO" ++ CRYPTO_PK11="-DPKCS11CRYPTO" + OPENSSLECDSALINKOBJS="" + OPENSSLECDSALINKSRCS="" + OPENSSLEDDSALINKOBJS="" +@@ -1605,7 +1607,9 @@ case "$use_openssl" in + OPENSSLGOSTLINKSRCS="" + OPENSSLLINKOBJS="" + OPENSSLLINKSRCS="" +- ;; ++fi ++ ++case "$use_openssl" in + no) + AC_MSG_RESULT(no) + DST_OPENSSL_INC="" +@@ -1635,11 +1639,11 @@ case "$use_openssl" in + If you don't want OpenSSL, use --without-openssl]) + ;; + *) +- if test "yes" = "$want_native_pkcs11" +- then +- AC_MSG_RESULT() +- AC_MSG_ERROR([OpenSSL and native PKCS11 cannot be used together.]) +- fi ++ # if test "yes" = "$want_native_pkcs11" ++ # then ++ # AC_MSG_RESULT() ++ # AC_MSG_ERROR([OpenSSL and native PKCS11 cannot be used together.]) ++ # fi + if test "yes" = "$use_openssl" + then + # User did not specify a path - guess it +@@ -2062,6 +2066,7 @@ AC_SUBST(OPENSSL_ED25519) + AC_SUBST(OPENSSL_GOST) + + DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DST_OPENSSL_LIBS" ++DNS_CRYPTO_PK11_LIBS="$DNS_CRYPTO_LIBS" + + ISC_PLATFORM_WANTAES="#undef ISC_PLATFORM_WANTAES" + if test "yes" = "$with_aes" +@@ -2381,6 +2386,7 @@ esac + AC_SUBST(PKCS11LINKOBJS) + AC_SUBST(PKCS11LINKSRCS) + AC_SUBST(CRYPTO) ++AC_SUBST(CRYPTO_PK11) + AC_SUBST(PKCS11_ECDSA) + AC_SUBST(PKCS11_GOST) + AC_SUBST(PKCS11_ED25519) +@@ -5434,8 +5440,11 @@ AC_CONFIG_FILES([ + bin/delv/Makefile + bin/dig/Makefile + bin/dnssec/Makefile ++ bin/dnssec-pkcs11/Makefile + bin/named/Makefile + bin/named/unix/Makefile ++ bin/named-pkcs11/Makefile ++ bin/named-pkcs11/unix/Makefile + bin/nsupdate/Makefile + bin/pkcs11/Makefile + bin/python/Makefile +@@ -5509,6 +5518,10 @@ AC_CONFIG_FILES([ + lib/dns/include/dns/Makefile + lib/dns/include/dst/Makefile + lib/dns/tests/Makefile ++ lib/dns-pkcs11/Makefile ++ lib/dns-pkcs11/include/Makefile ++ lib/dns-pkcs11/include/dns/Makefile ++ lib/dns-pkcs11/include/dst/Makefile + lib/irs/Makefile + lib/irs/include/Makefile + lib/irs/include/irs/Makefile +@@ -5533,6 +5546,24 @@ AC_CONFIG_FILES([ + lib/isc/unix/include/Makefile + lib/isc/unix/include/isc/Makefile + lib/isc/unix/include/pkcs11/Makefile ++ lib/isc-pkcs11/$arch/Makefile ++ lib/isc-pkcs11/$arch/include/Makefile ++ lib/isc-pkcs11/$arch/include/isc/Makefile ++ lib/isc-pkcs11/$thread_dir/Makefile ++ lib/isc-pkcs11/$thread_dir/include/Makefile ++ lib/isc-pkcs11/$thread_dir/include/isc/Makefile ++ lib/isc-pkcs11/Makefile ++ lib/isc-pkcs11/include/Makefile ++ lib/isc-pkcs11/include/isc/Makefile ++ lib/isc-pkcs11/include/isc/platform.h ++ lib/isc-pkcs11/include/pk11/Makefile ++ lib/isc-pkcs11/include/pkcs11/Makefile ++ lib/isc-pkcs11/tests/Makefile ++ lib/isc-pkcs11/nls/Makefile ++ lib/isc-pkcs11/unix/Makefile ++ lib/isc-pkcs11/unix/include/Makefile ++ lib/isc-pkcs11/unix/include/isc/Makefile ++ lib/isc-pkcs11/unix/include/pkcs11/Makefile + lib/isccc/Makefile + lib/isccc/include/Makefile + lib/isccc/include/isccc/Makefile +diff --git a/lib/Makefile.in b/lib/Makefile.in +index 81270a0..bcb5312 100644 +--- a/lib/Makefile.in ++++ b/lib/Makefile.in +@@ -15,7 +15,7 @@ top_srcdir = @top_srcdir@ + # Attempt to disable parallel processing. + .NOTPARALLEL: + .NO_PARALLEL: +-SUBDIRS = isc isccc dns isccfg bind9 lwres irs samples ++SUBDIRS = isc isc-pkcs11 isccc dns dns-pkcs11 isccfg bind9 lwres irs samples + TARGETS = + + @BIND9_MAKE_RULES@ +diff --git a/lib/dns-pkcs11/Makefile.in b/lib/dns-pkcs11/Makefile.in +index 4a8549e..6a19906 100644 +--- a/lib/dns-pkcs11/Makefile.in ++++ b/lib/dns-pkcs11/Makefile.in +@@ -26,16 +26,16 @@ VERSION=@BIND9_VERSION@ + + USE_ISC_SPNEGO = @USE_ISC_SPNEGO@ + +-CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} \ +- ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ ++CINCLUDES = -I. -I${top_srcdir}/lib/dns-pkcs11 -Iinclude ${DNS_PKCS11_INCLUDES} \ ++ ${ISC_PKCS11_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ + +-CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@ ${USE_ISC_SPNEGO} ++CDEFINES = -DUSE_MD5 @CRYPTO_PK11@ @USE_GSSAPI@ ${USE_ISC_SPNEGO} + + CWARNINGS = + +-ISCLIBS = ../../lib/isc/libisc.@A@ ++ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ + +-ISCDEPLIBS = ../../lib/isc/libisc.@A@ ++ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ + + LIBS = @LIBS@ + +@@ -146,15 +146,15 @@ version.@O@: version.c + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +-libdns.@SA@: ${OBJS} ++libdns-pkcs11.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +-libdns.la: ${OBJS} ++libdns-pkcs11.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ +- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns.la -rpath ${libdir} \ ++ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-pkcs11.la -rpath ${libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ +- ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} ++ ${OBJS} ${ISCLIBS} @DNS_CRYPTO_PK11_LIBS@ ${LIBS} + + include: gen + ${MAKE} include/dns/enumtype.h +@@ -180,25 +180,25 @@ code.h: gen + ./gen -s ${srcdir} > code.h || { rm -f $@ ; exit 1; } + + gen: gen.c +- ${BUILD_CC} ${BUILD_CFLAGS} -I${top_srcdir}/lib/isc/include \ ++ ${BUILD_CC} ${BUILD_CFLAGS} -I${top_srcdir}/lib/isc-pkcs11/include \ + ${BUILD_CPPFLAGS} ${BUILD_LDFLAGS} -o $@ ${srcdir}/gen.c ${BUILD_LIBS} + +-timestamp: include libdns.@A@ ++timestamp: include libdns-pkcs11.@A@ + touch timestamp + +-testdirs: libdns.@A@ ++testdirs: libdns-pkcs11.@A@ + + installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} + + install:: timestamp installdirs +- ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libdns.@A@ ${DESTDIR}${libdir} ++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libdns-pkcs11.@A@ ${DESTDIR}${libdir} + + uninstall:: +- ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${libdir}/libdns.@A@ ++ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${libdir}/libdns-pkcs11.@A@ + + clean distclean:: +- rm -f libdns.@A@ timestamp ++ rm -f libdns-pkcs11.@A@ timestamp + rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h + rm -f include/dns/rdatastruct.h + rm -f dnstap.pb-c.c dnstap.pb-c.h include/dns/dnstap.pb-c.h +diff --git a/lib/isc-pkcs11/Makefile.in b/lib/isc-pkcs11/Makefile.in +index ba53ef1..d1f1771 100644 +--- a/lib/isc-pkcs11/Makefile.in ++++ b/lib/isc-pkcs11/Makefile.in +@@ -23,8 +23,8 @@ CINCLUDES = -I${srcdir}/unix/include \ + -I${srcdir}/@ISC_THREAD_DIR@/include \ + -I${srcdir}/@ISC_ARCH_DIR@/include \ + -I./include \ +- -I${srcdir}/include ${DNS_INCLUDES} @ISC_OPENSSL_INC@ +-CDEFINES = @CRYPTO@ -DPK11_LIB_LOCATION=\"${PROVIDER}\" ++ -I${srcdir}/include ${DNS_PKCS11_INCLUDES} ++CDEFINES = @CRYPTO_PK11@ -DPK11_LIB_LOCATION=\"${PROVIDER}\" + CWARNINGS = + + # Alphabetically +@@ -107,40 +107,40 @@ version.@O@: version.c + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +-libisc.@SA@: ${OBJS} ${SYMTBLOBJS} ++libisc-pkcs11.@SA@: ${OBJS} ${SYMTBLOBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} ${SYMTBLOBJS} + ${RANLIB} $@ + +-libisc-nosymtbl.@SA@: ${OBJS} ++libisc-pkcs11-nosymtbl.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +-libisc.la: ${OBJS} ${SYMTBLOBJS} ++libisc-pkcs11.la: ${OBJS} ${SYMTBLOBJS} + ${LIBTOOL_MODE_LINK} \ +- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la -rpath ${libdir} \ ++ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-pkcs11.la -rpath ${libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${SYMTBLOBJS} ${LIBS} + +-libisc-nosymtbl.la: ${OBJS} ++libisc-pkcs11-nosymtbl.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ +- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-nosymtbl.la -rpath ${libdir} \ ++ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-pkcs11-nosymtbl.la -rpath ${libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${LIBS} + +-timestamp: libisc.@A@ libisc-nosymtbl.@A@ ++timestamp: libisc-pkcs11.@A@ libisc-pkcs11-nosymtbl.@A@ + touch timestamp + +-testdirs: libisc.@A@ libisc-nosymtbl.@A@ ++testdirs: libisc-pkcs11.@A@ libisc-pkcs11-nosymtbl.@A@ + + installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} + + install:: timestamp installdirs +- ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libisc.@A@ ${DESTDIR}${libdir} ++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libisc-pkcs11.@A@ ${DESTDIR}${libdir} + + uninstall:: +- ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${libdir}/libisc.@A@ ++ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${libdir}/libisc-pkcs11.@A@ + + clean distclean:: +- rm -f libisc.@A@ libisc-nosymtbl.@A@ libisc.la \ +- libisc-nosymtbl.la timestamp ++ rm -f libisc-pkcs11.@A@ libisc-pkcs11-nosymtbl.@A@ libisc-pkcs11.la \ ++ libisc-pkcs11-nosymtbl.la timestamp +diff --git a/make/includes.in b/make/includes.in +index fa86ad1..3cfbe9f 100644 +--- a/make/includes.in ++++ b/make/includes.in +@@ -43,3 +43,13 @@ BIND9_INCLUDES = @BIND9_BIND9_BUILDINCLUDE@ \ + + TEST_INCLUDES = \ + -I${top_srcdir}/lib/tests/include ++ ++ISC_PKCS11_INCLUDES = @BIND9_ISC_BUILDINCLUDE@ \ ++ -I${top_srcdir}/lib/isc-pkcs11 \ ++ -I${top_srcdir}/lib/isc-pkcs11/include \ ++ -I${top_srcdir}/lib/isc-pkcs11/unix/include \ ++ -I${top_srcdir}/lib/isc-pkcs11/@ISC_THREAD_DIR@/include \ ++ -I${top_srcdir}/lib/isc-pkcs11/@ISC_ARCH_DIR@/include ++ ++DNS_PKCS11_INCLUDES = @BIND9_DNS_BUILDINCLUDE@ \ ++ -I${top_srcdir}/lib/dns-pkcs11/include diff --git a/SOURCES/bind-9.10-sdb.patch b/SOURCES/bind-9.10-sdb.patch new file mode 100644 index 0000000..7874a5c --- /dev/null +++ b/SOURCES/bind-9.10-sdb.patch @@ -0,0 +1,309 @@ +diff --git a/bin/Makefile.in b/bin/Makefile.in +index ce7a2da..4e6a824 100644 +--- a/bin/Makefile.in ++++ b/bin/Makefile.in +@@ -11,8 +11,8 @@ srcdir = @srcdir@ + VPATH = @srcdir@ + top_srcdir = @top_srcdir@ + +-SUBDIRS = named named-pkcs11 rndc dig delv dnssec dnssec-pkcs11 tools nsupdate \ +- check confgen @NZD_TOOLS@ @PYTHON_TOOLS@ @PKCS11_TOOLS@ tests ++SUBDIRS = named named-sdb named-pkcs11 rndc dig delv dnssec dnssec-pkcs11 tools nsupdate \ ++ check confgen @NZD_TOOLS@ @PYTHON_TOOLS@ @PKCS11_TOOLS@ sdb_tools tests + TARGETS = + + @BIND9_MAKE_RULES@ +diff --git a/bin/named-sdb/Makefile.in b/bin/named-sdb/Makefile.in +index 6d2bfd1..d3f42e8 100644 +--- a/bin/named-sdb/Makefile.in ++++ b/bin/named-sdb/Makefile.in +@@ -30,10 +30,10 @@ VERSION=@BIND9_VERSION@ + # + # Add database drivers here. + # +-DBDRIVER_OBJS = +-DBDRIVER_SRCS = ++DBDRIVER_OBJS = ldapdb.@O@ pgsqldb.@O@ sqlitedb.@O@ dirdb.@O@ ++DBDRIVER_SRCS = ldapdb.c pgsqldb.c sqlitedb.c dirdb.c + DBDRIVER_INCLUDES = +-DBDRIVER_LIBS = ++DBDRIVER_LIBS = -lldap -llber -lsqlite3 -lpq + + DLZ_DRIVER_DIR = ${top_srcdir}/contrib/dlz/drivers + +@@ -79,7 +79,7 @@ NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ + + SUBDIRS = unix + +-TARGETS = named@EXEEXT@ lwresd@EXEEXT@ ++TARGETS = named-sdb@EXEEXT@ + + GEOIPLINKOBJS = geoip.@O@ + +@@ -146,7 +146,7 @@ server.@O@: server.c + -DPRODUCT=\"${PRODUCT}\" \ + -DVERSION=\"${VERSION}\" -c ${srcdir}/server.c + +-named@EXEEXT@: ${OBJS} ${DEPLIBS} ++named-sdb@EXEEXT@: ${OBJS} ${DEPLIBS} + export MAKE_SYMTABLE="yes"; \ + export BASEOBJS="${OBJS} ${UOBJS}"; \ + ${FINALBUILDCMD} +@@ -173,8 +173,6 @@ statschannel.@O@: bind9.xsl.h + + installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} +- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5 +- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + + install-man5: named.conf.5 + ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man5 +@@ -184,16 +182,11 @@ install-man8: named.8 lwresd.8 + + install-man: install-man5 install-man8 + +-install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs install-man +- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir} +- (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@) ++install:: ${TARGETS} installdirs ++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-sdb@EXEEXT@ ${DESTDIR}${sbindir} + + uninstall:: +- rm -f ${DESTDIR}${mandir}/man5/named.conf.5 +- rm -f ${DESTDIR}${mandir}/man8/lwresd.8 +- rm -f ${DESTDIR}${mandir}/man8/named.8 +- rm -f ${DESTDIR}${sbindir}/lwresd@EXEEXT@ +- ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named@EXEEXT@ ++ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named-sdb@EXEEXT@ + + @DLZ_DRIVER_RULES@ + +diff --git a/bin/named-sdb/main.c b/bin/named-sdb/main.c +index bb639d9..555c4d9 100644 +--- a/bin/named-sdb/main.c ++++ b/bin/named-sdb/main.c +@@ -91,6 +91,10 @@ + * Include header files for database drivers here. + */ + /* #include "xxdb.h" */ ++#include "ldapdb.h" ++#include "pgsqldb.h" ++#include "sqlitedb.h" ++#include "dirdb.h" + + #ifdef CONTRIB_DLZ + /* +@@ -1061,6 +1065,11 @@ setup(void) { + ns_main_earlyfatal("isc_app_start() failed: %s", + isc_result_totext(result)); + ++ ldapdb_clear(); ++ pgsqldb_clear(); ++ dirdb_clear(); ++ sqlitedb_clear(); ++ + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, + ISC_LOG_NOTICE, "starting %s %s%s%s ", + ns_g_product, ns_g_version, +@@ -1261,6 +1270,75 @@ setup(void) { + isc_result_totext(result)); + #endif + ++ result = ldapdb_init(); ++ if (result != ISC_R_SUCCESS) ++ { ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_ERROR, ++ "SDB ldap module initialisation failed: %s.", ++ isc_result_totext(result) ++ ); ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_ERROR, ++ "SDB ldap zone database will be unavailable." ++ ); ++ }else ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_NOTICE, "SDB ldap zone database module loaded." ++ ); ++ ++ result = pgsqldb_init(); ++ if (result != ISC_R_SUCCESS) ++ { ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_ERROR, ++ "SDB pgsql module initialisation failed: %s.", ++ isc_result_totext(result) ++ ); ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_ERROR, ++ "SDB pgsql zone database will be unavailable." ++ ); ++ }else ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_NOTICE, "SDB postgreSQL DB zone database module loaded." ++ ); ++ ++ result = sqlitedb_init(); ++ if (result != ISC_R_SUCCESS) ++ { ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_ERROR, ++ "SDB sqlite3 module initialisation failed: %s.", ++ isc_result_totext(result) ++ ); ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_ERROR, ++ "SDB sqlite3 zone database will be unavailable." ++ ); ++ }else ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_NOTICE, "SDB sqlite3 DB zone database module loaded." ++ ); ++ ++ result = dirdb_init(); ++ if (result != ISC_R_SUCCESS) ++ { ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_ERROR, ++ "SDB directory DB module initialisation failed: %s.", ++ isc_result_totext(result) ++ ); ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_ERROR, ++ "SDB directory DB zone database will be unavailable." ++ ); ++ }else ++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ++ ISC_LOG_NOTICE, "SDB directory DB zone database module loaded." ++ ); ++ ++ + ns_server_create(ns_g_mctx, &ns_g_server); + + #ifdef HAVE_LIBSECCOMP +@@ -1303,6 +1381,11 @@ cleanup(void) { + + dns_name_destroy(); + ++ ldapdb_clear(); ++ pgsqldb_clear(); ++ sqlitedb_clear(); ++ dirdb_clear(); ++ + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, + ISC_LOG_NOTICE, "exiting"); + ns_log_shutdown(); +diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in +index 6d2bfd1..86f8587 100644 +--- a/bin/named/Makefile.in ++++ b/bin/named/Makefile.in +@@ -45,9 +45,9 @@ DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@ + CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ + ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ + ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ +- ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ ++ @DST_OPENSSL_INC@ + +-CDEFINES = @CONTRIB_DLZ@ @CRYPTO@ ++CDEFINES = @CRYPTO@ + + CWARNINGS = + +@@ -71,11 +71,11 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ + + LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ + ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ +- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ ++ @LIBS@ + + NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ + ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \ +- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ ++ @LIBS@ + + SUBDIRS = unix + +@@ -90,8 +90,7 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ + tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ + zoneconf.@O@ \ + lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \ +- lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \ +- ${DLZDRIVER_OBJS} ${DBDRIVER_OBJS} ++ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ + + UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ + +@@ -106,8 +105,7 @@ SRCS = builtin.c client.c config.c control.c \ + tkeyconf.c tsigconf.c update.c xfrout.c \ + zoneconf.c \ + lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ +- lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \ +- ${DLZDRIVER_SRCS} ${DBDRIVER_SRCS} ++ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c + + MANPAGES = named.8 lwresd.8 named.conf.5 + +@@ -195,7 +193,5 @@ uninstall:: + rm -f ${DESTDIR}${sbindir}/lwresd@EXEEXT@ + ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/named@EXEEXT@ + +-@DLZ_DRIVER_RULES@ +- + named-symtbl.@O@: named-symtbl.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c named-symtbl.c +diff --git a/bin/sdb_tools/Makefile.in b/bin/sdb_tools/Makefile.in +index c7e0868..95ab742 100644 +--- a/bin/sdb_tools/Makefile.in ++++ b/bin/sdb_tools/Makefile.in +@@ -32,11 +32,11 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ + LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ + ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} ${DBDRIVER_LIBS} @LIBS@ + +-TARGETS = zone2ldap@EXEEXT@ zonetodb@EXEEXT@ ++TARGETS = zone2ldap@EXEEXT@ zonetodb@EXEEXT@ zone2sqlite@EXEEXT@ + +-OBJS = zone2ldap.@O@ zonetodb.@O@ ++OBJS = zone2ldap.@O@ zonetodb.@O@ zone2sqlite.@O@ + +-SRCS = zone2ldap.c zonetodb.c ++SRCS = zone2ldap.c zonetodb.c zone2sqlite.c + + MANPAGES = zone2ldap.1 + +@@ -50,6 +50,9 @@ zone2ldap@EXEEXT@: zone2ldap.@O@ ${DEPLIBS} + zonetodb@EXEEXT@: zonetodb.@O@ ${DEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ zonetodb.@O@ -lpq ${LIBS} + ++zone2sqlite@EXEEXT@: zone2sqlite.@O@ ${DEPLIBS} ++ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ zone2sqlite.@O@ -lsqlite3 -lssl ${LIBS} ++ + clean distclean manclean maintainer-clean:: + rm -f ${TARGETS} ${OBJS} + +@@ -60,4 +63,5 @@ installdirs: + install:: ${TARGETS} installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} zone2ldap@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} zonetodb@EXEEXT@ ${DESTDIR}${sbindir} ++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} zone2sqlite@EXEEXT@ ${DESTDIR}${sbindir} + ${INSTALL_DATA} ${srcdir}/zone2ldap.1 ${DESTDIR}${mandir}/man1/zone2ldap.1 +diff --git a/configure.in b/configure.in +index 62536a6..f571a4f 100644 +--- a/configure.in ++++ b/configure.in +@@ -5445,6 +5445,8 @@ AC_CONFIG_FILES([ + bin/named/unix/Makefile + bin/named-pkcs11/Makefile + bin/named-pkcs11/unix/Makefile ++ bin/named-sdb/Makefile ++ bin/named-sdb/unix/Makefile + bin/nsupdate/Makefile + bin/pkcs11/Makefile + bin/python/Makefile +@@ -5469,6 +5471,7 @@ AC_CONFIG_FILES([ + bin/python/isc/tests/dnskey_test.py + bin/python/isc/tests/policy_test.py + bin/rndc/Makefile ++ bin/sdb_tools/Makefile + bin/tests/Makefile + bin/tests/headerdep_test.sh + bin/tests/optional/Makefile diff --git a/SOURCES/bind-9.10-use-of-strlcat.patch b/SOURCES/bind-9.10-use-of-strlcat.patch new file mode 100644 index 0000000..2a39916 --- /dev/null +++ b/SOURCES/bind-9.10-use-of-strlcat.patch @@ -0,0 +1,18 @@ +diff --git a/bin/sdb_tools/zone2ldap.c b/bin/sdb_tools/zone2ldap.c +index d56bc56..99c3314 100644 +--- a/bin/sdb_tools/zone2ldap.c ++++ b/bin/sdb_tools/zone2ldap.c +@@ -817,11 +817,11 @@ build_dn_from_dc_list (char **dc_list, unsigned int ttl, int flag, char *zone) + } + + +- strlcat (dn, tmp, sizeof (dn)); ++ strncat (dn, tmp, sizeof (dn) - strlen (dn)); + } + + sprintf (tmp, "dc=%s", dc_list[0]); +- strlcat (dn, tmp, sizeof (dn)); ++ strncat (dn, tmp, sizeof (dn) - strlen (dn)); + + fflush(NULL); + return dn; diff --git a/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch b/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch new file mode 100644 index 0000000..5647ab6 --- /dev/null +++ b/SOURCES/bind-9.11-CVE-2018-5743-atomic.patch @@ -0,0 +1,131 @@ +From 94e08314024c812063bf99bd191a46265a2ba49f Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Wed, 24 Apr 2019 21:10:26 +0200 +Subject: [PATCH] Missing atomic fix to original CVE patch + +--- + bin/named/client.c | 18 +++++++----------- + bin/named/include/named/interfacemgr.h | 5 +++-- + bin/named/interfacemgr.c | 7 +++++-- + 3 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/bin/named/client.c b/bin/named/client.c +index 3ada6e9..d3bf47d 100644 +--- a/bin/named/client.c ++++ b/bin/named/client.c +@@ -405,12 +405,10 @@ tcpconn_detach(ns_client_t *client) { + static void + mark_tcp_active(ns_client_t *client, isc_boolean_t active) { + if (active && !client->tcpactive) { +- isc_atomic_xadd(&client->interface->ntcpactive, 1); ++ isc_refcount_increment0(&client->interface->ntcpactive, NULL); + client->tcpactive = active; + } else if (!active && client->tcpactive) { +- uint32_t old = +- isc_atomic_xadd(&client->interface->ntcpactive, -1); +- INSIST(old > 0); ++ isc_refcount_decrement(&client->interface->ntcpactive, NULL); + client->tcpactive = active; + } + } +@@ -557,7 +555,7 @@ exit_check(ns_client_t *client) { + if (client->mortal && TCP_CLIENT(client) && + client->newstate != NS_CLIENTSTATE_FREED && + !ns_g_clienttest && +- isc_atomic_xadd(&client->interface->ntcpaccepting, 0) == 0) ++ isc_refcount_current(&client->interface->ntcpaccepting) == 0) + { + /* Nobody else is accepting */ + client->mortal = ISC_FALSE; +@@ -3321,7 +3319,6 @@ client_newconn(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + ns_client_t *client = event->ev_arg; + isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; +- uint32_t old; + + REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN); + REQUIRE(NS_CLIENT_VALID(client)); +@@ -3341,8 +3338,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { + INSIST(client->naccepts == 1); + client->naccepts--; + +- old = isc_atomic_xadd(&client->interface->ntcpaccepting, -1); +- INSIST(old > 0); ++ isc_refcount_decrement(&client->interface->ntcpaccepting, NULL); + + /* + * We must take ownership of the new socket before the exit +@@ -3473,8 +3469,8 @@ client_accept(ns_client_t *client) { + * quota is tcp-clients plus the number of listening + * interfaces plus 1.) + */ +- exit = (isc_atomic_xadd(&client->interface->ntcpactive, 0) > +- (client->tcpactive ? 1 : 0)); ++ exit = (isc_refcount_current(&client->interface->ntcpactive) > ++ (client->tcpactive ? 1U : 0U)); + if (exit) { + client->newstate = NS_CLIENTSTATE_INACTIVE; + (void)exit_check(client); +@@ -3532,7 +3528,7 @@ client_accept(ns_client_t *client) { + * listening for connections itself to prevent the interface + * going dead. + */ +- isc_atomic_xadd(&client->interface->ntcpaccepting, 1); ++ isc_refcount_increment0(&client->interface->ntcpaccepting, NULL); + } + + static void +diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h +index d9ac90f..aa21049 100644 +--- a/bin/named/include/named/interfacemgr.h ++++ b/bin/named/include/named/interfacemgr.h +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #include + +@@ -73,11 +74,11 @@ struct ns_interface { + /*%< UDP dispatchers. */ + isc_socket_t * tcpsocket; /*%< TCP socket. */ + isc_dscp_t dscp; /*%< "listen-on" DSCP value */ +- int32_t ntcpaccepting; /*%< Number of clients ++ isc_refcount_t ntcpaccepting; /*%< Number of clients + ready to accept new + TCP connections on this + interface */ +- int32_t ntcpactive; /*%< Number of clients ++ isc_refcount_t ntcpactive; /*%< Number of clients + servicing TCP queries + (whether accepting or + connected) */ +diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c +index 96c080b..2ce97bb 100644 +--- a/bin/named/interfacemgr.c ++++ b/bin/named/interfacemgr.c +@@ -384,8 +384,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, + * connections will be handled in parallel even though there is + * only one client initially. + */ +- ifp->ntcpaccepting = 0; +- ifp->ntcpactive = 0; ++ isc_refcount_init(&ifp->ntcpaccepting, 0); ++ isc_refcount_init(&ifp->ntcpactive, 0); + + ifp->nudpdispatch = 0; + +@@ -616,6 +616,9 @@ ns_interface_destroy(ns_interface_t *ifp) { + + ns_interfacemgr_detach(&ifp->mgr); + ++ isc_refcount_destroy(&ifp->ntcpactive); ++ isc_refcount_destroy(&ifp->ntcpaccepting); ++ + ifp->magic = 0; + isc_mem_put(mctx, ifp, sizeof(*ifp)); + } +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-CVE-2018-5743.patch b/SOURCES/bind-9.11-CVE-2018-5743.patch new file mode 100644 index 0000000..665e2b2 --- /dev/null +++ b/SOURCES/bind-9.11-CVE-2018-5743.patch @@ -0,0 +1,868 @@ +From b2929ff50a7676563177bc52a372ddcae48cb002 Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Wed, 24 Apr 2019 20:09:07 +0200 +Subject: [PATCH] 5200. [security] tcp-clients settings could be + exceeded in some cases, which could lead to + exhaustion of file descriptors. (CVE-2018-5743) [GL + #615] + +--- + bin/named/client.c | 421 +++++++++++++++++++------ + bin/named/include/named/client.h | 13 +- + bin/named/include/named/interfacemgr.h | 13 +- + bin/named/interfacemgr.c | 9 +- + lib/isc/include/isc/quota.h | 7 + + lib/isc/quota.c | 33 +- + 6 files changed, 385 insertions(+), 111 deletions(-) + +diff --git a/bin/named/client.c b/bin/named/client.c +index b7d8a98..e1acaf1 100644 +--- a/bin/named/client.c ++++ b/bin/named/client.c +@@ -243,7 +243,7 @@ static void ns_client_dumpmessage(ns_client_t *client, const char *reason); + static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, + dns_dispatch_t *disp, isc_boolean_t tcp); + static isc_result_t get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, +- isc_socket_t *sock); ++ isc_socket_t *sock, ns_client_t *oldclient); + static inline isc_boolean_t + allowed(isc_netaddr_t *addr, dns_name_t *signer, isc_netaddr_t *ecs_addr, + isc_uint8_t ecs_addrlen, isc_uint8_t *ecs_scope, dns_acl_t *acl); +@@ -295,6 +295,119 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) { + } + } + ++/*% ++ * Allocate a reference-counted object that will maintain a single pointer to ++ * the (also reference-counted) TCP client quota, shared between all the ++ * clients processing queries on a single TCP connection, so that all ++ * clients sharing the one socket will together consume only one slot in ++ * the 'tcp-clients' quota. ++ */ ++static isc_result_t ++tcpconn_init(ns_client_t *client, isc_boolean_t force) { ++ isc_result_t result; ++ isc_quota_t *quota = NULL; ++ ns_tcpconn_t *tconn = NULL; ++ ++ REQUIRE(client->tcpconn == NULL); ++ ++ /* ++ * Try to attach to the quota first, so we won't pointlessly ++ * allocate memory for a tcpconn object if we can't get one. ++ */ ++ if (force) { ++ result = isc_quota_force(&ns_g_server->tcpquota, "a); ++ } else { ++ result = isc_quota_attach(&ns_g_server->tcpquota, "a); ++ } ++ if (result != ISC_R_SUCCESS) { ++ return (result); ++ } ++ ++ /* ++ * A global memory context is used for the allocation as different ++ * client structures may have different memory contexts assigned and a ++ * reference counter allocated here might need to be freed by a ++ * different client. The performance impact caused by memory context ++ * contention here is expected to be negligible, given that this code ++ * is only executed for TCP connections. ++ */ ++ tconn = isc_mem_allocate(ns_g_mctx, sizeof(*tconn)); ++ ++ isc_refcount_init(&tconn->refs, 1); ++ tconn->tcpquota = quota; ++ quota = NULL; ++ tconn->pipelined = ISC_FALSE; ++ ++ client->tcpconn = tconn; ++ ++ return (ISC_R_SUCCESS); ++} ++ ++/*% ++ * Increase the count of client structures sharing the TCP connection ++ * that 'source' is associated with; add a pointer to the same tcpconn ++ * to 'target', thus associating it with the same TCP connection. ++ */ ++static void ++tcpconn_attach(ns_client_t *source, ns_client_t *target) { ++ int refs; ++ ++ REQUIRE(source->tcpconn != NULL); ++ REQUIRE(target->tcpconn == NULL); ++ REQUIRE(source->tcpconn->pipelined); ++ ++ isc_refcount_increment(&source->tcpconn->refs, &refs); ++ INSIST(refs > 1); ++ target->tcpconn = source->tcpconn; ++} ++ ++/*% ++ * Decrease the count of client structures sharing the TCP connection that ++ * 'client' is associated with. If this is the last client using this TCP ++ * connection, we detach from the TCP quota and free the tcpconn ++ * object. Either way, client->tcpconn is set to NULL. ++ */ ++static void ++tcpconn_detach(ns_client_t *client) { ++ ns_tcpconn_t *tconn = NULL; ++ int refs; ++ ++ REQUIRE(client->tcpconn != NULL); ++ ++ tconn = client->tcpconn; ++ client->tcpconn = NULL; ++ ++ isc_refcount_decrement(&tconn->refs, &refs); ++ if (refs == 0) { ++ isc_quota_detach(&tconn->tcpquota); ++ isc_mem_free(ns_g_mctx, tconn); ++ } ++} ++ ++/*% ++ * Mark a client as active and increment the interface's 'ntcpactive' ++ * counter, as a signal that there is at least one client servicing ++ * TCP queries for the interface. If we reach the TCP client quota at ++ * some point, this will be used to determine whether a quota overrun ++ * should be permitted. ++ * ++ * Marking the client active with the 'tcpactive' flag ensures proper ++ * accounting, by preventing us from incrementing or decrementing ++ * 'ntcpactive' more than once per client. ++ */ ++static void ++mark_tcp_active(ns_client_t *client, isc_boolean_t active) { ++ if (active && !client->tcpactive) { ++ isc_atomic_xadd(&client->interface->ntcpactive, 1); ++ client->tcpactive = active; ++ } else if (!active && client->tcpactive) { ++ uint32_t old = ++ isc_atomic_xadd(&client->interface->ntcpactive, -1); ++ INSIST(old > 0); ++ client->tcpactive = active; ++ } ++} ++ + /*% + * Check for a deactivation or shutdown request and take appropriate + * action. Returns ISC_TRUE if either is in progress; in this case +@@ -384,7 +497,8 @@ exit_check(ns_client_t *client) { + INSIST(client->recursionquota == NULL); + + if (NS_CLIENTSTATE_READING == client->newstate) { +- if (!client->pipelined) { ++ INSIST(client->tcpconn != NULL); ++ if (!client->tcpconn->pipelined) { + client_read(client); + client->newstate = NS_CLIENTSTATE_MAX; + return (ISC_TRUE); /* We're done. */ +@@ -402,10 +516,13 @@ exit_check(ns_client_t *client) { + */ + INSIST(client->recursionquota == NULL); + INSIST(client->newstate <= NS_CLIENTSTATE_READY); +- if (client->nreads > 0) ++ ++ if (client->nreads > 0) { + dns_tcpmsg_cancelread(&client->tcpmsg); +- if (client->nreads != 0) { +- /* Still waiting for read cancel completion. */ ++ } ++ ++ /* Still waiting for read cancel completion. */ ++ if (client->nreads > 0) { + return (ISC_TRUE); + } + +@@ -413,14 +530,49 @@ exit_check(ns_client_t *client) { + dns_tcpmsg_invalidate(&client->tcpmsg); + client->tcpmsg_valid = ISC_FALSE; + } ++ ++ /* ++ * Soon the client will be ready to accept a new TCP ++ * connection or UDP request, but we may have enough ++ * clients doing that already. Check whether this client ++ * needs to remain active and allow it go inactive if ++ * not. ++ * ++ * UDP clients always go inactive at this point, but a TCP ++ * client may need to stay active and return to READY ++ * state if no other clients are available to listen ++ * for TCP requests on this interface. ++ * ++ * Regardless, if we're going to FREED state, that means ++ * the system is shutting down and we don't need to ++ * retain clients. ++ */ ++ if (client->mortal && TCP_CLIENT(client) && ++ client->newstate != NS_CLIENTSTATE_FREED && ++ !ns_g_clienttest && ++ isc_atomic_xadd(&client->interface->ntcpaccepting, 0) == 0) ++ { ++ /* Nobody else is accepting */ ++ client->mortal = ISC_FALSE; ++ client->newstate = NS_CLIENTSTATE_READY; ++ } ++ ++ /* ++ * Detach from TCP connection and TCP client quota, ++ * if appropriate. If this is the last reference to ++ * the TCP connection in our pipeline group, the ++ * TCP quota slot will be released. ++ */ ++ if (client->tcpconn) { ++ tcpconn_detach(client); ++ } ++ + if (client->tcpsocket != NULL) { + CTRACE("closetcp"); + isc_socket_detach(&client->tcpsocket); ++ mark_tcp_active(client, ISC_FALSE); + } + +- if (client->tcpquota != NULL) +- isc_quota_detach(&client->tcpquota); +- + if (client->timerset) { + (void)isc_timer_reset(client->timer, + isc_timertype_inactive, +@@ -428,45 +580,26 @@ exit_check(ns_client_t *client) { + client->timerset = ISC_FALSE; + } + +- client->pipelined = ISC_FALSE; +- + client->peeraddr_valid = ISC_FALSE; + + client->state = NS_CLIENTSTATE_READY; +- INSIST(client->recursionquota == NULL); +- +- /* +- * Now the client is ready to accept a new TCP connection +- * or UDP request, but we may have enough clients doing +- * that already. Check whether this client needs to remain +- * active and force it to go inactive if not. +- * +- * UDP clients go inactive at this point, but TCP clients +- * may remain active if we have fewer active TCP client +- * objects than desired due to an earlier quota exhaustion. +- */ +- if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) { +- LOCK(&client->interface->lock); +- if (client->interface->ntcpcurrent < +- client->interface->ntcptarget) +- client->mortal = ISC_FALSE; +- UNLOCK(&client->interface->lock); +- } + + /* + * We don't need the client; send it to the inactive + * queue for recycling. + */ + if (client->mortal) { +- if (client->newstate > NS_CLIENTSTATE_INACTIVE) ++ if (client->newstate > NS_CLIENTSTATE_INACTIVE) { + client->newstate = NS_CLIENTSTATE_INACTIVE; ++ } + } + + if (NS_CLIENTSTATE_READY == client->newstate) { + if (TCP_CLIENT(client)) { + client_accept(client); +- } else ++ } else { + client_udprecv(client); ++ } + client->newstate = NS_CLIENTSTATE_MAX; + return (ISC_TRUE); + } +@@ -478,41 +611,51 @@ exit_check(ns_client_t *client) { + /* + * We are trying to enter the inactive state. + */ +- if (client->naccepts > 0) ++ if (client->naccepts > 0) { + isc_socket_cancel(client->tcplistener, client->task, + ISC_SOCKCANCEL_ACCEPT); ++ } + + /* Still waiting for accept cancel completion. */ +- if (! (client->naccepts == 0)) ++ if (client->naccepts > 0) { + return (ISC_TRUE); ++ } + + /* Accept cancel is complete. */ +- if (client->nrecvs > 0) ++ if (client->nrecvs > 0) { + isc_socket_cancel(client->udpsocket, client->task, + ISC_SOCKCANCEL_RECV); ++ } + + /* Still waiting for recv cancel completion. */ +- if (! (client->nrecvs == 0)) ++ if (client->nrecvs > 0) { + return (ISC_TRUE); ++ } + + /* Still waiting for control event to be delivered */ +- if (client->nctls > 0) ++ if (client->nctls > 0) { + return (ISC_TRUE); +- +- /* Deactivate the client. */ +- if (client->interface) +- ns_interface_detach(&client->interface); ++ } + + INSIST(client->naccepts == 0); + INSIST(client->recursionquota == NULL); +- if (client->tcplistener != NULL) ++ if (client->tcplistener != NULL) { + isc_socket_detach(&client->tcplistener); ++ mark_tcp_active(client, ISC_FALSE); ++ } + +- if (client->udpsocket != NULL) ++ if (client->udpsocket != NULL) { + isc_socket_detach(&client->udpsocket); ++ } + +- if (client->dispatch != NULL) ++ /* Deactivate the client. */ ++ if (client->interface != NULL) { ++ ns_interface_detach(&client->interface); ++ } ++ ++ if (client->dispatch != NULL) { + dns_dispatch_detach(&client->dispatch); ++ } + + client->attributes = 0; + client->mortal = ISC_FALSE; +@@ -537,10 +680,13 @@ exit_check(ns_client_t *client) { + client->newstate = NS_CLIENTSTATE_MAX; + if (!ns_g_clienttest && manager != NULL && + !manager->exiting) ++ { + ISC_QUEUE_PUSH(manager->inactive, client, + ilink); +- if (client->needshutdown) ++ } ++ if (client->needshutdown) { + isc_task_shutdown(client->task); ++ } + return (ISC_TRUE); + } + } +@@ -650,7 +796,7 @@ client_start(isc_task_t *task, isc_event_t *event) { + return; + + if (TCP_CLIENT(client)) { +- if (client->pipelined) { ++ if (client->tcpconn != NULL) { + client_read(client); + } else { + client_accept(client); +@@ -660,7 +806,6 @@ client_start(isc_task_t *task, isc_event_t *event) { + } + } + +- + /*% + * The client's task has received a shutdown event. + */ +@@ -2301,6 +2446,7 @@ client_request(isc_task_t *task, isc_event_t *event) { + client->nrecvs--; + } else { + INSIST(TCP_CLIENT(client)); ++ INSIST(client->tcpconn != NULL); + REQUIRE(event->ev_type == DNS_EVENT_TCPMSG); + REQUIRE(event->ev_sender == &client->tcpmsg); + buffer = &client->tcpmsg.buffer; +@@ -2484,18 +2630,27 @@ client_request(isc_task_t *task, isc_event_t *event) { + /* + * Pipeline TCP query processing. + */ +- if (client->message->opcode != dns_opcode_query) +- client->pipelined = ISC_FALSE; +- if (TCP_CLIENT(client) && client->pipelined) { +- result = isc_quota_reserve(&ns_g_server->tcpquota); +- if (result == ISC_R_SUCCESS) +- result = ns_client_replace(client); ++ if (TCP_CLIENT(client) && ++ client->message->opcode != dns_opcode_query) ++ { ++ client->tcpconn->pipelined = ISC_FALSE; ++ } ++ if (TCP_CLIENT(client) && client->tcpconn->pipelined) { ++ /* ++ * We're pipelining. Replace the client; the ++ * replacement can read the TCP socket looking ++ * for new messages and this one can process the ++ * current message asynchronously. ++ * ++ * There will now be at least three clients using this ++ * TCP socket - one accepting new connections, ++ * one reading an existing connection to get new ++ * messages, and one answering the message already ++ * received. ++ */ ++ result = ns_client_replace(client); + if (result != ISC_R_SUCCESS) { +- ns_client_log(client, NS_LOGCATEGORY_CLIENT, +- NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, +- "no more TCP clients(read): %s", +- isc_result_totext(result)); +- client->pipelined = ISC_FALSE; ++ client->tcpconn->pipelined = ISC_FALSE; + } + } + +@@ -3051,8 +3206,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { + client->signer = NULL; + dns_name_init(&client->signername, NULL); + client->mortal = ISC_FALSE; +- client->pipelined = ISC_FALSE; +- client->tcpquota = NULL; ++ client->tcpconn = NULL; + client->recursionquota = NULL; + client->interface = NULL; + client->peeraddr_valid = ISC_FALSE; +@@ -3062,6 +3216,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { + client->filter_aaaa = dns_aaaa_ok; + #endif + client->needshutdown = ns_g_clienttest; ++ client->tcpactive = ISC_FALSE; + + ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL, + NS_EVENT_CLIENTCONTROL, client_start, client, client, +@@ -3156,9 +3311,10 @@ client_read(ns_client_t *client) { + + static void + client_newconn(isc_task_t *task, isc_event_t *event) { ++ isc_result_t result; + ns_client_t *client = event->ev_arg; + isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; +- isc_result_t result; ++ uint32_t old; + + REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN); + REQUIRE(NS_CLIENT_VALID(client)); +@@ -3168,13 +3324,18 @@ client_newconn(isc_task_t *task, isc_event_t *event) { + + INSIST(client->state == NS_CLIENTSTATE_READY); + ++ /* ++ * The accept() was successful and we're now establishing a new ++ * connection. We need to make note of it in the client and ++ * interface objects so client objects can do the right thing ++ * when going inactive in exit_check() (see comments in ++ * client_accept() for details). ++ */ + INSIST(client->naccepts == 1); + client->naccepts--; + +- LOCK(&client->interface->lock); +- INSIST(client->interface->ntcpcurrent > 0); +- client->interface->ntcpcurrent--; +- UNLOCK(&client->interface->lock); ++ old = isc_atomic_xadd(&client->interface->ntcpaccepting, -1); ++ INSIST(old > 0); + + /* + * We must take ownership of the new socket before the exit +@@ -3207,6 +3368,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { + NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), + "accept failed: %s", + isc_result_totext(nevent->result)); ++ tcpconn_detach(client); + } + + if (exit_check(client)) +@@ -3244,20 +3406,13 @@ client_newconn(isc_task_t *task, isc_event_t *event) { + * telnetting to port 53 (once per CPU) will + * deny service to legitimate TCP clients. + */ +- client->pipelined = ISC_FALSE; +- result = isc_quota_attach(&ns_g_server->tcpquota, +- &client->tcpquota); +- if (result == ISC_R_SUCCESS) +- result = ns_client_replace(client); +- if (result != ISC_R_SUCCESS) { +- ns_client_log(client, NS_LOGCATEGORY_CLIENT, +- NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, +- "no more TCP clients(accept): %s", +- isc_result_totext(result)); +- } else if (ns_g_server->keepresporder == NULL || +- !allowed(&netaddr, NULL, NULL, 0, NULL, +- ns_g_server->keepresporder)) { +- client->pipelined = ISC_TRUE; ++ result = ns_client_replace(client); ++ if (result == ISC_R_SUCCESS && ++ (ns_g_server->keepresporder == NULL || ++ !allowed(&netaddr, NULL, NULL, 0, NULL, ++ ns_g_server->keepresporder))) ++ { ++ client->tcpconn->pipelined = ISC_TRUE; + } + + client_read(client); +@@ -3273,12 +3428,66 @@ client_accept(ns_client_t *client) { + + CTRACE("accept"); + ++ /* ++ * Set up a new TCP connection. This means try to attach to the ++ * TCP client quota (tcp-clients), but fail if we're over quota. ++ */ ++ result = tcpconn_init(client, ISC_FALSE); ++ if (result != ISC_R_SUCCESS) { ++ isc_boolean_t exit; ++ ++ ns_client_log(client, NS_LOGCATEGORY_CLIENT, ++ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, ++ "TCP client quota reached: %s", ++ isc_result_totext(result)); ++ ++ /* ++ * We have exceeded the system-wide TCP client quota. But, ++ * we can't just block this accept in all cases, because if ++ * we did, a heavy TCP load on other interfaces might cause ++ * this interface to be starved, with no clients able to ++ * accept new connections. ++ * ++ * So, we check here to see if any other clients are ++ * already servicing TCP queries on this interface (whether ++ * accepting, reading, or processing). If we find that at ++ * least one client other than this one is active, then ++ * it's okay *not* to call accept - we can let this ++ * client go inactive and another will take over when it's ++ * done. ++ * ++ * If there aren't enough active clients on the interface, ++ * then we can be a little bit flexible about the quota. ++ * We'll allow *one* extra client through to ensure we're ++ * listening on every interface; we do this by setting the ++ * 'force' option to tcpconn_init(). ++ * ++ * (Note: In practice this means that the real TCP client ++ * quota is tcp-clients plus the number of listening ++ * interfaces plus 1.) ++ */ ++ exit = (isc_atomic_xadd(&client->interface->ntcpactive, 0) > ++ (client->tcpactive ? 1 : 0)); ++ if (exit) { ++ client->newstate = NS_CLIENTSTATE_INACTIVE; ++ (void)exit_check(client); ++ return; ++ } ++ ++ result = tcpconn_init(client, ISC_TRUE); ++ RUNTIME_CHECK(result == ISC_R_SUCCESS); ++ } ++ ++ /* ++ * If this client was set up using get_client() or get_worker(), ++ * then TCP is already marked active. However, if it was restarted ++ * from exit_check(), it might not be, so we take care of it now. ++ */ ++ mark_tcp_active(client, ISC_TRUE); ++ + result = isc_socket_accept(client->tcplistener, client->task, + client_newconn, client); + if (result != ISC_R_SUCCESS) { +- UNEXPECTED_ERROR(__FILE__, __LINE__, +- "isc_socket_accept() failed: %s", +- isc_result_totext(result)); + /* + * XXXRTH What should we do? We're trying to accept but + * it didn't work. If we just give up, then TCP +@@ -3286,13 +3495,37 @@ client_accept(ns_client_t *client) { + * + * For now, we just go idle. + */ ++ UNEXPECTED_ERROR(__FILE__, __LINE__, ++ "isc_socket_accept() failed: %s", ++ isc_result_totext(result)); ++ ++ tcpconn_detach(client); ++ mark_tcp_active(client, ISC_FALSE); + return; + } ++ ++ /* ++ * The client's 'naccepts' counter indicates that this client has ++ * called accept() and is waiting for a new connection. It should ++ * never exceed 1. ++ */ + INSIST(client->naccepts == 0); + client->naccepts++; +- LOCK(&client->interface->lock); +- client->interface->ntcpcurrent++; +- UNLOCK(&client->interface->lock); ++ ++ /* ++ * The interface's 'ntcpaccepting' counter is incremented when ++ * any client calls accept(), and decremented in client_newconn() ++ * once the connection is established. ++ * ++ * When the client object is shutting down after handling a TCP ++ * request (see exit_check()), if this value is at least one, that ++ * means another client has called accept() and is waiting to ++ * establish the next connection. That means the client may be ++ * be free to become inactive; otherwise it may need to start ++ * listening for connections itself to prevent the interface ++ * going dead. ++ */ ++ isc_atomic_xadd(&client->interface->ntcpaccepting, 1); + } + + static void +@@ -3363,15 +3596,17 @@ ns_client_replace(ns_client_t *client) { + REQUIRE(client->manager != NULL); + + tcp = TCP_CLIENT(client); +- if (tcp && client->pipelined) { ++ if (tcp && client->tcpconn != NULL && client->tcpconn->pipelined) { + result = get_worker(client->manager, client->interface, +- client->tcpsocket); ++ client->tcpsocket, client); + } else { + result = get_client(client->manager, client->interface, + client->dispatch, tcp); ++ + } +- if (result != ISC_R_SUCCESS) ++ if (result != ISC_R_SUCCESS) { + return (result); ++ } + + /* + * The responsibility for listening for new requests is hereby +@@ -3557,9 +3792,12 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, + client->dscp = ifp->dscp; + + if (tcp) { ++ mark_tcp_active(client, ISC_TRUE); ++ + client->attributes |= NS_CLIENTATTR_TCP; + isc_socket_attach(ifp->tcpsocket, + &client->tcplistener); ++ + } else { + isc_socket_t *sock; + +@@ -3577,7 +3815,8 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, + } + + static isc_result_t +-get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock) ++get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock, ++ ns_client_t *oldclient) + { + isc_result_t result = ISC_R_SUCCESS; + isc_event_t *ev; +@@ -3585,6 +3824,7 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock) + MTRACE("get worker"); + + REQUIRE(manager != NULL); ++ REQUIRE(oldclient != NULL); + + if (manager->exiting) + return (ISC_R_SHUTTINGDOWN); +@@ -3617,14 +3857,15 @@ get_worker(ns_clientmgr_t *manager, ns_interface_t *ifp, isc_socket_t *sock) + ns_interface_attach(ifp, &client->interface); + client->newstate = client->state = NS_CLIENTSTATE_WORKING; + INSIST(client->recursionquota == NULL); +- client->tcpquota = &ns_g_server->tcpquota; + + client->dscp = ifp->dscp; + + client->attributes |= NS_CLIENTATTR_TCP; +- client->pipelined = ISC_TRUE; + client->mortal = ISC_TRUE; + ++ tcpconn_attach(oldclient, client); ++ mark_tcp_active(client, ISC_TRUE); ++ + isc_socket_attach(ifp->tcpsocket, &client->tcplistener); + isc_socket_attach(sock, &client->tcpsocket); + isc_socket_setname(client->tcpsocket, "worker-tcp", NULL); +diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h +index 262b906..0f54d22 100644 +--- a/bin/named/include/named/client.h ++++ b/bin/named/include/named/client.h +@@ -9,8 +9,6 @@ + * information regarding copyright ownership. + */ + +-/* $Id: client.h,v 1.96 2012/01/31 23:47:31 tbox Exp $ */ +- + #ifndef NAMED_CLIENT_H + #define NAMED_CLIENT_H 1 + +@@ -77,6 +75,13 @@ + *** Types + ***/ + ++/*% reference-counted TCP connection object */ ++typedef struct ns_tcpconn { ++ isc_refcount_t refs; ++ isc_quota_t *tcpquota; ++ isc_boolean_t pipelined; ++} ns_tcpconn_t; ++ + /*% nameserver client structure */ + struct ns_client { + unsigned int magic; +@@ -91,6 +96,7 @@ struct ns_client { + int nupdates; + int nctls; + int references; ++ isc_boolean_t tcpactive; + isc_boolean_t needshutdown; /* + * Used by clienttest to get + * the client to go from +@@ -129,8 +135,7 @@ struct ns_client { + dns_name_t signername; /*%< [T]SIG key name */ + dns_name_t * signer; /*%< NULL if not valid sig */ + isc_boolean_t mortal; /*%< Die after handling request */ +- isc_boolean_t pipelined; /*%< TCP queries not in sequence */ +- isc_quota_t *tcpquota; ++ ns_tcpconn_t *tcpconn; + isc_quota_t *recursionquota; + ns_interface_t *interface; + +diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h +index 36870f3..d9ac90f 100644 +--- a/bin/named/include/named/interfacemgr.h ++++ b/bin/named/include/named/interfacemgr.h +@@ -9,8 +9,6 @@ + * information regarding copyright ownership. + */ + +-/* $Id: interfacemgr.h,v 1.35 2011/07/28 23:47:58 tbox Exp $ */ +- + #ifndef NAMED_INTERFACEMGR_H + #define NAMED_INTERFACEMGR_H 1 + +@@ -75,9 +73,14 @@ struct ns_interface { + /*%< UDP dispatchers. */ + isc_socket_t * tcpsocket; /*%< TCP socket. */ + isc_dscp_t dscp; /*%< "listen-on" DSCP value */ +- int ntcptarget; /*%< Desired number of concurrent +- TCP accepts */ +- int ntcpcurrent; /*%< Current ditto, locked */ ++ int32_t ntcpaccepting; /*%< Number of clients ++ ready to accept new ++ TCP connections on this ++ interface */ ++ int32_t ntcpactive; /*%< Number of clients ++ servicing TCP queries ++ (whether accepting or ++ connected) */ + int nudpdispatch; /*%< Number of UDP dispatches */ + ns_clientmgr_t * clientmgr; /*%< Client manager. */ + ISC_LINK(ns_interface_t) link; +diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c +index d8c7188..96c080b 100644 +--- a/bin/named/interfacemgr.c ++++ b/bin/named/interfacemgr.c +@@ -384,8 +384,9 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, + * connections will be handled in parallel even though there is + * only one client initially. + */ +- ifp->ntcptarget = 1; +- ifp->ntcpcurrent = 0; ++ ifp->ntcpaccepting = 0; ++ ifp->ntcpactive = 0; ++ + ifp->nudpdispatch = 0; + + ifp->dscp = -1; +@@ -520,9 +521,7 @@ ns_interface_accepttcp(ns_interface_t *ifp) { + */ + (void)isc_socket_filter(ifp->tcpsocket, "dataready"); + +- result = ns_clientmgr_createclients(ifp->clientmgr, +- ifp->ntcptarget, ifp, +- ISC_TRUE); ++ result = ns_clientmgr_createclients(ifp->clientmgr, 1, ifp, ISC_TRUE); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "TCP ns_clientmgr_createclients(): %s", +diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h +index b9bf598..36c5830 100644 +--- a/lib/isc/include/isc/quota.h ++++ b/lib/isc/include/isc/quota.h +@@ -100,6 +100,13 @@ isc_quota_attach(isc_quota_t *quota, isc_quota_t **p); + * quota if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA). + */ + ++isc_result_t ++isc_quota_force(isc_quota_t *quota, isc_quota_t **p); ++/*%< ++ * Like isc_quota_attach, but will attach '*p' to the quota ++ * even if the hard quota has been exceeded. ++ */ ++ + void + isc_quota_detach(isc_quota_t **p); + /*%< +diff --git a/lib/isc/quota.c b/lib/isc/quota.c +index 3ddff0d..20976a4 100644 +--- a/lib/isc/quota.c ++++ b/lib/isc/quota.c +@@ -74,20 +74,39 @@ isc_quota_release(isc_quota_t *quota) { + UNLOCK("a->lock); + } + +-isc_result_t +-isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) +-{ ++static isc_result_t ++doattach(isc_quota_t *quota, isc_quota_t **p, isc_boolean_t force) { + isc_result_t result; +- INSIST(p != NULL && *p == NULL); ++ REQUIRE(p != NULL && *p == NULL); ++ + result = isc_quota_reserve(quota); +- if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) ++ if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) { ++ *p = quota; ++ } else if (result == ISC_R_QUOTA && force) { ++ /* attach anyway */ ++ LOCK("a->lock); ++ quota->used++; ++ UNLOCK("a->lock); ++ + *p = quota; ++ result = ISC_R_SUCCESS; ++ } ++ + return (result); + } + ++isc_result_t ++isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) { ++ return (doattach(quota, p, ISC_FALSE)); ++} ++ ++isc_result_t ++isc_quota_force(isc_quota_t *quota, isc_quota_t **p) { ++ return (doattach(quota, p, ISC_TRUE)); ++} ++ + void +-isc_quota_detach(isc_quota_t **p) +-{ ++isc_quota_detach(isc_quota_t **p) { + INSIST(p != NULL && *p != NULL); + isc_quota_release(*p); + *p = NULL; +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-CVE-2019-6471.patch b/SOURCES/bind-9.11-CVE-2019-6471.patch new file mode 100644 index 0000000..64f86d5 --- /dev/null +++ b/SOURCES/bind-9.11-CVE-2019-6471.patch @@ -0,0 +1,48 @@ +From 66c074b707318005d50f14910678ba451877a7a6 Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Wed, 19 Jun 2019 12:28:08 +0200 +Subject: [PATCH] Fix CVE-2019-6471 + +5244. [security] Fixed a race condition in dns_dispatch_getnext() + that could cause an assertion failure if a + significant number of incoming packets were + rejected. (CVE-2019-6471) [GL #942] +--- + lib/dns/dispatch.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c +index 321459ebcb..ae5c9c0fc7 100644 +--- a/lib/dns/dispatch.c ++++ b/lib/dns/dispatch.c +@@ -3419,13 +3419,14 @@ dns_dispatch_getnext(dns_dispentry_t *resp, dns_dispatchevent_t **sockevent) { + disp = resp->disp; + REQUIRE(VALID_DISPATCH(disp)); + +- REQUIRE(resp->item_out == ISC_TRUE); +- resp->item_out = ISC_FALSE; +- + ev = *sockevent; + *sockevent = NULL; + + LOCK(&disp->lock); ++ ++ REQUIRE(resp->item_out == ISC_TRUE); ++ resp->item_out = ISC_FALSE; ++ + if (ev->buffer.base != NULL) + free_buffer(disp, ev->buffer.base, ev->buffer.length); + free_devent(disp, ev); +@@ -3570,6 +3571,9 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, + isc_task_send(disp->task[0], &disp->ctlevent); + } + ++/* ++ * disp must be locked. ++ */ + static void + do_cancel(dns_dispatch_t *disp) { + dns_dispatchevent_t *ev; +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-dnssec-lookaside.patch b/SOURCES/bind-9.11-dnssec-lookaside.patch new file mode 100644 index 0000000..8c1b316 --- /dev/null +++ b/SOURCES/bind-9.11-dnssec-lookaside.patch @@ -0,0 +1,49 @@ +From d5ca0a8f5d31dad4e77bdb8316853f703e68b60f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Tue, 29 Jan 2019 21:26:33 +0100 +Subject: [PATCH 4/5] Accept dnssec-lookaside yes; + +Thread it the same way as "auto" value. Print a warning and ignore it. +--- + bin/named/server.c | 3 ++- + lib/bind9/check.c | 8 +++++--- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/bin/named/server.c b/bin/named/server.c +index 0c8939d..93f9417 100644 +--- a/bin/named/server.c ++++ b/bin/named/server.c +@@ -4615,7 +4615,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, + /* If "no", skip; if "auto", log warning */ + if (!strcasecmp(dom, "no")) { + result = ISC_R_NOTFOUND; +- } else if (!strcasecmp(dom, "auto")) { ++ } else if (!strcasecmp(dom, "auto") ++ || !strcasecmp(dom, "yes")) { + /* + * Warning logged by libbind9. + */ +diff --git a/lib/bind9/check.c b/lib/bind9/check.c +index 1a3d534..f075de0 100644 +--- a/lib/bind9/check.c ++++ b/lib/bind9/check.c +@@ -1176,11 +1176,13 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx, + if (!strcasecmp(dlv, "no")) { + continue; + } +- if (!strcasecmp(dlv, "auto")) { ++ if (!strcasecmp(dlv, "auto") ++ || !strcasecmp(dlv, "yes")) { + cfg_obj_log(obj, logctx, + ISC_LOG_WARNING, +- "dnssec-lookaside 'auto' " +- "is no longer supported"); ++ "dnssec-lookaside '%s' " ++ "is no longer supported", ++ dlv); + continue; + } + } +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-ed448-disable.patch b/SOURCES/bind-9.11-ed448-disable.patch new file mode 100644 index 0000000..f3006bf --- /dev/null +++ b/SOURCES/bind-9.11-ed448-disable.patch @@ -0,0 +1,41 @@ +From e1da251de9647872d776b70078556f4e3e21cad8 Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Thu, 21 Feb 2019 12:36:17 +0100 +Subject: [PATCH] Disable autodetected ED448 algorithm support + +Implementation is broken in bind, disabled also in more recent versions. +Makes bin/tests/system/dnssec fail. +--- + configure.in | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/configure.in b/configure.in +index 1397c50..475ab9e 100644 +--- a/configure.in ++++ b/configure.in +@@ -1964,6 +1964,9 @@ int main() { + } + ], + [AC_MSG_RESULT(yes) ++ # ED448 support is broken in BIND ++ # https://gitlab.isc.org/isc-projects/bind9/issues/225 ++ # disable if autodetected, can be enabled by --with-eddsa=all + have_ed448="yes"], + [AC_MSG_RESULT(no) + have_ed448="no"], +@@ -1976,8 +1979,10 @@ int main() { + esac + case $have_ed448 in + yes) +- AC_DEFINE(HAVE_OPENSSL_ED448, 1, +- [Define if your OpenSSL version supports Ed448.]) ++ # ED448 support is broken in BIND ++ # https://gitlab.isc.org/isc-projects/bind9/issues/225 ++ # AC_DEFINE(HAVE_OPENSSL_ED448, 1, ++ # [Define if your OpenSSL version supports Ed448.]) + ;; + *) + ;; +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-export-suffix.patch b/SOURCES/bind-9.11-export-suffix.patch new file mode 100644 index 0000000..e3ba29c --- /dev/null +++ b/SOURCES/bind-9.11-export-suffix.patch @@ -0,0 +1,39 @@ +diff --git a/configure.in b/configure.in +index e6cd6a4..988b0a7 100644 +--- a/configure.in ++++ b/configure.in +@@ -5116,6 +5116,8 @@ AC_SUBST(BUILD_CPPFLAGS) + AC_SUBST(BUILD_LDFLAGS) + AC_SUBST(BUILD_LIBS) + ++AC_SUBST(LIBDIR_SUFFIX) ++ + # + # Commands to run at the end of config.status. + # Don't just put these into configure, it won't work right if somebody +diff --git a/isc-config.sh.in b/isc-config.sh.in +index 110191a..5a64004 100644 +--- a/isc-config.sh.in ++++ b/isc-config.sh.in +@@ -12,16 +12,17 @@ prefix=@prefix@ + exec_prefix=@exec_prefix@ + exec_prefix_set= + includedir=@includedir@ ++libdir_suffix=@LIBDIR_SUFFIX@ + arch=$(uname -m) + + case $arch in + x86_64 | amd64 | sparc64 | s390x | ppc64) +- libdir=/usr/lib64 +- sec_libdir=/usr/lib ++ libdir=/usr/lib64${libdir_suffix} ++ sec_libdir=/usr/lib${libdir_suffix} + ;; + * ) +- libdir=/usr/lib +- sec_libdir=/usr/lib64 ++ libdir=/usr/lib${libdir_suffix} ++ sec_libdir=/usr/lib64${libdir_suffix} + ;; + esac + diff --git a/SOURCES/bind-9.11-fips-code.patch b/SOURCES/bind-9.11-fips-code.patch new file mode 100644 index 0000000..2dccdea --- /dev/null +++ b/SOURCES/bind-9.11-fips-code.patch @@ -0,0 +1,1516 @@ +From fb8665aebd79ea33cb255f578544e1738f5bbb58 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Thu, 2 Aug 2018 23:34:45 +0200 +Subject: [PATCH 1/2] Squashed commit of the following: +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit b49f70ce0575b6b52a71b90fe0376dbf16f92c6b +Author: Petr Menšík +Date: Mon Jan 22 14:12:37 2018 +0100 + + Update system tests to detect MD5 disabled at runtime + +commit 80ceffee4860c24baf70bc9a8653d92731eda2e4 +Author: Petr Menšík +Date: Thu Aug 2 14:53:54 2018 +0200 + + Avoid warning about undefined parameters + +commit e4ad4363e3d1acaac58456117579f02761f38fdc +Author: Petr Menšík +Date: Wed Jun 20 19:31:19 2018 +0200 + + Fix rndc-confgen default algorithm, report true algorithm in usage. + +commit 7e629a351010cb75e0589ec361f720085675998c +Author: Petr Menšík +Date: Fri Feb 23 21:21:30 2018 +0100 + + Cleanup only if initialization was successful + +commit 2101b948c77cbcbe07eb4a1e60f3e693b2245ec6 +Author: Petr Menšík +Date: Mon Feb 5 12:19:28 2018 +0100 + + Ensure dst backend is initialized first even before hmac algorithms. + +commit 7567c7edde7519115a9ae7e20818c835d3eb1ffe +Author: Petr Menšík +Date: Mon Feb 5 12:17:54 2018 +0100 + + Skip initialization of MD5 based algorithms if not available. + +commit 5782137df6b45a6d900d5a1c250c1257227e917a +Author: Petr Menšík +Date: Mon Feb 5 10:21:27 2018 +0100 + + Change secalgs skipping to be more safe + +commit f2d78729898182d2d19d5064de1bec9b66817159 +Author: Petr Menšík +Date: Wed Jan 31 18:26:11 2018 +0100 + + Skip MD5 algorithm also in case of NULL name + +commit 32a2ad4abc7aaca1c257730319ad3c27405d3407 +Author: Petr Menšík +Date: Wed Jan 31 11:38:12 2018 +0100 + + Make MD5 behave like unknown algorithm in TSIG. + +commit 13cd3f704dce568fdf24a567be5802b58ac6007b +Author: Petr Menšík +Date: Tue Nov 28 20:14:37 2017 +0100 + + Select token with most supported functions, instead of demanding it must support all functions + + Initialize PKCS#11 always until successfully initialized + +commit a71df74abdca4fe63bcdf542b81a109cf1f495b4 +Author: Petr Menšík +Date: Mon Jan 22 16:17:44 2018 +0100 + + Handle MD5 unavailability from DST + +commit dd82cb263efa2753d3ee772972726ea08bcc639b +Author: Petr Menšík +Date: Mon Jan 22 14:11:16 2018 +0100 + + Check runtime flag from library and applications, fail gracefully. + +commit c7b2f87f07ecae75b821a908e29f08a42371e32e +Author: Petr Menšík +Date: Mon Jan 22 08:39:08 2018 +0100 + + Modify libraries to use isc_md5_available() if PK11_MD5_DISABLE is not + defined. + TODO: pk11.c should accept slot without MD5 support. + +commit 0b8e470ec636b9e350b5ec3203eb2b4091415fde +Author: Petr Menšík +Date: Mon Jan 22 07:21:04 2018 +0100 + + Add runtime detection whether MD5 is useable. +--- + bin/confgen/keygen.c | 10 ++++- + bin/confgen/rndc-confgen.c | 36 +++++------------- + bin/dig/dig.c | 7 ++-- + bin/dig/dighost.c | 14 +++++-- + bin/dnssec/dnssec-keygen.c | 14 +++++++ + bin/named/config.c | 25 ++++++++++++- + bin/nsupdate/nsupdate.c | 24 +++++++----- + bin/rndc/rndc.c | 3 +- + bin/tests/optional/hash_test.c | 78 ++++++++++++++++++++------------------- + bin/tests/system/tkey/keycreate.c | 3 ++ + bin/tests/system/tkey/keydelete.c | 18 ++++++--- + lib/bind9/check.c | 10 +++++ + lib/dns/dst_api.c | 23 ++++++++---- + lib/dns/dst_internal.h | 3 +- + lib/dns/dst_parse.c | 18 +++++++-- + lib/dns/hmac_link.c | 20 +++------- + lib/dns/opensslrsa_link.c | 6 +++ + lib/dns/pkcs11rsa_link.c | 33 +++++++++++++++-- + lib/dns/rcode.c | 21 ++++++++++- + lib/dns/tests/rsa_test.c | 29 ++++++++------- + lib/dns/tests/tsig_test.c | 1 + + lib/dns/tkey.c | 9 +++++ + lib/dns/tsec.c | 8 +++- + lib/dns/tsig.c | 17 +++++---- + lib/isc/include/isc/md5.h | 3 ++ + lib/isc/md5.c | 59 +++++++++++++++++++++++++++++ + lib/isc/pk11.c | 58 ++++++++++++++++++++--------- + lib/isc/tests/hash_test.c | 9 +++-- + lib/isccc/cc.c | 42 +++++++++++++-------- + 29 files changed, 424 insertions(+), 177 deletions(-) + +diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c +index 453c641dba..11cc54dd46 100644 +--- a/bin/confgen/keygen.c ++++ b/bin/confgen/keygen.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -73,7 +74,7 @@ alg_fromtext(const char *name) { + p = &name[5]; + + #ifndef PK11_MD5_DISABLE +- if (strcasecmp(p, "md5") == 0) ++ if (strcasecmp(p, "md5") == 0 && isc_md5_available()) + return DST_ALG_HMACMD5; + #endif + if (strcasecmp(p, "sha1") == 0) +@@ -132,6 +133,13 @@ generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, + switch (alg) { + #ifndef PK11_MD5_DISABLE + case DST_ALG_HMACMD5: ++ if (isc_md5_available() == ISC_FALSE) { ++ fatal("unsupported algorithm %d\n", alg); ++ } else if (keysize < 1 || keysize > 512) { ++ fatal("keysize %d out of range (must be 1-512)\n", ++ keysize); ++ } ++ break; + #endif + case DST_ALG_HMACSHA1: + case DST_ALG_HMACSHA224: +diff --git a/bin/confgen/rndc-confgen.c b/bin/confgen/rndc-confgen.c +index 2925baf32f..d7d8418073 100644 +--- a/bin/confgen/rndc-confgen.c ++++ b/bin/confgen/rndc-confgen.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -62,7 +63,7 @@ const char *progname; + + isc_boolean_t verbose = ISC_FALSE; + +-const char *keyfile, *keydef; ++const char *keyfile, *keydef, *algdef; + + ISC_PLATFORM_NORETURN_PRE static void + usage(int status) ISC_PLATFORM_NORETURN_POST; +@@ -70,13 +71,12 @@ usage(int status) ISC_PLATFORM_NORETURN_POST; + static void + usage(int status) { + +-#ifndef PK11_MD5_DISABLE + fprintf(stderr, "\ + Usage:\n\ + %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ + [-s addr] [-t chrootdir] [-u user]\n\ + -a: generate just the key clause and write it to keyfile (%s)\n\ +- -A alg: algorithm (default hmac-md5)\n\ ++ -A alg: algorithm (default %s)\n\ + -b bits: from 1 through 512, default 256; total length of the secret\n\ + -c keyfile: specify an alternate key file (requires -a)\n\ + -k keyname: the name as it will be used in named.conf and rndc.conf\n\ +@@ -85,24 +85,7 @@ Usage:\n\ + -s addr: the address to which rndc should connect\n\ + -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ + -u user: set the keyfile owner to \"user\" (requires -a)\n", +- progname, keydef); +-#else +- fprintf(stderr, "\ +-Usage:\n\ +- %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ +-[-s addr] [-t chrootdir] [-u user]\n\ +- -a: generate just the key clause and write it to keyfile (%s)\n\ +- -A alg: algorithm (default hmac-sha256)\n\ +- -b bits: from 1 through 512, default 256; total length of the secret\n\ +- -c keyfile: specify an alternate key file (requires -a)\n\ +- -k keyname: the name as it will be used in named.conf and rndc.conf\n\ +- -p port: the port named will listen on and rndc will connect to\n\ +- -r randomfile: source of random data (use \"keyboard\" for key timing)\n\ +- -s addr: the address to which rndc should connect\n\ +- -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ +- -u user: set the keyfile owner to \"user\" (requires -a)\n", +- progname, keydef); +-#endif ++ progname, keydef, algdef); + + exit (status); + } +@@ -138,13 +121,14 @@ main(int argc, char **argv) { + progname = program; + + keyname = DEFAULT_KEYNAME; +-#ifndef PK11_MD5_DISABLE +- alg = DST_ALG_HMACMD5; +-#else +- alg = DST_ALG_HMACSHA256; +-#endif + serveraddr = DEFAULT_SERVER; + port = DEFAULT_PORT; ++ alg = DST_ALG_HMACSHA256; ++#ifndef PK11_MD5_DISABLE ++ if (isc_md5_available()) ++ alg = DST_ALG_HMACMD5; ++#endif ++ algdef = alg_totext(alg); + + isc_commandline_errprint = ISC_FALSE; + +diff --git a/bin/dig/dig.c b/bin/dig/dig.c +index d4808ada67..9dff7c8ecd 100644 +--- a/bin/dig/dig.c ++++ b/bin/dig/dig.c +@@ -17,6 +17,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -1757,10 +1758,10 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, + ptr = ptr2; + ptr2 = ptr3; + } else { +-#ifndef PK11_MD5_DISABLE +- hmacname = DNS_TSIG_HMACMD5_NAME; +-#else + hmacname = DNS_TSIG_HMACSHA256_NAME; ++#ifndef PK11_MD5_DISABLE ++ if (isc_md5_available()) ++ hmacname = DNS_TSIG_HMACMD5_NAME; + #endif + digestbits = 0; + } +diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c +index ecefc98453..94c428ed30 100644 +--- a/bin/dig/dighost.c ++++ b/bin/dig/dighost.c +@@ -77,6 +77,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1243,9 +1244,10 @@ parse_hmac(const char *hmac) { + digestbits = 0; + + #ifndef PK11_MD5_DISABLE +- if (strcasecmp(buf, "hmac-md5") == 0) { ++ if (strcasecmp(buf, "hmac-md5") == 0 && isc_md5_available()) { + hmacname = DNS_TSIG_HMACMD5_NAME; +- } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { ++ } else if (strncasecmp(buf, "hmac-md5-", 9) == 0 && ++ isc_md5_available()) { + hmacname = DNS_TSIG_HMACMD5_NAME; + digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); + } else +@@ -1365,7 +1367,13 @@ setup_file_key(void) { + switch (dst_key_alg(dstkey)) { + #ifndef PK11_MD5_DISABLE + case DST_ALG_HMACMD5: +- hmacname = DNS_TSIG_HMACMD5_NAME; ++ if (isc_md5_available()) { ++ hmacname = DNS_TSIG_HMACMD5_NAME; ++ } else { ++ printf(";; Couldn't create key %s: bad algorithm\n", ++ keynametext); ++ goto failure; ++ } + break; + #endif + case DST_ALG_HMACSHA1: +diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c +index 6fc3ab0979..fc04356ed4 100644 +--- a/bin/dnssec/dnssec-keygen.c ++++ b/bin/dnssec/dnssec-keygen.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -560,6 +561,19 @@ main(int argc, char **argv) { + "\"-a RSAMD5\"\n"); + INSIST(freeit == NULL); + return (1); ++ } else if (strcasecmp(algname, "HMAC-MD5") == 0) { ++ if (isc_md5_available()) { ++ alg = DST_ALG_HMACMD5; ++ } else { ++ fprintf(stderr, ++ "The use of HMAC-MD5 was disabled\n"); ++ return (1); ++ } ++ } else if (strcasecmp(algname, "RSAMD5") == 0 && ++ isc_md5_available() == ISC_FALSE) { ++ fprintf(stderr, "The use of RSAMD5 was disabled\n"); ++ INSIST(freeit == NULL); ++ return (1); + } else if (strcasecmp(algname, "HMAC-MD5") == 0) { + alg = DST_ALG_HMACMD5; + #else +diff --git a/bin/named/config.c b/bin/named/config.c +index 54bc37fff7..c50f759ddd 100644 +--- a/bin/named/config.c ++++ b/bin/named/config.c +@@ -17,6 +17,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -966,6 +967,21 @@ ns_config_getkeyalgorithm(const char *str, dns_name_t **name, + return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits)); + } + ++static inline int ++algorithms_start() { ++#ifndef PK11_MD5_DISABLE ++ if (isc_md5_available() == ISC_FALSE) { ++ int i = 0; ++ while (algorithms[i].str != NULL && ++ algorithms[i].hmac == hmacmd5) { ++ i++; ++ } ++ return i; ++ } ++#endif ++ return 0; ++} ++ + isc_result_t + ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, + unsigned int *typep, isc_uint16_t *digestbits) +@@ -975,7 +991,7 @@ ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, + isc_uint16_t bits; + isc_result_t result; + +- for (i = 0; algorithms[i].str != NULL; i++) { ++ for (i = algorithms_start(); algorithms[i].str != NULL; i++) { + len = strlen(algorithms[i].str); + if (strncasecmp(algorithms[i].str, str, len) == 0 && + (str[len] == '\0' || +@@ -998,7 +1014,12 @@ ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, + if (name != NULL) { + switch (algorithms[i].hmac) { + #ifndef PK11_MD5_DISABLE +- case hmacmd5: *name = dns_tsig_hmacmd5_name; break; ++ case hmacmd5: ++ if (isc_md5_available()) { ++ *name = dns_tsig_hmacmd5_name; break; ++ } else { ++ return (ISC_R_NOTFOUND); ++ } + #endif + case hmacsha1: *name = dns_tsig_hmacsha1_name; break; + case hmacsha224: *name = dns_tsig_hmacsha224_name; break; +diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c +index 6967b49754..bb5d50038f 100644 +--- a/bin/nsupdate/nsupdate.c ++++ b/bin/nsupdate/nsupdate.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -474,9 +475,10 @@ parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len, + strlcpy(buf, hmacstr, ISC_MIN(len + 1, sizeof(buf))); + + #ifndef PK11_MD5_DISABLE +- if (strcasecmp(buf, "hmac-md5") == 0) { ++ if (strcasecmp(buf, "hmac-md5") == 0 && isc_md5_available()) { + *hmac = DNS_TSIG_HMACMD5_NAME; +- } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { ++ } else if (strncasecmp(buf, "hmac-md5-", 9) == 0 && ++ isc_md5_available()) { + *hmac = DNS_TSIG_HMACMD5_NAME; + result = isc_parse_uint16(&digestbits, &buf[9], 10); + if (result != ISC_R_SUCCESS || digestbits > 128) { +@@ -589,10 +591,10 @@ setup_keystr(void) { + exit(1); + } + } else { +-#ifndef PK11_MD5_DISABLE +- hmacname = DNS_TSIG_HMACMD5_NAME; +-#else + hmacname = DNS_TSIG_HMACSHA256_NAME; ++#ifndef PK11_MD5_DISABLE ++ if (isc_md5_available()) ++ hmacname = DNS_TSIG_HMACMD5_NAME; + #endif + name = keystr; + n = s; +@@ -729,7 +731,8 @@ setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { + switch (dst_key_alg(dstkey)) { + #ifndef PK11_MD5_DISABLE + case DST_ALG_HMACMD5: +- hmacname = DNS_TSIG_HMACMD5_NAME; ++ if (isc_md5_available()) ++ hmacname = DNS_TSIG_HMACMD5_NAME; + break; + #endif + case DST_ALG_HMACSHA1: +@@ -1604,12 +1607,13 @@ evaluate_key(char *cmdline) { + return (STATUS_SYNTAX); + } + namestr = n + 1; +- } else +-#ifndef PK11_MD5_DISABLE +- hmacname = DNS_TSIG_HMACMD5_NAME; +-#else ++ } else { + hmacname = DNS_TSIG_HMACSHA256_NAME; ++#ifndef PK11_MD5_DISABLE ++ if (isc_md5_available()) ++ hmacname = DNS_TSIG_HMACMD5_NAME; + #endif ++ } + + isc_buffer_init(&b, namestr, strlen(namestr)); + isc_buffer_add(&b, strlen(namestr)); +diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c +index 5c29caf86b..617b06b4a1 100644 +--- a/bin/rndc/rndc.c ++++ b/bin/rndc/rndc.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -634,7 +635,7 @@ parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, + algorithmstr = cfg_obj_asstring(algorithmobj); + + #ifndef PK11_MD5_DISABLE +- if (strcasecmp(algorithmstr, "hmac-md5") == 0) ++ if (strcasecmp(algorithmstr, "hmac-md5") == 0 && isc_md5_available()) + algorithm = ISCCC_ALG_HMACMD5; + else + #endif +diff --git a/bin/tests/optional/hash_test.c b/bin/tests/optional/hash_test.c +index bf2891ad4c..b5f0a1c5f5 100644 +--- a/bin/tests/optional/hash_test.c ++++ b/bin/tests/optional/hash_test.c +@@ -90,43 +90,47 @@ main(int argc, char **argv) { + print_digest(s, "sha224", digest, ISC_SHA224_DIGESTLENGTH/4); + + #ifndef PK11_MD5_DISABLE +- s = "abc"; +- isc_md5_init(&md5); +- memmove(buffer, s, strlen(s)); +- isc_md5_update(&md5, buffer, strlen(s)); +- isc_md5_final(&md5, digest); +- print_digest(s, "md5", digest, 4); +- +- /* +- * The 3 HMAC-MD5 examples from RFC2104 +- */ +- s = "Hi There"; +- memset(key, 0x0b, 16); +- isc_hmacmd5_init(&hmacmd5, key, 16); +- memmove(buffer, s, strlen(s)); +- isc_hmacmd5_update(&hmacmd5, buffer, strlen(s)); +- isc_hmacmd5_sign(&hmacmd5, digest); +- print_digest(s, "hmacmd5", digest, 4); +- +- s = "what do ya want for nothing?"; +- strlcpy((char *)key, "Jefe", sizeof(key)); +- isc_hmacmd5_init(&hmacmd5, key, 4); +- memmove(buffer, s, strlen(s)); +- isc_hmacmd5_update(&hmacmd5, buffer, strlen(s)); +- isc_hmacmd5_sign(&hmacmd5, digest); +- print_digest(s, "hmacmd5", digest, 4); +- +- s = "\335\335\335\335\335\335\335\335\335\335" +- "\335\335\335\335\335\335\335\335\335\335" +- "\335\335\335\335\335\335\335\335\335\335" +- "\335\335\335\335\335\335\335\335\335\335" +- "\335\335\335\335\335\335\335\335\335\335"; +- memset(key, 0xaa, 16); +- isc_hmacmd5_init(&hmacmd5, key, 16); +- memmove(buffer, s, strlen(s)); +- isc_hmacmd5_update(&hmacmd5, buffer, strlen(s)); +- isc_hmacmd5_sign(&hmacmd5, digest); +- print_digest(s, "hmacmd5", digest, 4); ++ if (isc_md5_available()) { ++ s = "abc"; ++ isc_md5_init(&md5); ++ memmove(buffer, s, strlen(s)); ++ isc_md5_update(&md5, buffer, strlen(s)); ++ isc_md5_final(&md5, digest); ++ print_digest(s, "md5", digest, 4); ++ ++ /* ++ * The 3 HMAC-MD5 examples from RFC2104 ++ */ ++ s = "Hi There"; ++ memset(key, 0x0b, 16); ++ isc_hmacmd5_init(&hmacmd5, key, 16); ++ memmove(buffer, s, strlen(s)); ++ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s)); ++ isc_hmacmd5_sign(&hmacmd5, digest); ++ print_digest(s, "hmacmd5", digest, 4); ++ ++ s = "what do ya want for nothing?"; ++ strlcpy((char *)key, "Jefe", sizeof(key)); ++ isc_hmacmd5_init(&hmacmd5, key, 4); ++ memmove(buffer, s, strlen(s)); ++ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s)); ++ isc_hmacmd5_sign(&hmacmd5, digest); ++ print_digest(s, "hmacmd5", digest, 4); ++ ++ s = "\335\335\335\335\335\335\335\335\335\335" ++ "\335\335\335\335\335\335\335\335\335\335" ++ "\335\335\335\335\335\335\335\335\335\335" ++ "\335\335\335\335\335\335\335\335\335\335" ++ "\335\335\335\335\335\335\335\335\335\335"; ++ memset(key, 0xaa, 16); ++ isc_hmacmd5_init(&hmacmd5, key, 16); ++ memmove(buffer, s, strlen(s)); ++ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s)); ++ isc_hmacmd5_sign(&hmacmd5, digest); ++ print_digest(s, "hmacmd5", digest, 4); ++ } else { ++ fprintf(stderr, "Skipping disabled MD5 algorithm\n"); ++ } + #endif + + /* +diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c +index 2a0ee94888..489f4390dc 100644 +--- a/bin/tests/system/tkey/keycreate.c ++++ b/bin/tests/system/tkey/keycreate.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -142,6 +143,8 @@ sendquery(isc_task_t *task, isc_event_t *event) { + static char keystr[] = "0123456789ab"; + + isc_event_free(&event); ++ if (isc_md5_available() == ISC_FALSE) ++ CHECK("MD5 was disabled", ISC_R_NOTIMPLEMENTED); + + result = ISC_R_FAILURE; + if (inet_pton(AF_INET, "10.53.0.1", &inaddr) != 1) +diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c +index 7057c318e4..36ee6c7d21 100644 +--- a/bin/tests/system/tkey/keydelete.c ++++ b/bin/tests/system/tkey/keydelete.c +@@ -225,12 +225,18 @@ main(int argc, char **argv) { + result = dst_key_fromnamedfile(keyname, NULL, type, mctx, &dstkey); + CHECK("dst_key_fromnamedfile", result); + #ifndef PK11_MD5_DISABLE +- result = dns_tsigkey_createfromkey(dst_key_name(dstkey), +- DNS_TSIG_HMACMD5_NAME, +- dstkey, ISC_TRUE, NULL, 0, 0, +- mctx, ring, &tsigkey); +- dst_key_free(&dstkey); +- CHECK("dns_tsigkey_createfromkey", result); ++ if (isc_md5_available()) { ++ result = dns_tsigkey_createfromkey(dst_key_name(dstkey), ++ DNS_TSIG_HMACMD5_NAME, ++ dstkey, ISC_TRUE, ++ NULL, 0, 0, ++ mctx, ring, &tsigkey); ++ dst_key_free(&dstkey); ++ CHECK("dns_tsigkey_createfromkey", result); ++ } else { ++ dst_key_free(&dstkey); ++ CHECK("MD5 was disabled", ISC_R_NOTIMPLEMENTED); ++ } + #else + dst_key_free(&dstkey); + CHECK("MD5 was disabled", ISC_R_NOTIMPLEMENTED); +diff --git a/lib/bind9/check.c b/lib/bind9/check.c +index 3da83a7ae2..1a3d534799 100644 +--- a/lib/bind9/check.c ++++ b/lib/bind9/check.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2572,6 +2573,15 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) { + } + + algorithm = cfg_obj_asstring(algobj); ++#ifndef PK11_MD5_DISABLE ++ /* Skip hmac-md5* algorithms */ ++ if (isc_md5_available() == ISC_FALSE && ++ strncasecmp(algorithm, "hmac-md5", 8) == 0) { ++ cfg_obj_log(algobj, logctx, ISC_LOG_ERROR, ++ "disabled algorithm '%s'", algorithm); ++ return (ISC_R_DISABLED); ++ } ++#endif + for (i = 0; algorithms[i].name != NULL; i++) { + len = strlen(algorithms[i].name); + if (strncasecmp(algorithms[i].name, algorithm, len) == 0 && +diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c +index 4f3d6ac55c..dbece0ac56 100644 +--- a/lib/dns/dst_api.c ++++ b/lib/dns/dst_api.c +@@ -190,6 +190,12 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, + dst_result_register(); + + memset(dst_t_func, 0, sizeof(dst_t_func)); ++ ++#ifdef OPENSSL ++ RETERR(dst__openssl_init(engine)); ++#elif PKCS11CRYPTO ++ RETERR(dst__pkcs11_init(mctx, engine)); ++#endif + #ifndef PK11_MD5_DISABLE + RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5])); + #endif +@@ -199,7 +205,6 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, + RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384])); + RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512])); + #ifdef OPENSSL +- RETERR(dst__openssl_init(engine)); + #ifndef PK11_MD5_DISABLE + RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5], + DST_ALG_RSAMD5)); +@@ -233,14 +238,18 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, + RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED448])); + #endif + #elif PKCS11CRYPTO +- RETERR(dst__pkcs11_init(mctx, engine)); + #ifndef PK11_MD5_DISABLE +- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5])); ++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5], ++ DST_ALG_RSAMD5)); + #endif +- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1])); +- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1])); +- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256])); +- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512])); ++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1], ++ DST_ALG_RSASHA1)); ++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1], ++ DST_ALG_NSEC3RSASHA1)); ++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256], ++ DST_ALG_RSASHA256)); ++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512], ++ DST_ALG_RSASHA512)); + #ifndef PK11_DSA_DISABLE + RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_DSA])); + RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); +diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h +index 640519a5ba..deb7ed4e13 100644 +--- a/lib/dns/dst_internal.h ++++ b/lib/dns/dst_internal.h +@@ -245,7 +245,8 @@ isc_result_t dst__hmacsha384_init(struct dst_func **funcp); + isc_result_t dst__hmacsha512_init(struct dst_func **funcp); + isc_result_t dst__opensslrsa_init(struct dst_func **funcp, + unsigned char algorithm); +-isc_result_t dst__pkcs11rsa_init(struct dst_func **funcp); ++isc_result_t dst__pkcs11rsa_init(struct dst_func **funcp, ++ unsigned char algorithm); + #ifndef PK11_DSA_DISABLE + isc_result_t dst__openssldsa_init(struct dst_func **funcp); + isc_result_t dst__pkcs11dsa_init(struct dst_func **funcp); +diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c +index b0e5c895c6..03f2b8ace8 100644 +--- a/lib/dns/dst_parse.c ++++ b/lib/dns/dst_parse.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -393,6 +394,10 @@ check_data(const dst_private_t *priv, const unsigned int alg, + switch (alg) { + #ifndef PK11_MD5_DISABLE + case DST_ALG_RSAMD5: ++ if (isc_md5_available()) ++ return (check_rsa(priv, external)); ++ else ++ return (DST_R_UNSUPPORTEDALG); + #endif + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: +@@ -418,7 +423,10 @@ check_data(const dst_private_t *priv, const unsigned int alg, + return (check_eddsa(priv, external)); + #ifndef PK11_MD5_DISABLE + case DST_ALG_HMACMD5: +- return (check_hmac_md5(priv, old)); ++ if (isc_md5_available()) ++ return (check_hmac_md5(priv, old)); ++ else ++ return (DST_R_UNSUPPORTEDALG); + #endif + case DST_ALG_HMACSHA1: + return (check_hmac_sha(priv, HMACSHA1_NTAGS, alg)); +@@ -637,11 +645,13 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, + } + + #ifdef PK11_MD5_DISABLE +- check = check_data(priv, alg == DST_ALG_RSA ? DST_ALG_RSASHA1 : alg, +- ISC_TRUE, external); ++ if (alg == DST_ALG_RSA) ++ alg = DST_ALG_RSASHA1; + #else +- check = check_data(priv, alg, ISC_TRUE, external); ++ if (isc_md5_available() == ISC_FALSE && alg == DST_ALG_RSA) ++ alg = DST_ALG_RSASHA1; + #endif ++ check = check_data(priv, alg, ISC_TRUE, external); + if (check < 0) { + ret = DST_R_INVALIDPRIVATEKEY; + goto fail; +diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c +index 59aa4705e5..21bfa44450 100644 +--- a/lib/dns/hmac_link.c ++++ b/lib/dns/hmac_link.c +@@ -338,25 +338,17 @@ static dst_func_t hmacmd5_functions = { + + isc_result_t + dst__hmacmd5_init(dst_func_t **funcp) { +-#ifdef HAVE_FIPS_MODE + /* +- * Problems from OpenSSL are likely from FIPS mode ++ * Prevent use of incorrect crypto + */ +- int fips_mode = FIPS_mode(); +- +- if (fips_mode != 0) { +- UNEXPECTED_ERROR(__FILE__, __LINE__, +- "FIPS mode is %d: MD5 is only supported " +- "if the value is 0.\n" +- "Please disable either FIPS mode or MD5.", +- fips_mode); ++ ++#ifndef PK11_MD5_DISABLE ++ if (isc_md5_available() == ISC_FALSE) { ++ /* Intentionally skip initialization */ ++ return (ISC_R_SUCCESS); + } + #endif + +- /* +- * Prevent use of incorrect crypto +- */ +- + RUNTIME_CHECK(isc_md5_check(ISC_FALSE)); + RUNTIME_CHECK(isc_hmacmd5_check(0)); + +diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c +index f4847bbe74..126cebca19 100644 +--- a/lib/dns/opensslrsa_link.c ++++ b/lib/dns/opensslrsa_link.c +@@ -1801,6 +1801,12 @@ dst__opensslrsa_init(dst_func_t **funcp, unsigned char algorithm) { + + if (*funcp == NULL) { + switch (algorithm) { ++#ifndef PK11_MD5_DISABLE ++ case DST_ALG_RSAMD5: ++ if (isc_md5_available()) ++ *funcp = &opensslrsa_functions; ++ break; ++#endif + case DST_ALG_RSASHA256: + #if defined(HAVE_EVP_SHA256) || !USE_EVP + *funcp = &opensslrsa_functions; +diff --git a/lib/dns/pkcs11rsa_link.c b/lib/dns/pkcs11rsa_link.c +index 56955203e9..af6008d4dd 100644 +--- a/lib/dns/pkcs11rsa_link.c ++++ b/lib/dns/pkcs11rsa_link.c +@@ -94,10 +94,15 @@ pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { + #endif + + /* +- * Reject incorrect RSA key lengths. ++ * Reject incorrect RSA key lengths or disabled algorithms. + */ + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: ++#ifndef PK11_MD5_DISABLE ++ if (isc_md5_available() == ISC_FALSE) ++ return (ISC_R_FAILURE); ++#endif ++ /* FALLTHROUGH */ + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + /* From RFC 3110 */ +@@ -634,6 +639,9 @@ pkcs11rsa_createctx(dst_key_t *key, dst_context_t *dctx) { + switch (key->key_alg) { + #ifndef PK11_MD5_DISABLE + case DST_ALG_RSAMD5: ++ if (isc_md5_available() == ISC_FALSE) ++ return (ISC_R_FAILURE); ++ + mech.mechanism = CKM_MD5; + break; + #endif +@@ -790,6 +798,9 @@ pkcs11rsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { + switch (key->key_alg) { + #ifndef PK11_MD5_DISABLE + case DST_ALG_RSAMD5: ++ if (isc_md5_available() == ISC_FALSE) ++ return (ISC_R_FAILURE); ++ + der = md5_der; + derlen = sizeof(md5_der); + hashlen = ISC_MD5_DIGESTLENGTH; +@@ -1014,6 +1025,9 @@ pkcs11rsa_verify(dst_context_t *dctx, const isc_region_t *sig) { + switch (key->key_alg) { + #ifndef PK11_MD5_DISABLE + case DST_ALG_RSAMD5: ++ if (isc_md5_available() == ISC_FALSE) ++ return (ISC_R_FAILURE); ++ + der = md5_der; + derlen = sizeof(md5_der); + hashlen = ISC_MD5_DIGESTLENGTH; +@@ -2217,11 +2231,22 @@ static dst_func_t pkcs11rsa_functions = { + }; + + isc_result_t +-dst__pkcs11rsa_init(dst_func_t **funcp) { ++dst__pkcs11rsa_init(dst_func_t **funcp, unsigned char algorithm) { + REQUIRE(funcp != NULL); + +- if (*funcp == NULL) +- *funcp = &pkcs11rsa_functions; ++ if (*funcp == NULL) { ++ switch (algorithm) { ++#ifndef PK11_MD5_DISABLE ++ case DST_ALG_RSAMD5: ++ if (isc_md5_available()) ++ *funcp = &pkcs11rsa_functions; ++ break; ++#endif ++ default: ++ *funcp = &pkcs11rsa_functions; ++ break; ++ } ++ } + return (ISC_R_SUCCESS); + } + +diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c +index 937d8fc1ec..d1fa8d5870 100644 +--- a/lib/dns/rcode.c ++++ b/lib/dns/rcode.c +@@ -14,6 +14,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -347,17 +348,33 @@ dns_cert_totext(dns_cert_t cert, isc_buffer_t *target) { + return (dns_mnemonic_totext(cert, target, certs)); + } + ++static inline struct tbl * ++secalgs_tbl_start() { ++ struct tbl *algs = secalgs; ++ ++#ifndef PK11_MD5_DISABLE ++ if (isc_md5_available() == ISC_FALSE) { ++ while (algs->name != NULL && ++ algs->value == DNS_KEYALG_RSAMD5) ++ ++algs; ++ } ++#endif ++ return algs; ++} ++ + isc_result_t + dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) { + unsigned int value; +- RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff)); ++ ++ RETERR(dns_mnemonic_fromtext(&value, source, ++ secalgs_tbl_start(), 0xff)); + *secalgp = value; + return (ISC_R_SUCCESS); + } + + isc_result_t + dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) { +- return (dns_mnemonic_totext(secalg, target, secalgs)); ++ return (dns_mnemonic_totext(secalg, target, secalgs_tbl_start())); + } + + void +diff --git a/lib/dns/tests/rsa_test.c b/lib/dns/tests/rsa_test.c +index 224cf5b475..44040dd8b7 100644 +--- a/lib/dns/tests/rsa_test.c ++++ b/lib/dns/tests/rsa_test.c +@@ -19,6 +19,7 @@ + #include + #include + ++#include + #include + #include + +@@ -225,23 +226,25 @@ ATF_TC_BODY(isc_rsa_verify, tc) { + /* RSAMD5 */ + + #ifndef PK11_MD5_DISABLE +- key->key_alg = DST_ALG_RSAMD5; ++ if (isc_md5_available()) { ++ key->key_alg = DST_ALG_RSAMD5; + +- ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_DNSSEC, +- ISC_FALSE, &ctx); +- ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); ++ ret = dst_context_create3(key, mctx, DNS_LOGCATEGORY_DNSSEC, ++ ISC_FALSE, &ctx); ++ ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + +- r.base = d; +- r.length = 10; +- ret = dst_context_adddata(ctx, &r); +- ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); ++ r.base = d; ++ r.length = 10; ++ ret = dst_context_adddata(ctx, &r); ++ ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + +- r.base = sigmd5; +- r.length = 256; +- ret = dst_context_verify(ctx, &r); +- ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); ++ r.base = sigmd5; ++ r.length = 256; ++ ret = dst_context_verify(ctx, &r); ++ ATF_REQUIRE_EQ(ret, ISC_R_SUCCESS); + +- dst_context_destroy(&ctx); ++ dst_context_destroy(&ctx); ++ } + #endif + + /* RSASHA256 */ +diff --git a/lib/dns/tests/tsig_test.c b/lib/dns/tests/tsig_test.c +index ee025c2387..c403d9954d 100644 +--- a/lib/dns/tests/tsig_test.c ++++ b/lib/dns/tests/tsig_test.c +@@ -14,6 +14,7 @@ + #include + #include + ++#include + #include + #include + +diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c +index d9f68e50b1..a8edde47b5 100644 +--- a/lib/dns/tkey.c ++++ b/lib/dns/tkey.c +@@ -242,6 +242,9 @@ compute_secret(isc_buffer_t *shared, isc_region_t *queryrandomness, + unsigned char digests[32]; + unsigned int i; + ++ if (isc_md5_available() == ISC_FALSE) ++ return (ISC_R_NOTIMPLEMENTED); ++ + isc_buffer_usedregion(shared, &r); + + /* +@@ -318,6 +321,12 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, + } + + #ifndef PK11_MD5_DISABLE ++ if (isc_md5_available() == ISC_FALSE) { ++ tkey_log("process_dhtkey: MD5 was disabled"); ++ tkeyout->error = dns_tsigerror_badalg; ++ return (ISC_R_SUCCESS); ++ } ++ + if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) { + tkey_log("process_dhtkey: algorithms other than " + "hmac-md5 are not supported"); +diff --git a/lib/dns/tsec.c b/lib/dns/tsec.c +index a367291f23..37baad7437 100644 +--- a/lib/dns/tsec.c ++++ b/lib/dns/tsec.c +@@ -11,6 +11,7 @@ + + #include + ++#include + #include + #include + +@@ -63,7 +64,12 @@ dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key, + switch (dst_key_alg(key)) { + #ifndef PK11_MD5_DISABLE + case DST_ALG_HMACMD5: +- algname = dns_tsig_hmacmd5_name; ++ if (isc_md5_available()) { ++ algname = dns_tsig_hmacmd5_name; ++ } else { ++ isc_mem_put(mctx, tsec, sizeof(*tsec)); ++ return (DNS_R_BADALG); ++ } + break; + #endif + case DST_ALG_HMACSHA1: +diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c +index bdcc581bc3..70805bb709 100644 +--- a/lib/dns/tsig.c ++++ b/lib/dns/tsig.c +@@ -270,7 +270,8 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, + (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); + + #ifndef PK11_MD5_DISABLE +- if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { ++ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && ++ isc_md5_available()) { + tkey->algorithm = DNS_TSIG_HMACMD5_NAME; + if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) { + ret = DNS_R_BADALG; +@@ -496,7 +497,8 @@ destroyring(dns_tsig_keyring_t *ring) { + static unsigned int + dst_alg_fromname(dns_name_t *algorithm) { + #ifndef PK11_MD5_DISABLE +- if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { ++ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && ++ isc_md5_available()) { + return (DST_ALG_HMACMD5); + } else + #endif +@@ -680,7 +682,8 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, + REQUIRE(secret != NULL); + + #ifndef PK11_MD5_DISABLE +- if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { ++ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && ++ isc_md5_available()) { + if (secret != NULL) { + isc_buffer_t b; + +@@ -1280,7 +1283,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, + return (ret); + if ( + #ifndef PK11_MD5_DISABLE +- alg == DST_ALG_HMACMD5 || ++ (alg == DST_ALG_HMACMD5 && isc_md5_available()) || + #endif + alg == DST_ALG_HMACSHA1 || + alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || +@@ -1449,7 +1452,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, + + if ( + #ifndef PK11_MD5_DISABLE +- alg == DST_ALG_HMACMD5 || ++ (alg == DST_ALG_HMACMD5 && isc_md5_available()) || + #endif + alg == DST_ALG_HMACSHA1 || + alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || +@@ -1590,7 +1593,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { + goto cleanup_querystruct; + if ( + #ifndef PK11_MD5_DISABLE +- alg == DST_ALG_HMACMD5 || ++ (alg == DST_ALG_HMACMD5 && isc_md5_available()) || + #endif + alg == DST_ALG_HMACSHA1 || + alg == DST_ALG_HMACSHA224 || +@@ -1769,7 +1772,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { + goto cleanup_context; + if ( + #ifndef PK11_MD5_DISABLE +- alg == DST_ALG_HMACMD5 || ++ (alg == DST_ALG_HMACMD5 && isc_md5_available()) || + #endif + alg == DST_ALG_HMACSHA1 || + alg == DST_ALG_HMACSHA224 || +diff --git a/lib/isc/include/isc/md5.h b/lib/isc/include/isc/md5.h +index e5f46dd9c7..9d11f9f8b6 100644 +--- a/lib/isc/include/isc/md5.h ++++ b/lib/isc/include/isc/md5.h +@@ -89,6 +89,9 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest); + isc_boolean_t + isc_md5_check(isc_boolean_t testing); + ++isc_boolean_t ++isc_md5_available(void); ++ + ISC_LANG_ENDDECLS + + #endif /* !PK11_MD5_DISABLE */ +diff --git a/lib/isc/md5.c b/lib/isc/md5.c +index 740d863b1b..aefd16478f 100644 +--- a/lib/isc/md5.c ++++ b/lib/isc/md5.c +@@ -35,6 +35,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -53,6 +54,9 @@ + #define EVP_MD_CTX_free(ptr) EVP_MD_CTX_cleanup(ptr) + #endif + ++static isc_once_t available_once = ISC_ONCE_INIT; ++static isc_boolean_t available = ISC_FALSE; ++ + void + isc_md5_init(isc_md5_t *ctx) { + ctx->ctx = EVP_MD_CTX_new(); +@@ -84,8 +88,33 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { + ctx->ctx = NULL; + } + ++static void ++do_detect_available() { ++ isc_md5_t local; ++ isc_md5_t *ctx = &local; ++ unsigned char digest[ISC_MD5_DIGESTLENGTH]; ++ ++ ctx->ctx = EVP_MD_CTX_new(); ++ RUNTIME_CHECK(ctx->ctx != NULL); ++ available = ISC_TF(EVP_DigestInit(ctx->ctx, EVP_md5()) == 1); ++ if (available) ++ (void)EVP_DigestFinal(ctx->ctx, digest, NULL); ++ EVP_MD_CTX_free(ctx->ctx); ++ ctx->ctx = NULL; ++} ++ ++isc_boolean_t ++isc_md5_available() { ++ RUNTIME_CHECK(isc_once_do(&available_once, do_detect_available) ++ == ISC_R_SUCCESS); ++ return available; ++} ++ + #elif PKCS11CRYPTO + ++static isc_once_t available_once = ISC_ONCE_INIT; ++static isc_boolean_t available = ISC_FALSE; ++ + void + isc_md5_init(isc_md5_t *ctx) { + CK_RV rv; +@@ -128,6 +157,31 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { + pk11_return_session(ctx); + } + ++static void ++do_detect_available() { ++ isc_md5_t local; ++ isc_md5_t *ctx = &local; ++ CK_RV rv; ++ CK_MECHANISM mech = { CKM_MD5, NULL, 0 }; ++ ++ if (pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, ++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS) ++ { ++ rv = pkcs_C_DigestInit(ctx->session, &mech); ++ isc_md5_invalidate(ctx); ++ available = (ISC_TF(rv == CKR_OK)); ++ } else { ++ available = ISC_FALSE; ++ } ++} ++ ++isc_boolean_t ++isc_md5_available() { ++ RUNTIME_CHECK(isc_once_do(&available_once, do_detect_available) ++ == ISC_R_SUCCESS); ++ return available; ++} ++ + #else + + static void +@@ -337,6 +391,11 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { + memmove(digest, ctx->buf, 16); + isc_safe_memwipe(ctx, sizeof(*ctx)); /* In case it's sensitive */ + } ++ ++isc_boolean_t ++isc_md5_available() { ++ return ISC_TRUE; ++} + #endif + + /* +diff --git a/lib/isc/pk11.c b/lib/isc/pk11.c +index fc75a46154..48e1031974 100644 +--- a/lib/isc/pk11.c ++++ b/lib/isc/pk11.c +@@ -191,13 +191,12 @@ pk11_initialize(isc_mem_t *mctx, const char *engine) { + LOCK(&alloclock); + if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0)) + isc_mem_attach(mctx, &pk11_mctx); ++ UNLOCK(&alloclock); ++ ++ LOCK(&sessionlock); + if (initialized) { +- UNLOCK(&alloclock); +- return (ISC_R_SUCCESS); +- } else { +- LOCK(&sessionlock); +- initialized = ISC_TRUE; +- UNLOCK(&alloclock); ++ result = ISC_R_SUCCESS; ++ goto unlock; + } + + ISC_LIST_INIT(tokens); +@@ -237,6 +236,7 @@ pk11_initialize(isc_mem_t *mctx, const char *engine) { + } + #endif + #endif /* PKCS11CRYPTO */ ++ initialized = ISC_TRUE; + result = ISC_R_SUCCESS; + unlock: + UNLOCK(&sessionlock); +@@ -273,9 +273,14 @@ pk11_finalize(void) { + pk11_mem_put(token, sizeof(*token)); + token = next; + } ++ LOCK(&alloclock); + if (pk11_mctx != NULL) + isc_mem_detach(&pk11_mctx); ++ UNLOCK(&alloclock); ++ ++ LOCK(&sessionlock); + initialized = ISC_FALSE; ++ UNLOCK(&sessionlock); + return (ret); + } + +@@ -589,6 +594,8 @@ scan_slots(void) { + pk11_token_t *token; + unsigned int i; + isc_boolean_t bad; ++ unsigned int best_rsa_algorithms = 0; ++ unsigned int best_digest_algorithms = 0; + + slotCount = 0; + PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount)); +@@ -601,6 +608,8 @@ scan_slots(void) { + PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount)); + + for (i = 0; i < slotCount; i++) { ++ unsigned int rsa_algorithms = 0; ++ unsigned int digest_algorithms = 0; + slot = slotList[i]; + PK11_TRACE2("slot#%u=0x%lx\n", i, slot); + +@@ -640,11 +649,12 @@ scan_slots(void) { + if ((rv != CKR_OK) || + ((mechInfo.flags & CKF_SIGN) == 0) || + ((mechInfo.flags & CKF_VERIFY) == 0)) { +-#if !defined(PK11_MD5_DISABLE) && !defined(PK11_RSA_PKCS_REPLACE) +- bad = ISC_TRUE; +-#endif + PK11_TRACEM(CKM_MD5_RSA_PKCS); + } ++#if !defined(PK11_MD5_DISABLE) && !defined(PK11_RSA_PKCS_REPLACE) ++ else ++ ++rsa_algorithms; ++#endif + rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS, + &mechInfo); + if ((rv != CKR_OK) || +@@ -687,8 +697,14 @@ scan_slots(void) { + if (bad) + goto try_dsa; + token->operations |= 1 << OP_RSA; +- if (best_rsa_token == NULL) ++ if (best_rsa_token == NULL) { ++ best_rsa_token = token; ++ best_rsa_algorithms = rsa_algorithms; ++ } else if (rsa_algorithms > best_rsa_algorithms) { ++ pk11_mem_put(best_rsa_token, sizeof(*best_rsa_token)); + best_rsa_token = token; ++ best_rsa_algorithms = rsa_algorithms; ++ } + + try_dsa: + bad = ISC_FALSE; +@@ -756,11 +772,12 @@ scan_slots(void) { + bad = ISC_FALSE; + rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5, &mechInfo); + if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) { +-#ifndef PK11_MD5_DISABLE +- bad = ISC_TRUE; +-#endif + PK11_TRACEM(CKM_MD5); + } ++#ifndef PK11_MD5_DISABLE ++ else ++ ++digest_algorithms; ++#endif + rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1, &mechInfo); + if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) { + bad = ISC_TRUE; +@@ -788,11 +805,12 @@ scan_slots(void) { + } + rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_HMAC, &mechInfo); + if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) { +-#if !defined(PK11_MD5_DISABLE) && !defined(PK11_MD5_HMAC_REPLACE) +- bad = ISC_TRUE; +-#endif + PK11_TRACEM(CKM_MD5_HMAC); + } ++#if !defined(PK11_MD5_DISABLE) && !defined(PK11_MD5_HMAC_REPLACE) ++ else ++ ++digest_algorithms; ++#endif + rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1_HMAC, &mechInfo); + if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) { + #ifndef PK11_SHA_1_HMAC_REPLACE +@@ -830,8 +848,14 @@ scan_slots(void) { + } + if (!bad) { + token->operations |= 1 << OP_DIGEST; +- if (digest_token == NULL) ++ if (digest_token == NULL) { ++ digest_token = token; ++ best_digest_algorithms = digest_algorithms; ++ } else if (digest_algorithms > best_digest_algorithms) { ++ pk11_mem_put(digest_token, sizeof(*digest_token)); + digest_token = token; ++ best_digest_algorithms = digest_algorithms; ++ } + } + + /* ECDSA requires digest */ +diff --git a/lib/isc/tests/hash_test.c b/lib/isc/tests/hash_test.c +index 18759903be..6bc45b1ad3 100644 +--- a/lib/isc/tests/hash_test.c ++++ b/lib/isc/tests/hash_test.c +@@ -2008,7 +2008,8 @@ ATF_TP_ADD_TCS(tp) { + * various cryptographic hashes. + */ + #ifndef PK11_MD5_DISABLE +- ATF_TP_ADD_TC(tp, md5_check); ++ if (isc_md5_available()) ++ ATF_TP_ADD_TC(tp, md5_check); + #endif + ATF_TP_ADD_TC(tp, sha1_check); + +@@ -2016,7 +2017,8 @@ ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, isc_hash_function_reverse); + ATF_TP_ADD_TC(tp, isc_hash_initializer); + #ifndef PK11_MD5_DISABLE +- ATF_TP_ADD_TC(tp, isc_hmacmd5); ++ if (isc_md5_available()) ++ ATF_TP_ADD_TC(tp, isc_hmacmd5); + #endif + ATF_TP_ADD_TC(tp, isc_hmacsha1); + ATF_TP_ADD_TC(tp, isc_hmacsha224); +@@ -2024,7 +2026,8 @@ ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, isc_hmacsha384); + ATF_TP_ADD_TC(tp, isc_hmacsha512); + #ifndef PK11_MD5_DISABLE +- ATF_TP_ADD_TC(tp, isc_md5); ++ if (isc_md5_available()) ++ ATF_TP_ADD_TC(tp, isc_md5); + #endif + ATF_TP_ADD_TC(tp, isc_sha1); + ATF_TP_ADD_TC(tp, isc_sha224); +diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c +index 7225ab4a37..42b30466be 100644 +--- a/lib/isccc/cc.c ++++ b/lib/isccc/cc.c +@@ -270,11 +270,15 @@ sign(unsigned char *data, unsigned int length, unsigned char *hmac, + switch (algorithm) { + #ifndef PK11_MD5_DISABLE + case ISCCC_ALG_HMACMD5: +- isc_hmacmd5_init(&ctx.hmd5, secret->rstart, +- REGION_SIZE(*secret)); +- isc_hmacmd5_update(&ctx.hmd5, data, length); +- isc_hmacmd5_sign(&ctx.hmd5, digest); +- source.rend = digest + ISC_MD5_DIGESTLENGTH; ++ if (isc_md5_available()) { ++ isc_hmacmd5_init(&ctx.hmd5, secret->rstart, ++ REGION_SIZE(*secret)); ++ isc_hmacmd5_update(&ctx.hmd5, data, length); ++ isc_hmacmd5_sign(&ctx.hmd5, digest); ++ source.rend = digest + ISC_MD5_DIGESTLENGTH; ++ } else { ++ return (ISC_R_FAILURE); ++ } + break; + #endif + +@@ -348,14 +352,18 @@ isccc_cc_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer, + { + unsigned int hmac_base, signed_base; + isc_result_t result; ++ const isc_boolean_t md5 = ISC_TF(algorithm == ISCCC_ALG_HMACMD5); + + #ifndef PK11_MD5_DISABLE ++ if (md5 && isc_md5_available() == ISC_FALSE) ++ return (ISC_R_NOTIMPLEMENTED); ++ + result = isc_buffer_reserve(buffer, +- 4 + ((algorithm == ISCCC_ALG_HMACMD5) ? ++ 4 + ((md5) ? + sizeof(auth_hmd5) : + sizeof(auth_hsha))); + #else +- if (algorithm == ISCCC_ALG_HMACMD5) ++ if (md5) + return (ISC_R_NOTIMPLEMENTED); + result = isc_buffer_reserve(buffer, 4 + sizeof(auth_hsha)); + #endif +@@ -374,7 +382,7 @@ isccc_cc_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer, + * we know what it is. + */ + #ifndef PK11_MD5_DISABLE +- if (algorithm == ISCCC_ALG_HMACMD5) { ++ if (md5) { + hmac_base = (*buffer)->used + HMD5_OFFSET; + isc_buffer_putmem(*buffer, + auth_hmd5, sizeof(auth_hmd5)); +@@ -440,7 +448,7 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, + if (!isccc_alist_alistp(_auth)) + return (ISC_R_FAILURE); + #ifndef PK11_MD5_DISABLE +- if (algorithm == ISCCC_ALG_HMACMD5) ++ if (algorithm == ISCCC_ALG_HMACMD5 && isc_md5_available()) + hmac = isccc_alist_lookup(_auth, "hmd5"); + else + #endif +@@ -455,12 +463,16 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, + switch (algorithm) { + #ifndef PK11_MD5_DISABLE + case ISCCC_ALG_HMACMD5: +- isc_hmacmd5_init(&ctx.hmd5, secret->rstart, +- REGION_SIZE(*secret)); +- isc_hmacmd5_update(&ctx.hmd5, data, length); +- isc_hmacmd5_sign(&ctx.hmd5, digest); +- source.rend = digest + ISC_MD5_DIGESTLENGTH; +- break; ++ if (isc_md5_available()) { ++ isc_hmacmd5_init(&ctx.hmd5, secret->rstart, ++ REGION_SIZE(*secret)); ++ isc_hmacmd5_update(&ctx.hmd5, data, length); ++ isc_hmacmd5_sign(&ctx.hmd5, digest); ++ source.rend = digest + ISC_MD5_DIGESTLENGTH; ++ break; ++ } else { ++ return (ISC_R_FAILURE); ++ } + #endif + + case ISCCC_ALG_HMACSHA1: +-- +2.14.4 + diff --git a/SOURCES/bind-9.11-fips-tests.patch b/SOURCES/bind-9.11-fips-tests.patch new file mode 100644 index 0000000..f7a998d --- /dev/null +++ b/SOURCES/bind-9.11-fips-tests.patch @@ -0,0 +1,1781 @@ +From 35b53607724ec4b5d4060385218c39ccd0d78a4d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Thu, 2 Aug 2018 23:46:45 +0200 +Subject: [PATCH 2/2] Squashed commit of the following: +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 09e5eb48698d4fef2fc1031870de86c553b6bfaa +Author: Petr Menšík +Date: Wed Mar 7 20:35:13 2018 +0100 + + Fix nsupdate test. Do not use md5 by default for rndc, skip gracefully md5 if not available. + +commit ab303db70082db76ecf36493d0b82ef3e8750cad +Author: Petr Menšík +Date: Wed Mar 7 18:11:10 2018 +0100 + + Changed root key to be RSASHA256 + + Change bad trusted key to be the same algorithm. + +commit 88ab07c0e14cc71247e1f9d11a1ea832b64c1ee8 +Author: Petr Menšík +Date: Wed Mar 7 16:56:17 2018 +0100 + + Change used key to not use hmac-md5 + + Fix upforwd test, do not use hmac-md5 + +commit aec891571626f053acfb4d0a247240cbc21a84e9 +Author: Petr Menšík +Date: Wed Mar 7 15:54:11 2018 +0100 + + Increase bitsize of DSA key to pass FIPS 140-2 mode. + +commit bca8e164fa0d9aff2f946b8b4eb0f1f7e0bf6696 +Author: Petr Menšík +Date: Wed Mar 7 15:41:08 2018 +0100 + + Fix tsig and rndc tests for disabled md5 + + Use hmac-sha256 instead of hmac-md5. + +commit 0d314c1ab6151aa13574a21ad22f28d3b7f42a67 +Author: Petr Menšík +Date: Wed Mar 7 13:21:00 2018 +0100 + + Add md5 availability detection to featuretest + +commit f389a918803e2853e4b55fed62765dc4a492e34f +Author: Petr Menšík +Date: Wed Mar 7 10:44:23 2018 +0100 + + Change tests to not use hmac-md5 algorithms if not required + + Use hmac-sha256 instead of default hmac-md5 for allow-query +--- + bin/tests/system/acl/ns2/named1.conf.in | 4 +- + bin/tests/system/acl/ns2/named2.conf.in | 4 +- + bin/tests/system/acl/ns2/named3.conf.in | 6 +-- + bin/tests/system/acl/ns2/named4.conf.in | 4 +- + bin/tests/system/acl/ns2/named5.conf.in | 4 +- + bin/tests/system/acl/tests.sh | 32 +++++------ + bin/tests/system/allow-query/ns2/named10.conf.in | 2 +- + bin/tests/system/allow-query/ns2/named11.conf.in | 4 +- + bin/tests/system/allow-query/ns2/named12.conf.in | 2 +- + bin/tests/system/allow-query/ns2/named30.conf.in | 2 +- + bin/tests/system/allow-query/ns2/named31.conf.in | 4 +- + bin/tests/system/allow-query/ns2/named32.conf.in | 2 +- + bin/tests/system/allow-query/ns2/named40.conf.in | 4 +- + bin/tests/system/allow-query/tests.sh | 18 +++---- + bin/tests/system/catz/ns1/named.conf.in | 2 +- + bin/tests/system/catz/ns2/named.conf.in | 2 +- + bin/tests/system/checkconf/bad-tsig.conf | 2 +- + bin/tests/system/checkconf/good.conf | 2 +- + bin/tests/system/digdelv/ns2/example.db | 15 +++--- + bin/tests/system/digdelv/tests.sh | 28 +++++----- + bin/tests/system/dlv/ns1/sign.sh | 4 +- + bin/tests/system/dlv/ns2/sign.sh | 4 +- + bin/tests/system/dlv/ns3/sign.sh | 69 ++++++++++++------------ + bin/tests/system/dlv/ns6/sign.sh | 66 ++++++++++++----------- + bin/tests/system/dnssec/ns1/sign.sh | 4 +- + bin/tests/system/dnssec/ns2/sign.sh | 12 ++--- + bin/tests/system/dnssec/ns3/sign.sh | 20 +++---- + bin/tests/system/dnssec/ns5/trusted.conf.bad | 2 +- + bin/tests/system/dnssec/tests.sh | 8 +-- + bin/tests/system/feature-test.c | 14 +++++ + bin/tests/system/filter-aaaa/ns1/sign.sh | 4 +- + bin/tests/system/filter-aaaa/ns4/sign.sh | 4 +- + bin/tests/system/notify/ns5/named.conf.in | 6 +-- + bin/tests/system/notify/tests.sh | 6 +-- + bin/tests/system/nsupdate/ns1/named.conf.in | 2 +- + bin/tests/system/nsupdate/ns2/named.conf.in | 2 +- + bin/tests/system/nsupdate/setup.sh | 7 ++- + bin/tests/system/nsupdate/tests.sh | 11 +++- + bin/tests/system/rndc/setup.sh | 2 +- + bin/tests/system/rndc/tests.sh | 23 ++++---- + bin/tests/system/tsig/clean.sh | 1 + + bin/tests/system/tsig/ns1/named.conf.in | 10 +--- + bin/tests/system/tsig/ns1/rndc5.conf.in | 11 ++++ + bin/tests/system/tsig/setup.sh | 4 ++ + bin/tests/system/tsig/tests.sh | 67 ++++++++++++++--------- + bin/tests/system/tsiggss/setup.sh | 2 +- + bin/tests/system/upforwd/ns1/named.conf.in | 2 +- + bin/tests/system/upforwd/tests.sh | 2 +- + 48 files changed, 287 insertions(+), 225 deletions(-) + create mode 100644 bin/tests/system/tsig/ns1/rndc5.conf.in + +diff --git a/bin/tests/system/acl/ns2/named1.conf.in b/bin/tests/system/acl/ns2/named1.conf.in +index 0ea6502708..026db3f134 100644 +--- a/bin/tests/system/acl/ns2/named1.conf.in ++++ b/bin/tests/system/acl/ns2/named1.conf.in +@@ -33,12 +33,12 @@ options { + }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key two { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/acl/ns2/named2.conf.in b/bin/tests/system/acl/ns2/named2.conf.in +index b877880554..d8f50be255 100644 +--- a/bin/tests/system/acl/ns2/named2.conf.in ++++ b/bin/tests/system/acl/ns2/named2.conf.in +@@ -33,12 +33,12 @@ options { + }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key two { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/acl/ns2/named3.conf.in b/bin/tests/system/acl/ns2/named3.conf.in +index 0a950622a2..aa54088138 100644 +--- a/bin/tests/system/acl/ns2/named3.conf.in ++++ b/bin/tests/system/acl/ns2/named3.conf.in +@@ -33,17 +33,17 @@ options { + }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key two { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key three { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/acl/ns2/named4.conf.in b/bin/tests/system/acl/ns2/named4.conf.in +index 7cdcb6e341..606a3452d8 100644 +--- a/bin/tests/system/acl/ns2/named4.conf.in ++++ b/bin/tests/system/acl/ns2/named4.conf.in +@@ -33,12 +33,12 @@ options { + }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key two { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/acl/ns2/named5.conf.in b/bin/tests/system/acl/ns2/named5.conf.in +index 4b4e05027a..0e679a821d 100644 +--- a/bin/tests/system/acl/ns2/named5.conf.in ++++ b/bin/tests/system/acl/ns2/named5.conf.in +@@ -34,12 +34,12 @@ options { + }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key two { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/acl/tests.sh b/bin/tests/system/acl/tests.sh +index 09f31f2bb9..f88f0d4430 100644 +--- a/bin/tests/system/acl/tests.sh ++++ b/bin/tests/system/acl/tests.sh +@@ -22,14 +22,14 @@ echo_i "testing basic ACL processing" + # key "one" should fail + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:one:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; } + + + # any other key should be fine + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:two:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; } + + copy_setports ns2/named2.conf.in ns2/named.conf +@@ -39,18 +39,18 @@ sleep 5 + # prefix 10/8 should fail + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:one:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; } + + # any other address should work, as long as it sends key "one" + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 127.0.0.1 axfr -y two:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 127.0.0.1 axfr -y hmac-sha256:two:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; } + + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 127.0.0.1 axfr -y one:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 127.0.0.1 axfr -y hmac-sha256:one:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; } + + echo_i "testing nested ACL processing" +@@ -62,31 +62,31 @@ sleep 5 + # should succeed + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.2 axfr -y two:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.2 axfr -y hmac-sha256:two:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; } + + # should succeed + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.2 axfr -y one:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.2 axfr -y hmac-sha256:one:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; } + + # should succeed + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:two:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; } + + # should succeed + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:two:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; } + + # but only one or the other should fail + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 127.0.0.1 axfr -y one:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 127.0.0.1 axfr -y hmac-sha256:one:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; } + + t=`expr $t + 1` +@@ -97,7 +97,7 @@ grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $tt failed" ; status=1 + # and other values? right out + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 127.0.0.1 axfr -y three:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 127.0.0.1 axfr -y hmac-sha256:three:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; } + + # now we only allow 10.53.0.1 *and* key one, or 10.53.0.2 *and* key two +@@ -108,31 +108,31 @@ sleep 5 + # should succeed + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.2 axfr -y two:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.2 axfr -y hmac-sha256:two:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; } + + # should succeed + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:one:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 && { echo_i "test $t failed" ; status=1; } + + # should fail + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.2 axfr -y one:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.2 axfr -y hmac-sha256:one:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; } + + # should fail + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:two:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; } + + # should fail + t=`expr $t + 1` + $DIG $DIGOPTS tsigzone. \ +- @10.53.0.2 -b 10.53.0.3 axfr -y one:1234abcd8765 > dig.out.${t} ++ @10.53.0.2 -b 10.53.0.3 axfr -y hmac-sha256:one:1234abcd8765 > dig.out.${t} + grep "^;" dig.out.${t} > /dev/null 2>&1 || { echo_i "test $t failed" ; status=1; } + + echo_i "testing allow-query-on ACL processing" +diff --git a/bin/tests/system/allow-query/ns2/named10.conf.in b/bin/tests/system/allow-query/ns2/named10.conf.in +index 1569913b37..e9c5c2d574 100644 +--- a/bin/tests/system/allow-query/ns2/named10.conf.in ++++ b/bin/tests/system/allow-query/ns2/named10.conf.in +@@ -12,7 +12,7 @@ + controls { /* empty */ }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/allow-query/ns2/named11.conf.in b/bin/tests/system/allow-query/ns2/named11.conf.in +index 18ac91c6e7..2b1c8739d8 100644 +--- a/bin/tests/system/allow-query/ns2/named11.conf.in ++++ b/bin/tests/system/allow-query/ns2/named11.conf.in +@@ -12,12 +12,12 @@ + controls { /* empty */ }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key two { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234efgh8765"; + }; + +diff --git a/bin/tests/system/allow-query/ns2/named12.conf.in b/bin/tests/system/allow-query/ns2/named12.conf.in +index b8248444dd..dd48945bf8 100644 +--- a/bin/tests/system/allow-query/ns2/named12.conf.in ++++ b/bin/tests/system/allow-query/ns2/named12.conf.in +@@ -12,7 +12,7 @@ + controls { /* empty */ }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/allow-query/ns2/named30.conf.in b/bin/tests/system/allow-query/ns2/named30.conf.in +index aeb1540e95..bfce58bddd 100644 +--- a/bin/tests/system/allow-query/ns2/named30.conf.in ++++ b/bin/tests/system/allow-query/ns2/named30.conf.in +@@ -12,7 +12,7 @@ + controls { /* empty */ }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/allow-query/ns2/named31.conf.in b/bin/tests/system/allow-query/ns2/named31.conf.in +index d4b743281a..e0f52526ba 100644 +--- a/bin/tests/system/allow-query/ns2/named31.conf.in ++++ b/bin/tests/system/allow-query/ns2/named31.conf.in +@@ -12,12 +12,12 @@ + controls { /* empty */ }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key two { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234efgh8765"; + }; + +diff --git a/bin/tests/system/allow-query/ns2/named32.conf.in b/bin/tests/system/allow-query/ns2/named32.conf.in +index c0259387e7..87afb3fa3a 100644 +--- a/bin/tests/system/allow-query/ns2/named32.conf.in ++++ b/bin/tests/system/allow-query/ns2/named32.conf.in +@@ -12,7 +12,7 @@ + controls { /* empty */ }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/allow-query/ns2/named40.conf.in b/bin/tests/system/allow-query/ns2/named40.conf.in +index d83b376cfd..d726b9480b 100644 +--- a/bin/tests/system/allow-query/ns2/named40.conf.in ++++ b/bin/tests/system/allow-query/ns2/named40.conf.in +@@ -16,12 +16,12 @@ acl accept { 10.53.0.2; }; + acl badaccept { 10.53.0.1; }; + + key one { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234abcd8765"; + }; + + key two { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "1234efgh8765"; + }; + +diff --git a/bin/tests/system/allow-query/tests.sh b/bin/tests/system/allow-query/tests.sh +index fb6059d5b8..f9601564a2 100644 +--- a/bin/tests/system/allow-query/tests.sh ++++ b/bin/tests/system/allow-query/tests.sh +@@ -190,7 +190,7 @@ rndc_reload + + echo_i "test $n: key allowed - query allowed" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 + grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -203,7 +203,7 @@ rndc_reload + + echo_i "test $n: key not allowed - query refused" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1 + grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -216,7 +216,7 @@ rndc_reload + + echo_i "test $n: key disallowed - query refused" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 + grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -349,7 +349,7 @@ rndc_reload + + echo_i "test $n: views key allowed - query allowed" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 + grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -362,7 +362,7 @@ rndc_reload + + echo_i "test $n: views key not allowed - query refused" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1 + grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -375,7 +375,7 @@ rndc_reload + + echo_i "test $n: views key disallowed - query refused" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 + grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -508,7 +508,7 @@ status=`expr $status + $ret` + n=`expr $n + 1` + echo_i "test $n: zone key allowed - query allowed" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.keyallow.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.keyallow.example a > dig.out.ns2.$n || ret=1 + grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.keyallow.example' dig.out.ns2.$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -518,7 +518,7 @@ status=`expr $status + $ret` + n=`expr $n + 1` + echo_i "test $n: zone key not allowed - query refused" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.keyallow.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:two:1234efgh8765 a.keyallow.example a > dig.out.ns2.$n || ret=1 + grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.keyallow.example' dig.out.ns2.$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +@@ -528,7 +528,7 @@ status=`expr $status + $ret` + n=`expr $n + 1` + echo_i "test $n: zone key disallowed - query refused" + ret=0 +-$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.keydisallow.example a > dig.out.ns2.$n || ret=1 ++$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.keydisallow.example a > dig.out.ns2.$n || ret=1 + grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 + grep '^a.keydisallow.example' dig.out.ns2.$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi +diff --git a/bin/tests/system/catz/ns1/named.conf.in b/bin/tests/system/catz/ns1/named.conf.in +index 74b7d371b7..c35376640d 100644 +--- a/bin/tests/system/catz/ns1/named.conf.in ++++ b/bin/tests/system/catz/ns1/named.conf.in +@@ -61,5 +61,5 @@ zone "catalog4.example" { + + key tsig_key. { + secret "LSAnCU+Z"; +- algorithm hmac-md5; ++ algorithm hmac-sha256; + }; +diff --git a/bin/tests/system/catz/ns2/named.conf.in b/bin/tests/system/catz/ns2/named.conf.in +index ee83efbee4..35ced08842 100644 +--- a/bin/tests/system/catz/ns2/named.conf.in ++++ b/bin/tests/system/catz/ns2/named.conf.in +@@ -70,5 +70,5 @@ zone "catalog4.example" { + + key tsig_key. { + secret "LSAnCU+Z"; +- algorithm hmac-md5; ++ algorithm hmac-sha256; + }; +diff --git a/bin/tests/system/checkconf/bad-tsig.conf b/bin/tests/system/checkconf/bad-tsig.conf +index 21be03e9d2..e57c30875c 100644 +--- a/bin/tests/system/checkconf/bad-tsig.conf ++++ b/bin/tests/system/checkconf/bad-tsig.conf +@@ -11,7 +11,7 @@ + + /* Bad secret */ + key "badtsig" { +- algorithm hmac-md5; ++ algorithm hmac-sha256; + secret "jEdD+BPKg=="; + }; + +diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf +index 9ab35b38a5..486551ae64 100644 +--- a/bin/tests/system/checkconf/good.conf ++++ b/bin/tests/system/checkconf/good.conf +@@ -153,6 +153,6 @@ dyndb "name" "library.so" { + system; + }; + key "mykey" { +- algorithm "hmac-md5"; ++ algorithm "hmac-sha256"; + secret "qwertyuiopasdfgh"; + }; +diff --git a/bin/tests/system/digdelv/ns2/example.db b/bin/tests/system/digdelv/ns2/example.db +index f4e30f51e5..9f53e31c97 100644 +--- a/bin/tests/system/digdelv/ns2/example.db ++++ b/bin/tests/system/digdelv/ns2/example.db +@@ -38,12 +38,15 @@ foo SSHFP 2 1 123456789abcdef67890123456789abcdef67890 + ;; + ;; we are not testing DNSSEC behavior, so we don't care about the semantics + ;; of the following records. +-dnskey 300 DNSKEY 256 3 1 ( +- AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg +- +Ge4noWROpTWOIBvm76zeJPWs4Zfqa1IsswD +- Ix5Mqeg0zwclz59uecKsKyx5w9IhtZ8plc4R +- b9VIE5x7KNHAYTvTO5d4S8M= +- ) ++dnskey 300 DNSKEY 256 3 8 ( ++ AwEAAaWmCoDpj2K59zcpqnmnQM7IC/XbjS6jIP7uTBR4X7p1bdQJzAeo ++ EnMhnpnxPp0j+20eZm4847DB2U+HuHy79Mvqd3aozTmfBJvzjKs9qyba ++ zY/ZHn6BDYxNJiFfjSS/VJ1KuQPDbpCzhm2hbvT5s9nSOaG0WyRk+d+R ++ qEca11E7ZKkmmNiGlyzMAgfmTTBwgxWBAAhvd9nU1GqD6eQ6Z63hpTc/ ++ KDIHnFTo7pOcZ4z5urIKUMCMcFytedETlEoR5CIWGPdQq2eIEEMfn5ld ++ QqdEZRHVErD9og8aluJ2s767HZb8LzjCfYgBFoT9/n48T75oZLEKtSkG ++ /idCeeQlaLU= ++ ) + + ; TTL of 3 weeks + weeks 1814400 A 10.53.0.2 +diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh +index 1b25c4ddfc..5dbf20a3e1 100644 +--- a/bin/tests/system/digdelv/tests.sh ++++ b/bin/tests/system/digdelv/tests.sh +@@ -62,7 +62,7 @@ if [ -x ${DIG} ] ; then + echo_i "checking dig +multi +norrcomments works for dnskey (when default is rrcomments)($n)" + ret=0 + $DIG $DIGOPTS +tcp @10.53.0.3 +multi +norrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1 +- grep "; ZSK; alg = RSAMD5 ; key id = 30795" < dig.out.test$n > /dev/null && ret=1 ++ grep "; ZSK; alg = RSASHA256 ; key id = 36895" < dig.out.test$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -70,7 +70,7 @@ if [ -x ${DIG} ] ; then + echo_i "checking dig +multi +norrcomments works for soa (when default is rrcomments)($n)" + ret=0 + $DIG $DIGOPTS +tcp @10.53.0.3 +multi +norrcomments SOA example > dig.out.test$n || ret=1 +- grep "; ZSK; alg = RSAMD5 ; key id = 30795" < dig.out.test$n > /dev/null && ret=1 ++ grep "; ZSK; alg = RSASHA256 ; key id = 36895" < dig.out.test$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -78,7 +78,7 @@ if [ -x ${DIG} ] ; then + echo_i "checking dig +rrcomments works for DNSKEY($n)" + ret=0 + $DIG $DIGOPTS +tcp @10.53.0.3 +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1 +- grep "; ZSK; alg = RSAMD5 ; key id = 30795" < dig.out.test$n > /dev/null || ret=1 ++ grep "; ZSK; alg = RSASHA256 ; key id = 36895$" < dig.out.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -86,7 +86,7 @@ if [ -x ${DIG} ] ; then + echo_i "checking dig +short +rrcomments works for DNSKEY ($n)" + ret=0 + $DIG $DIGOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1 +- grep "; ZSK; alg = RSAMD5 ; key id = 30795" < dig.out.test$n > /dev/null || ret=1 ++ grep "; ZSK; alg = RSASHA256 ; key id = 36895$" < dig.out.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -94,7 +94,7 @@ if [ -x ${DIG} ] ; then + echo_i "checking dig +short +nosplit works($n)" + ret=0 + $DIG $DIGOPTS +tcp @10.53.0.3 +short +nosplit DNSKEY dnskey.example > dig.out.test$n || ret=1 +- grep "Z8plc4Rb9VIE5x7KNHAYTvTO5d4S8M=$" < dig.out.test$n > /dev/null || ret=1 ++ grep "T9/n48T75oZLEKtSkG/idCeeQlaLU=$" < dig.out.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -102,7 +102,7 @@ if [ -x ${DIG} ] ; then + echo_i "checking dig +short +rrcomments works($n)" + ret=0 + $DIG $DIGOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1 +- grep "S8M= ; ZSK; alg = RSAMD5 ; key id = 30795$" < dig.out.test$n > /dev/null || ret=1 ++ grep "aLU= ; ZSK; alg = RSASHA256 ; key id = 36895$" < dig.out.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -118,7 +118,7 @@ if [ -x ${DIG} ] ; then + echo_i "checking dig +short +rrcomments works($n)" + ret=0 + $DIG $DIGOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1 +- grep "S8M= ; ZSK; alg = RSAMD5 ; key id = 30795$" < dig.out.test$n > /dev/null || ret=1 ++ grep "aLU= ; ZSK; alg = RSASHA256 ; key id = 36895$" < dig.out.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -543,7 +543,7 @@ if [ -x ${DELV} ] ; then + echo_i "checking delv +multi +norrcomments works for dnskey (when default is rrcomments)($n)" + ret=0 + $DELV $DELVOPTS +tcp @10.53.0.3 +multi +norrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1 +- grep "; ZSK; alg = RSAMD5 ; key id = 30795" < delv.out.test$n > /dev/null && ret=1 ++ grep "; ZSK; alg = RSASHA256 ; key id = 36895" < delv.out.test$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -551,7 +551,7 @@ if [ -x ${DELV} ] ; then + echo_i "checking delv +multi +norrcomments works for soa (when default is rrcomments)($n)" + ret=0 + $DELV $DELVOPTS +tcp @10.53.0.3 +multi +norrcomments SOA example > delv.out.test$n || ret=1 +- grep "; ZSK; alg = RSAMD5 ; key id = 30795" < delv.out.test$n > /dev/null && ret=1 ++ grep "; ZSK; alg = RSASHA256 ; key id = 36895" < delv.out.test$n > /dev/null && ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -559,7 +559,7 @@ if [ -x ${DELV} ] ; then + echo_i "checking delv +rrcomments works for DNSKEY($n)" + ret=0 + $DELV $DELVOPTS +tcp @10.53.0.3 +rrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1 +- grep "; ZSK; alg = RSAMD5 ; key id = 30795" < delv.out.test$n > /dev/null || ret=1 ++ grep "; ZSK; alg = RSASHA256 ; key id = 36895" < delv.out.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -567,7 +567,7 @@ if [ -x ${DELV} ] ; then + echo_i "checking delv +short +rrcomments works for DNSKEY ($n)" + ret=0 + $DELV $DELVOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1 +- grep "; ZSK; alg = RSAMD5 ; key id = 30795" < delv.out.test$n > /dev/null || ret=1 ++ grep "; ZSK; alg = RSASHA256 ; key id = 36895" < delv.out.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -575,7 +575,7 @@ if [ -x ${DELV} ] ; then + echo_i "checking delv +short +rrcomments works ($n)" + ret=0 + $DELV $DELVOPTS +tcp @10.53.0.3 +short +rrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1 +- grep "S8M= ; ZSK; alg = RSAMD5 ; key id = 30795$" < delv.out.test$n > /dev/null || ret=1 ++ grep "aLU= ; ZSK; alg = RSASHA256 ; key id = 36895$" < delv.out.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + +@@ -583,7 +583,7 @@ if [ -x ${DELV} ] ; then + echo_i "checking delv +short +nosplit works ($n)" + ret=0 + $DELV $DELVOPTS +tcp @10.53.0.3 +short +nosplit DNSKEY dnskey.example > delv.out.test$n || ret=1 +- grep "Z8plc4Rb9VIE5x7KNHAYTvTO5d4S8M=" < delv.out.test$n > /dev/null || ret=1 ++ grep "T9/n48T75oZLEKtSkG/idCeeQlaLU=" < delv.out.test$n > /dev/null || ret=1 + if test `wc -l < delv.out.test$n` != 1 ; then ret=1 ; fi + f=`awk '{print NF}' < delv.out.test$n` + test "${f:-0}" -eq 14 || ret=1 +@@ -594,7 +594,7 @@ if [ -x ${DELV} ] ; then + echo_i "checking delv +short +nosplit +norrcomments works ($n)" + ret=0 + $DELV $DELVOPTS +tcp @10.53.0.3 +short +nosplit +norrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1 +- grep "Z8plc4Rb9VIE5x7KNHAYTvTO5d4S8M=$" < delv.out.test$n > /dev/null || ret=1 ++ grep "T9/n48T75oZLEKtSkG/idCeeQlaLU=$" < delv.out.test$n > /dev/null || ret=1 + if test `wc -l < delv.out.test$n` != 1 ; then ret=1 ; fi + f=`awk '{print NF}' < delv.out.test$n` + test "${f:-0}" -eq 4 || ret=1 +diff --git a/bin/tests/system/dlv/ns1/sign.sh b/bin/tests/system/dlv/ns1/sign.sh +index b8151620cc..2a62e583b8 100755 +--- a/bin/tests/system/dlv/ns1/sign.sh ++++ b/bin/tests/system/dlv/ns1/sign.sh +@@ -23,8 +23,8 @@ infile=root.db.in + zonefile=root.db + outfile=root.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +diff --git a/bin/tests/system/dlv/ns2/sign.sh b/bin/tests/system/dlv/ns2/sign.sh +index 6f84d7a525..e128303a22 100755 +--- a/bin/tests/system/dlv/ns2/sign.sh ++++ b/bin/tests/system/dlv/ns2/sign.sh +@@ -24,8 +24,8 @@ zonefile=druz.db + outfile=druz.pre + dlvzone=utld. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +diff --git a/bin/tests/system/dlv/ns3/sign.sh b/bin/tests/system/dlv/ns3/sign.sh +index bcc9922e26..846dbcc0df 100755 +--- a/bin/tests/system/dlv/ns3/sign.sh ++++ b/bin/tests/system/dlv/ns3/sign.sh +@@ -19,6 +19,7 @@ echo_i "dlv/ns3/sign.sh" + dlvzone=dlv.utld. + dlvsets= + dssets= ++bits=1024 + + zone=child1.utld. + infile=child.db.in +@@ -26,8 +27,8 @@ zonefile=child1.utld.db + outfile=child1.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP + cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile +@@ -42,8 +43,8 @@ zonefile=child3.utld.db + outfile=child3.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP + cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile +@@ -58,8 +59,8 @@ zonefile=child4.utld.db + outfile=child4.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -73,8 +74,8 @@ zonefile=child5.utld.db + outfile=child5.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP + cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile +@@ -88,8 +89,8 @@ infile=child.db.in + zonefile=child7.utld.db + outfile=child7.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP + cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile +@@ -103,8 +104,8 @@ infile=child.db.in + zonefile=child8.utld.db + outfile=child8.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -118,8 +119,8 @@ zonefile=child9.utld.db + outfile=child9.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -132,8 +133,8 @@ zonefile=child10.utld.db + outfile=child10.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -147,8 +148,8 @@ outfile=child1.druz.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP + cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile +@@ -164,8 +165,8 @@ outfile=child3.druz.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP + cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile +@@ -181,8 +182,8 @@ outfile=child4.druz.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -197,8 +198,8 @@ outfile=child5.druz.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP + cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile +@@ -213,8 +214,8 @@ zonefile=child7.druz.db + outfile=child7.druz.signed + dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + dsfilename=../ns6/dsset-grand.`echo $zone |sed -e "s/\.$//g"`$TP + cat $infile $keyname1.key $keyname2.key $dsfilename >$zonefile +@@ -228,8 +229,8 @@ infile=child.db.in + zonefile=child8.druz.db + outfile=child8.druz.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -243,8 +244,8 @@ zonefile=child9.druz.db + outfile=child9.druz.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -258,8 +259,8 @@ outfile=child10.druz.signed + dlvsets="$dlvsets dlvset-`echo $zone |sed -e "s/.$//g"`$TP" + dssets="$dssets dsset-`echo $zone |sed -e "s/.$//g"`$TP" + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -272,8 +273,8 @@ infile=dlv.db.in + zonefile=dlv.utld.db + outfile=dlv.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $dlvsets $keyname1.key $keyname2.key >$zonefile + +diff --git a/bin/tests/system/dlv/ns6/sign.sh b/bin/tests/system/dlv/ns6/sign.sh +index 1e398625f1..4ed19acd1f 100755 +--- a/bin/tests/system/dlv/ns6/sign.sh ++++ b/bin/tests/system/dlv/ns6/sign.sh +@@ -16,13 +16,15 @@ SYSTESTDIR=dlv + + echo_i "dlv/ns6/sign.sh" + ++bits=1024 ++ + zone=grand.child1.utld. + infile=child.db.in + zonefile=grand.child1.utld.db + outfile=grand.child1.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -36,8 +38,8 @@ zonefile=grand.child3.utld.db + outfile=grand.child3.signed + dlvzone=dlv.utld. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -51,8 +53,8 @@ zonefile=grand.child4.utld.db + outfile=grand.child4.signed + dlvzone=dlv.utld. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -66,8 +68,8 @@ zonefile=grand.child5.utld.db + outfile=grand.child5.signed + dlvzone=dlv.utld. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -81,8 +83,8 @@ zonefile=grand.child7.utld.db + outfile=grand.child7.signed + dlvzone=dlv.utld. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -96,8 +98,8 @@ zonefile=grand.child8.utld.db + outfile=grand.child8.signed + dlvzone=dlv.utld. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -111,8 +113,8 @@ zonefile=grand.child9.utld.db + outfile=grand.child9.signed + dlvzone=dlv.utld. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -125,8 +127,8 @@ zonefile=grand.child10.utld.db + outfile=grand.child10.signed + dlvzone=dlv.utld. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -138,8 +140,8 @@ infile=child.db.in + zonefile=grand.child1.druz.db + outfile=grand.child1.druz.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -153,8 +155,8 @@ zonefile=grand.child3.druz.db + outfile=grand.child3.druz.signed + dlvzone=dlv.druz. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -168,8 +170,8 @@ zonefile=grand.child4.druz.db + outfile=grand.child4.druz.signed + dlvzone=dlv.druz. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -183,8 +185,8 @@ zonefile=grand.child5.druz.db + outfile=grand.child5.druz.signed + dlvzone=dlv.druz. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -198,8 +200,8 @@ zonefile=grand.child7.druz.db + outfile=grand.child7.druz.signed + dlvzone=dlv.druz. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -213,8 +215,8 @@ zonefile=grand.child8.druz.db + outfile=grand.child8.druz.signed + dlvzone=dlv.druz. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -228,8 +230,8 @@ zonefile=grand.child9.druz.db + outfile=grand.child9.druz.signed + dlvzone=dlv.druz. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -242,8 +244,8 @@ zonefile=grand.child10.druz.db + outfile=grand.child10.druz.signed + dlvzone=dlv.druz. + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b $bits -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +diff --git a/bin/tests/system/dnssec/ns1/sign.sh b/bin/tests/system/dnssec/ns1/sign.sh +index 198d60ae15..d89a539ffd 100644 +--- a/bin/tests/system/dnssec/ns1/sign.sh ++++ b/bin/tests/system/dnssec/ns1/sign.sh +@@ -27,7 +27,7 @@ cp ../ns2/dsset-in-addr.arpa$TP . + grep "8 [12] " ../ns2/dsset-algroll$TP > dsset-algroll$TP + cp ../ns6/dsset-optout-tld$TP . + +-keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone` + + cat $infile $keyname.key > $zonefile + +@@ -48,6 +48,6 @@ cp managed.conf ../ns4/managed.conf + # + # Save keyid for managed key id test. + # +-keyid=`expr $keyname : 'K.+001+\(.*\)'` ++keyid=`expr $keyname : 'K.+008+\([0-9]*\)'` + keyid=`expr $keyid + 0` + echo "$keyid" > managed.key.id +diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh +index 9078459ac8..9dcd028eb5 100644 +--- a/bin/tests/system/dnssec/ns2/sign.sh ++++ b/bin/tests/system/dnssec/ns2/sign.sh +@@ -29,8 +29,8 @@ do + cp ../ns3/dsset-$subdomain.example$TP . + done + +-keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone` +-keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone` ++keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 1024 -n zone $zone` ++keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 1024 -n zone $zone` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -89,8 +89,8 @@ zone=in-addr.arpa. + infile=in-addr.arpa.db.in + zonefile=in-addr.arpa.db + +-keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone` +-keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone` ++keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 1024 -n zone $zone` ++keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 1024 -n zone $zone` + + cat $infile $keyname1.key $keyname2.key >$zonefile + $SIGNER -P -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null +@@ -101,7 +101,7 @@ privzone=private.secure.example. + privinfile=private.secure.example.db.in + privzonefile=private.secure.example.db + +-privkeyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $privzone` ++privkeyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $privzone` + + cat $privinfile $privkeyname.key >$privzonefile + +@@ -115,7 +115,7 @@ dlvinfile=dlv.db.in + dlvzonefile=dlv.db + dlvsetfile=dlvset-`echo $privzone |sed -e "s/\.$//g"`$TP + +-dlvkeyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $dlvzone` ++dlvkeyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $dlvzone` + + cat $dlvinfile $dlvkeyname.key $dlvsetfile > $dlvzonefile + +diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh +index 330abf7feb..f95a6b7ea8 100644 +--- a/bin/tests/system/dnssec/ns3/sign.sh ++++ b/bin/tests/system/dnssec/ns3/sign.sh +@@ -28,7 +28,7 @@ zone=bogus.example. + infile=bogus.example.db.in + zonefile=bogus.example.db + +-keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone $zone` + + cat $infile $keyname.key >$zonefile + +@@ -38,8 +38,8 @@ zone=dynamic.example. + infile=dynamic.example.db.in + zonefile=dynamic.example.db + +-keyname1=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone` +-keyname2=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 1024 -n zone -f KSK $zone` ++keyname1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone $zone` ++keyname2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone -f KSK $zone` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +@@ -49,7 +49,7 @@ zone=keyless.example. + infile=generic.example.db.in + zonefile=keyless.example.db + +-keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone $zone` + + cat $infile $keyname.key >$zonefile + +@@ -69,7 +69,7 @@ zone=secure.nsec3.example. + infile=secure.nsec3.example.db.in + zonefile=secure.nsec3.example.db + +-keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone $zone` + + cat $infile $keyname.key >$zonefile + +@@ -82,7 +82,7 @@ zone=nsec3.nsec3.example. + infile=nsec3.nsec3.example.db.in + zonefile=nsec3.nsec3.example.db + +-keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone` + + cat $infile $keyname.key >$zonefile + +@@ -95,7 +95,7 @@ zone=optout.nsec3.example. + infile=optout.nsec3.example.db.in + zonefile=optout.nsec3.example.db + +-keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone` + + cat $infile $keyname.key >$zonefile + +@@ -108,7 +108,7 @@ zone=nsec3.example. + infile=nsec3.example.db.in + zonefile=nsec3.example.db + +-keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone` + + cat $infile $keyname.key >$zonefile + +@@ -121,7 +121,7 @@ zone=secure.optout.example. + infile=secure.optout.example.db.in + zonefile=secure.optout.example.db + +-keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone $zone` + + cat $infile $keyname.key >$zonefile + +@@ -498,7 +498,7 @@ zone=badds.example. + infile=bogus.example.db.in + zonefile=badds.example.db + +-keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone` ++keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 2048 -n zone $zone` + + cat $infile $keyname.key >$zonefile + +diff --git a/bin/tests/system/dnssec/ns5/trusted.conf.bad b/bin/tests/system/dnssec/ns5/trusted.conf.bad +index ed30460bda..e6b112630e 100644 +--- a/bin/tests/system/dnssec/ns5/trusted.conf.bad ++++ b/bin/tests/system/dnssec/ns5/trusted.conf.bad +@@ -10,5 +10,5 @@ + */ + + trusted-keys { +- "." 256 3 1 "AQO6Cl+slAf+iuieDim9L3kujFHQD7s/IOj03ClMOpKYcTXtK4mRpuULVfvWxDi9Ew/gj0xLnnX7z9OJHIxLI+DSrAHd8Dm0XfBEAtVtJSn70GaPZgnLMw1rk5ap2DsEoWk="; ++ "." 256 3 8 "AwEAAarwAdjV4gIhpBCjXVAScRFEx3co7k8smJdxrnqoGsl5NB7EZ9jRdgvCXbJn6v8y9jlNWVHvaC8ilhfhLh0A1vLWiWv4ijd/12xcnrY7xpG7Cu3YkxUxaXJ7Jdg/Iw1+9mGgXF1v4UbCIcw/3U3cxyk7OxYg+VSb5KBAQSR0upxV"; + }; +diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh +index bb2315fbf3..315666825e 100644 +--- a/bin/tests/system/dnssec/tests.sh ++++ b/bin/tests/system/dnssec/tests.sh +@@ -1690,7 +1690,7 @@ ret=0 + $RNDCCMD 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i + keyid=`cat ns1/managed.key.id` + cp ns4/named.secroots named.secroots.test$n +-linecount=`grep "./RSAMD5/$keyid ; trusted" named.secroots.test$n | wc -l` ++linecount=`grep "./RSASHA256/$keyid ; trusted" named.secroots.test$n | wc -l` + [ "$linecount" -eq 1 ] || ret=1 + linecount=`cat named.secroots.test$n | wc -l` + [ "$linecount" -eq 10 ] || ret=1 +@@ -3018,7 +3018,7 @@ echo_i "check dig's +nocrypto flag ($n)" + ret=0 + $DIG $DIGOPTS +norec +nocrypto DNSKEY . \ + @10.53.0.1 > dig.out.dnskey.ns1.test$n || ret=1 +-grep '256 3 1 \[key id = [1-9][0-9]*]' dig.out.dnskey.ns1.test$n > /dev/null || ret=1 ++grep '256 3 8 \[key id = [1-9][0-9]*]' dig.out.dnskey.ns1.test$n > /dev/null || ret=1 + grep 'RRSIG.* \[omitted]' dig.out.dnskey.ns1.test$n > /dev/null || ret=1 + $DIG $DIGOPTS +norec +nocrypto DS example \ + @10.53.0.1 > dig.out.ds.ns1.test$n || ret=1 +@@ -3130,8 +3130,8 @@ do + alg=`expr $alg + 1` + continue;; + 3) size="-b 512";; +- 5) size="-b 512";; +- 6) size="-b 512";; ++ 5) size="-b 1024";; ++ 6) size="-b 1024";; + 7) size="-b 512";; + 8) size="-b 512";; + 10) size="-b 1024";; +diff --git a/bin/tests/system/feature-test.c b/bin/tests/system/feature-test.c +index 9612450ab4..5eee6aa4f8 100644 +--- a/bin/tests/system/feature-test.c ++++ b/bin/tests/system/feature-test.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + + #ifdef WIN32 +@@ -45,6 +46,7 @@ usage() { + fprintf(stderr, " --have-geoip\n"); + fprintf(stderr, " --have-libxml2\n"); + fprintf(stderr, " --ipv6only=no\n"); ++ fprintf(stderr, " --md5\n"); + fprintf(stderr, " --rpz-nsdname\n"); + fprintf(stderr, " --rpz-nsip\n"); + fprintf(stderr, " --with-idn\n"); +@@ -136,6 +138,18 @@ main(int argc, char **argv) { + #endif + } + ++ if (strcmp(argv[1], "--md5") == 0) { ++#ifdef PK11_MD5_DISABLE ++ return (1); ++#else ++ if (isc_md5_available()) { ++ return (0); ++ } else { ++ return (1); ++ } ++#endif ++ } ++ + if (strcmp(argv[1], "--rpz-nsip") == 0) { + #ifdef ENABLE_RPZ_NSIP + return (0); +diff --git a/bin/tests/system/filter-aaaa/ns1/sign.sh b/bin/tests/system/filter-aaaa/ns1/sign.sh +index f7555810a0..4a7d89004a 100755 +--- a/bin/tests/system/filter-aaaa/ns1/sign.sh ++++ b/bin/tests/system/filter-aaaa/ns1/sign.sh +@@ -21,8 +21,8 @@ infile=signed.db.in + zonefile=signed.db.signed + outfile=signed.db.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +diff --git a/bin/tests/system/filter-aaaa/ns4/sign.sh b/bin/tests/system/filter-aaaa/ns4/sign.sh +index f7555810a0..4a7d89004a 100755 +--- a/bin/tests/system/filter-aaaa/ns4/sign.sh ++++ b/bin/tests/system/filter-aaaa/ns4/sign.sh +@@ -21,8 +21,8 @@ infile=signed.db.in + zonefile=signed.db.signed + outfile=signed.db.signed + +-keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` +-keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` ++keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` ++keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` + + cat $infile $keyname1.key $keyname2.key >$zonefile + +diff --git a/bin/tests/system/notify/ns5/named.conf.in b/bin/tests/system/notify/ns5/named.conf.in +index cfcfe8fa2f..0a1614d527 100644 +--- a/bin/tests/system/notify/ns5/named.conf.in ++++ b/bin/tests/system/notify/ns5/named.conf.in +@@ -10,17 +10,17 @@ + */ + + key "a" { +- algorithm "hmac-md5"; ++ algorithm "hmac-sha256"; + secret "aaaaaaaaaaaaaaaaaaaa"; + }; + + key "b" { +- algorithm "hmac-md5"; ++ algorithm "hmac-sha256"; + secret "bbbbbbbbbbbbbbbbbbbb"; + }; + + key "c" { +- algorithm "hmac-md5"; ++ algorithm "hmac-sha256"; + secret "cccccccccccccccccccc"; + }; + +diff --git a/bin/tests/system/notify/tests.sh b/bin/tests/system/notify/tests.sh +index ad20e3eaca..5a9ce4688a 100644 +--- a/bin/tests/system/notify/tests.sh ++++ b/bin/tests/system/notify/tests.sh +@@ -186,16 +186,16 @@ ret=0 + $NSUPDATE << EOF + server 10.53.0.5 ${PORT} + zone x21 +-key a aaaaaaaaaaaaaaaaaaaa ++key hmac-sha256:a aaaaaaaaaaaaaaaaaaaa + update add added.x21 0 in txt "test string" + send + EOF + + for i in 1 2 3 4 5 6 7 8 9 + do +- $DIG $DIGOPTS added.x21. -y b:bbbbbbbbbbbbbbbbbbbb @10.53.0.5 \ ++ $DIG $DIGOPTS added.x21. -y hmac-sha256:b:bbbbbbbbbbbbbbbbbbbb @10.53.0.5 \ + txt > dig.out.b.ns5.test$n || ret=1 +- $DIG $DIGOPTS added.x21. -y c:cccccccccccccccccccc @10.53.0.5 \ ++ $DIG $DIGOPTS added.x21. -y hmac-sha256:c:cccccccccccccccccccc @10.53.0.5 \ + txt > dig.out.c.ns5.test$n || ret=1 + grep "test string" dig.out.b.ns5.test$n > /dev/null && + grep "test string" dig.out.c.ns5.test$n > /dev/null && +diff --git a/bin/tests/system/nsupdate/ns1/named.conf.in b/bin/tests/system/nsupdate/ns1/named.conf.in +index 1d999adc39..26b6b7c9ab 100644 +--- a/bin/tests/system/nsupdate/ns1/named.conf.in ++++ b/bin/tests/system/nsupdate/ns1/named.conf.in +@@ -32,7 +32,7 @@ controls { + }; + + key altkey { +- algorithm hmac-md5; ++ algorithm hmac-sha512; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/nsupdate/ns2/named.conf.in b/bin/tests/system/nsupdate/ns2/named.conf.in +index b4ecf96668..1adb33eb0b 100644 +--- a/bin/tests/system/nsupdate/ns2/named.conf.in ++++ b/bin/tests/system/nsupdate/ns2/named.conf.in +@@ -24,7 +24,7 @@ options { + }; + + key altkey { +- algorithm hmac-md5; ++ algorithm hmac-sha512; + secret "1234abcd8765"; + }; + +diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh +index 32674eb382..2331b30b00 100644 +--- a/bin/tests/system/nsupdate/setup.sh ++++ b/bin/tests/system/nsupdate/setup.sh +@@ -59,7 +59,12 @@ EOF + + $DDNSCONFGEN -q -r $RANDFILE -z example.nil > ns1/ddns.key + +-$DDNSCONFGEN -q -r $RANDFILE -a hmac-md5 -k md5-key -z keytests.nil > ns1/md5.key ++if $FEATURETEST --md5; then ++ $DDNSCONFGEN -q -r $RANDFILE -a hmac-md5 -k md5-key -z keytests.nil > ns1/md5.key ++else ++ echo -n > ns1/md5.key ++fi ++ + $DDNSCONFGEN -q -r $RANDFILE -a hmac-sha1 -k sha1-key -z keytests.nil > ns1/sha1.key + $DDNSCONFGEN -q -r $RANDFILE -a hmac-sha224 -k sha224-key -z keytests.nil > ns1/sha224.key + $DDNSCONFGEN -q -r $RANDFILE -a hmac-sha256 -k sha256-key -z keytests.nil > ns1/sha256.key +diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh +index 2a01d1e46d..e8659587c3 100755 +--- a/bin/tests/system/nsupdate/tests.sh ++++ b/bin/tests/system/nsupdate/tests.sh +@@ -680,7 +680,14 @@ fi + n=`expr $n + 1` + ret=0 + echo_i "check TSIG key algorithms ($n)" +-for alg in md5 sha1 sha224 sha256 sha384 sha512; do ++if $FEATURETEST --md5 ++then ++ ALGS="md5 sha1 sha224 sha256 sha384 sha512" ++else ++ ALGS="sha1 sha224 sha256 sha384 sha512" ++ echo_i "skipping disabled md5 algorithm" ++fi ++for alg in $ALGS; do + $NSUPDATE -k ns1/${alg}.key < /dev/null || ret=1 + server 10.53.0.1 ${PORT} + update add ${alg}.keytests.nil. 600 A 10.10.10.3 +@@ -688,7 +695,7 @@ send + END + done + sleep 2 +-for alg in md5 sha1 sha224 sha256 sha384 sha512; do ++for alg in $ALGS; do + $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.3 > /dev/null 2>&1 || ret=1 + done + if [ $ret -ne 0 ]; then +diff --git a/bin/tests/system/rndc/setup.sh b/bin/tests/system/rndc/setup.sh +index 850c4d2744..09a3e0f9ad 100644 +--- a/bin/tests/system/rndc/setup.sh ++++ b/bin/tests/system/rndc/setup.sh +@@ -37,7 +37,7 @@ make_key () { + sed 's/allow { 10.53.0.4/allow { any/' >> ns4/named.conf + } + +-make_key 1 ${EXTRAPORT1} hmac-md5 ++$FEATURETEST --md5 && make_key 1 ${EXTRAPORT1} hmac-md5 + make_key 2 ${EXTRAPORT2} hmac-sha1 + make_key 3 ${EXTRAPORT3} hmac-sha224 + make_key 4 ${EXTRAPORT4} hmac-sha256 +diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh +index d364e6fea0..dbf3bc6780 100644 +--- a/bin/tests/system/rndc/tests.sh ++++ b/bin/tests/system/rndc/tests.sh +@@ -356,15 +356,20 @@ if [ $ret != 0 ]; then echo_i "failed"; fi + status=`expr $status + $ret` + + n=`expr $n + 1` +-echo_i "testing rndc with hmac-md5 ($n)" +-ret=0 +-$RNDC -s 10.53.0.4 -p ${EXTRAPORT1} -c ns4/key1.conf status > /dev/null 2>&1 || ret=1 +-for i in 2 3 4 5 6 +-do +- $RNDC -s 10.53.0.4 -p ${EXTRAPORT1} -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1 +-done +-if [ $ret != 0 ]; then echo_i "failed"; fi +-status=`expr $status + $ret` ++if $FEATURETEST --md5 ++then ++ echo_i "testing rndc with hmac-md5 ($n)" ++ ret=0 ++ $RNDC -s 10.53.0.4 -p ${EXTRAPORT1} -c ns4/key1.conf status > /dev/null 2>&1 || ret=1 ++ for i in 2 3 4 5 6 ++ do ++ $RNDC -s 10.53.0.4 -p ${EXTRAPORT1} -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1 ++ done ++ if [ $ret != 0 ]; then echo_i "failed"; fi ++ status=`expr $status + $ret` ++else ++ echo_i "skipping rndc with hmac-md5 ($n)" ++fi + + n=`expr $n + 1` + echo_i "testing rndc with hmac-sha1 ($n)" +diff --git a/bin/tests/system/tsig/clean.sh b/bin/tests/system/tsig/clean.sh +index 576ec70f76..cb7a852189 100644 +--- a/bin/tests/system/tsig/clean.sh ++++ b/bin/tests/system/tsig/clean.sh +@@ -20,3 +20,4 @@ rm -f */named.run + rm -f ns*/named.lock + rm -f Kexample.net.+163+* + rm -f keygen.out? ++rm -f ns1/named.conf +diff --git a/bin/tests/system/tsig/ns1/named.conf.in b/bin/tests/system/tsig/ns1/named.conf.in +index fbf30c6dc4..f61657d7cf 100644 +--- a/bin/tests/system/tsig/ns1/named.conf.in ++++ b/bin/tests/system/tsig/ns1/named.conf.in +@@ -21,10 +21,7 @@ options { + notify no; + }; + +-key "md5" { +- secret "97rnFx24Tfna4mHPfgnerA=="; +- algorithm hmac-md5; +-}; ++# md5 key appended by setup.sh at the end + + key "sha1" { + secret "FrSt77yPTFx6hTs4i2tKLB9LmE0="; +@@ -51,10 +48,7 @@ key "sha512" { + algorithm hmac-sha512; + }; + +-key "md5-trunc" { +- secret "97rnFx24Tfna4mHPfgnerA=="; +- algorithm hmac-md5-80; +-}; ++# md5-trunc key appended by setup.sh at the end + + key "sha1-trunc" { + secret "FrSt77yPTFx6hTs4i2tKLB9LmE0="; +diff --git a/bin/tests/system/tsig/ns1/rndc5.conf.in b/bin/tests/system/tsig/ns1/rndc5.conf.in +new file mode 100644 +index 0000000000..4117830adb +--- /dev/null ++++ b/bin/tests/system/tsig/ns1/rndc5.conf.in +@@ -0,0 +1,11 @@ ++ ++key "md5" { ++ secret "97rnFx24Tfna4mHPfgnerA=="; ++ algorithm hmac-md5; ++}; ++ ++key "md5-trunc" { ++ secret "97rnFx24Tfna4mHPfgnerA=="; ++ algorithm hmac-md5-80; ++}; ++ +diff --git a/bin/tests/system/tsig/setup.sh b/bin/tests/system/tsig/setup.sh +index 656e9bbcd8..628c5bbac1 100644 +--- a/bin/tests/system/tsig/setup.sh ++++ b/bin/tests/system/tsig/setup.sh +@@ -17,3 +17,7 @@ $SHELL clean.sh + copy_setports ns1/named.conf.in ns1/named.conf + + test -r $RANDFILE || $GENRANDOM 400 $RANDFILE ++if $FEATURETEST --md5 ++then ++ cat ns1/rndc5.conf.in >> ns1/named.conf ++fi +diff --git a/bin/tests/system/tsig/tests.sh b/bin/tests/system/tsig/tests.sh +index f731fa604c..cade35bc1d 100644 +--- a/bin/tests/system/tsig/tests.sh ++++ b/bin/tests/system/tsig/tests.sh +@@ -26,20 +26,25 @@ sha512="jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4f + + status=0 + +-echo_i "fetching using hmac-md5 (old form)" +-ret=0 +-$DIG $DIGOPTS example.nil. -y "md5:$md5" @10.53.0.1 soa > dig.out.md5.old || ret=1 +-grep -i "md5.*TSIG.*NOERROR" dig.out.md5.old > /dev/null || ret=1 +-if [ $ret -eq 1 ] ; then +- echo_i "failed"; status=1 +-fi +- +-echo_i "fetching using hmac-md5 (new form)" +-ret=0 +-$DIG $DIGOPTS example.nil. -y "hmac-md5:md5:$md5" @10.53.0.1 soa > dig.out.md5.new || ret=1 +-grep -i "md5.*TSIG.*NOERROR" dig.out.md5.new > /dev/null || ret=1 +-if [ $ret -eq 1 ] ; then +- echo_i "failed"; status=1 ++if $FEATURETEST --md5 ++then ++ echo_i "fetching using hmac-md5 (old form)" ++ ret=0 ++ $DIG $DIGOPTS example.nil. -y "md5:$md5" @10.53.0.1 soa > dig.out.md5.old || ret=1 ++ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.old > /dev/null || ret=1 ++ if [ $ret -eq 1 ] ; then ++ echo_i "failed"; status=1 ++ fi ++ ++ echo_i "fetching using hmac-md5 (new form)" ++ ret=0 ++ $DIG $DIGOPTS example.nil. -y "hmac-md5:md5:$md5" @10.53.0.1 soa > dig.out.md5.new || ret=1 ++ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.new > /dev/null || ret=1 ++ if [ $ret -eq 1 ] ; then ++ echo_i "failed"; status=1 ++ fi ++else ++ echo_i "skipping using hmac-md5" + fi + + echo_i "fetching using hmac-sha1" +@@ -87,12 +92,17 @@ fi + # Truncated TSIG + # + # +-echo_i "fetching using hmac-md5 (trunc)" +-ret=0 +-$DIG $DIGOPTS example.nil. -y "hmac-md5-80:md5-trunc:$md5" @10.53.0.1 soa > dig.out.md5.trunc || ret=1 +-grep -i "md5-trunc.*TSIG.*NOERROR" dig.out.md5.trunc > /dev/null || ret=1 +-if [ $ret -eq 1 ] ; then +- echo_i "failed"; status=1 ++if $FEATURETEST --md5 ++then ++ echo_i "fetching using hmac-md5 (trunc)" ++ ret=0 ++ $DIG $DIGOPTS example.nil. -y "hmac-md5-80:md5-trunc:$md5" @10.53.0.1 soa > dig.out.md5.trunc || ret=1 ++ grep -i "md5-trunc.*TSIG.*NOERROR" dig.out.md5.trunc > /dev/null || ret=1 ++ if [ $ret -eq 1 ] ; then ++ echo_i "failed"; status=1 ++ fi ++else ++ echo_i "skipping using hmac-md5 (trunc)" + fi + + echo_i "fetching using hmac-sha1 (trunc)" +@@ -141,12 +151,17 @@ fi + # Check for bad truncation. + # + # +-echo_i "fetching using hmac-md5-80 (BADTRUNC)" +-ret=0 +-$DIG $DIGOPTS example.nil. -y "hmac-md5-80:md5:$md5" @10.53.0.1 soa > dig.out.md5-80 || ret=1 +-grep -i "md5.*TSIG.*BADTRUNC" dig.out.md5-80 > /dev/null || ret=1 +-if [ $ret -eq 1 ] ; then +- echo_i "failed"; status=1 ++if $FEATURETEST --md5 ++then ++ echo_i "fetching using hmac-md5-80 (BADTRUNC)" ++ ret=0 ++ $DIG $DIGOPTS example.nil. -y "hmac-md5-80:md5:$md5" @10.53.0.1 soa > dig.out.md5-80 || ret=1 ++ grep -i "md5.*TSIG.*BADTRUNC" dig.out.md5-80 > /dev/null || ret=1 ++ if [ $ret -eq 1 ] ; then ++ echo_i "failed"; status=1 ++ fi ++else ++ echo_i "skipping using hmac-md5-80 (BADTRUNC)" + fi + + echo_i "fetching using hmac-sha1-80 (BADTRUNC)" +diff --git a/bin/tests/system/tsiggss/setup.sh b/bin/tests/system/tsiggss/setup.sh +index 5da33cfde0..fb108b02bd 100644 +--- a/bin/tests/system/tsiggss/setup.sh ++++ b/bin/tests/system/tsiggss/setup.sh +@@ -18,5 +18,5 @@ test -r $RANDFILE || $GENRANDOM 400 $RANDFILE + + copy_setports ns1/named.conf.in ns1/named.conf + +-key=`$KEYGEN -Cq -K ns1 -a DSA -b 512 -r $RANDFILE -n HOST -T KEY key.example.nil.` ++key=`$KEYGEN -Cq -K ns1 -a DSA -b 1024 -r $RANDFILE -n HOST -T KEY key.example.nil.` + cat ns1/example.nil.db.in ns1/${key}.key > ns1/example.nil.db +diff --git a/bin/tests/system/upforwd/ns1/named.conf.in b/bin/tests/system/upforwd/ns1/named.conf.in +index e0a30cda15..6a77b1ce52 100644 +--- a/bin/tests/system/upforwd/ns1/named.conf.in ++++ b/bin/tests/system/upforwd/ns1/named.conf.in +@@ -10,7 +10,7 @@ + */ + + key "update.example." { +- algorithm "hmac-md5"; ++ algorithm "hmac-sha256"; + secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; + }; + +diff --git a/bin/tests/system/upforwd/tests.sh b/bin/tests/system/upforwd/tests.sh +index b0694bbd5c..9adae8228e 100644 +--- a/bin/tests/system/upforwd/tests.sh ++++ b/bin/tests/system/upforwd/tests.sh +@@ -68,7 +68,7 @@ if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $status + $ret`; fi + + echo_i "updating zone (signed) ($n)" + ret=0 +-$NSUPDATE -y update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K -- - < +Date: Tue, 25 Sep 2018 18:08:46 +0200 +Subject: [PATCH] Disable IDN from environment as documented + +Manual page of host contained instructions to disable IDN processing +when it was built with libidn2. When refactoring IDN support however, +support for disabling IDN in host and nslookup was lost. Use also +environment variable and document it for nslookup, host and dig. + +Support variable CHARSET=ASCII to disable IDN, supported in downstream +RH patch since RHEL 5. +--- + bin/dig/dig.docbook | 4 +++- + bin/dig/dighost.c | 9 +++++++-- + bin/dig/host.docbook | 2 +- + bin/dig/nslookup.docbook | 15 +++++++++++++++ + 4 files changed, 26 insertions(+), 4 deletions(-) + +diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook +index fedd288..d5dba72 100644 +--- a/bin/dig/dig.docbook ++++ b/bin/dig/dig.docbook +@@ -1288,7 +1288,9 @@ dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr + reply from the server. + If you'd like to turn off the IDN support for some reason, use + parameters +noidnin and +- +noidnout. ++ +noidnout or define ++ the IDN_DISABLE environment variable. ++ + + + +diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c +index 7408193..d46379d 100644 +--- a/bin/dig/dighost.c ++++ b/bin/dig/dighost.c +@@ -822,12 +822,17 @@ make_empty_lookup(void) { + looknew->seenbadcookie = ISC_FALSE; + looknew->badcookie = ISC_TRUE; + #ifdef WITH_IDN_SUPPORT +- looknew->idnin = ISC_TRUE; ++ looknew->idnin = (getenv("IDN_DISABLE") == NULL); ++ if (looknew->idnin) { ++ const char *charset = getenv("CHARSET"); ++ if (charset && !strcmp(charset, "ASCII")) ++ looknew->idnin = ISC_FALSE; ++ } + #else + looknew->idnin = ISC_FALSE; + #endif + #ifdef WITH_IDN_OUT_SUPPORT +- looknew->idnout = ISC_TRUE; ++ looknew->idnout = looknew->idnin; + #else + looknew->idnout = ISC_FALSE; + #endif +diff --git a/bin/dig/host.docbook b/bin/dig/host.docbook +index 9c3aeaa..42cbbf9 100644 +--- a/bin/dig/host.docbook ++++ b/bin/dig/host.docbook +@@ -378,7 +378,7 @@ + host appropriately converts character encoding of + domain name before sending a request to DNS server or displaying a + reply from the server. +- If you'd like to turn off the IDN support for some reason, defines ++ If you'd like to turn off the IDN support for some reason, define + the IDN_DISABLE environment variable. + The IDN support is disabled if the variable is set when + host runs. +diff --git a/bin/dig/nslookup.docbook b/bin/dig/nslookup.docbook +index 3aff4e9..86a09c6 100644 +--- a/bin/dig/nslookup.docbook ++++ b/bin/dig/nslookup.docbook +@@ -478,6 +478,21 @@ nslookup -query=hinfo -timeout=10 + + + ++ IDN SUPPORT ++ ++ ++ If nslookup has been built with IDN (internationalized ++ domain name) support, it can accept and display non-ASCII domain names. ++ nslookup appropriately converts character encoding of ++ domain name before sending a request to DNS server or displaying a ++ reply from the server. ++ If you'd like to turn off the IDN support for some reason, define ++ the IDN_DISABLE environment variable. ++ The IDN support is disabled if the variable is set when ++ nslookup runs. ++ ++ ++ + FILES + + /etc/resolv.conf +-- +2.14.4 + diff --git a/SOURCES/bind-9.11-kyua-pkcs11.patch b/SOURCES/bind-9.11-kyua-pkcs11.patch new file mode 100644 index 0000000..ab21828 --- /dev/null +++ b/SOURCES/bind-9.11-kyua-pkcs11.patch @@ -0,0 +1,206 @@ +From d0433a314534e104f52acf2a0a96a68dd84305ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Tue, 2 Jan 2018 18:13:07 +0100 +Subject: [PATCH] Fix pkcs11 variants atf tests + +Add dns-pkcs11 tests Makefile to configure + +Add pkcs11 Kyuafile, fix dh_test to pass in pkcs11 mode +--- + configure.in | 1 + + lib/Atffile | 2 ++ + lib/Kyuafile | 2 ++ + lib/dns-pkcs11/tests/Makefile.in | 10 +++++----- + lib/dns-pkcs11/tests/dh_test.c | 3 ++- + lib/isc-pkcs11/tests/Makefile.in | 6 +++--- + lib/isc-pkcs11/tests/hash_test.c | 32 +++++++++++++++++++++++++------- + 7 files changed, 40 insertions(+), 16 deletions(-) + +diff --git a/configure.in b/configure.in +index 67b3aab..4767eeb 100644 +--- a/configure.in ++++ b/configure.in +@@ -5579,6 +5579,7 @@ AC_CONFIG_FILES([ + lib/dns-pkcs11/include/Makefile + lib/dns-pkcs11/include/dns/Makefile + lib/dns-pkcs11/include/dst/Makefile ++ lib/dns-pkcs11/tests/Makefile + lib/irs/Makefile + lib/irs/include/Makefile + lib/irs/include/irs/Makefile +diff --git a/lib/Atffile b/lib/Atffile +index 93bbb01..4db3dce 100644 +--- a/lib/Atffile ++++ b/lib/Atffile +@@ -3,7 +3,9 @@ Content-Type: application/X-atf-atffile; version="1" + prop: test-suite = bind9 + + tp: dns ++tp: dns-pkcs11 + tp: irs + tp: isc ++tp: isc-pkcs11 + tp: isccfg + tp: lwres +diff --git a/lib/Kyuafile b/lib/Kyuafile +index ff9fc56..eaaf0dc 100644 +--- a/lib/Kyuafile ++++ b/lib/Kyuafile +@@ -2,7 +2,9 @@ syntax(2) + test_suite('bind9') + + include('dns/Kyuafile') ++include('dns-pkcs11/Kyuafile') + include('irs/Kyuafile') + include('isc/Kyuafile') ++include('isc-pkcs11/Kyuafile') + include('isccfg/Kyuafile') + include('lwres/Kyuafile') +diff --git a/lib/dns-pkcs11/tests/Makefile.in b/lib/dns-pkcs11/tests/Makefile.in +index 2a6571b..f25a784 100644 +--- a/lib/dns-pkcs11/tests/Makefile.in ++++ b/lib/dns-pkcs11/tests/Makefile.in +@@ -20,12 +20,12 @@ VERSION=@BIND9_VERSION@ + + CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} \ + @DST_OPENSSL_INC@ +-CDEFINES = @CRYPTO@ -DTESTS="\"${top_builddir}/lib/dns/tests/\"" ++CDEFINES = @CRYPTO@ -DTESTS="\"${top_builddir}/lib/dns-pkcs11/tests/\"" + +-ISCLIBS = ../../isc/libisc.@A@ +-ISCDEPLIBS = ../../isc/libisc.@A@ +-DNSLIBS = ../libdns.@A@ @DNS_CRYPTO_LIBS@ +-DNSDEPLIBS = ../libdns.@A@ ++ISCLIBS = ../../isc-pkcs11/libisc-pkcs11.@A@ ++ISCDEPLIBS = ../../isc-pkcs11/libisc-pkcs11.@A@ ++DNSLIBS = ../libdns-pkcs11.@A@ @DNS_CRYPTO_LIBS@ ++DNSDEPLIBS = ../libdns-pkcs11.@A@ + + LIBS = @LIBS@ @ATFLIBS@ + +diff --git a/lib/dns-pkcs11/tests/dh_test.c b/lib/dns-pkcs11/tests/dh_test.c +index 036d27a..eb6554f 100644 +--- a/lib/dns-pkcs11/tests/dh_test.c ++++ b/lib/dns-pkcs11/tests/dh_test.c +@@ -63,7 +63,8 @@ ATF_TC_BODY(isc_dh_computesecret, tc) { + ret = dst_key_computesecret(key, key, &buf); + ATF_REQUIRE_EQ(ret, DST_R_NOTPRIVATEKEY); + ret = key->func->computesecret(key, key, &buf); +- ATF_REQUIRE_EQ(ret, DST_R_COMPUTESECRETFAILURE); ++ /* PKCS11 variant gives different result, accept both */ ++ ATF_REQUIRE(ret == DST_R_COMPUTESECRETFAILURE || ret == DST_R_INVALIDPRIVATEKEY); + + dst_key_free(&key); + dns_test_end(); +diff --git a/lib/isc-pkcs11/tests/Makefile.in b/lib/isc-pkcs11/tests/Makefile.in +index f7fa538..818dae4 100644 +--- a/lib/isc-pkcs11/tests/Makefile.in ++++ b/lib/isc-pkcs11/tests/Makefile.in +@@ -17,10 +17,10 @@ VERSION=@BIND9_VERSION@ + @BIND9_MAKE_INCLUDES@ + + CINCLUDES = -I. -Iinclude ${ISC_INCLUDES} @ISC_OPENSSL_INC@ +-CDEFINES = @CRYPTO@ -DTESTS="\"${top_builddir}/lib/isc/tests/\"" ++CDEFINES = @CRYPTO@ -DTESTS="\"${top_builddir}/lib/isc-pkcs11/tests/\"" + +-ISCLIBS = ../libisc.@A@ @ISC_OPENSSL_LIBS@ +-ISCDEPLIBS = ../libisc.@A@ ++ISCLIBS = ../libisc-pkcs11.@A@ @ISC_OPENSSL_LIBS@ ++ISCDEPLIBS = ../libisc-pkcs11.@A@ + + LIBS = @LIBS@ @ATFLIBS@ + +diff --git a/lib/isc-pkcs11/tests/hash_test.c b/lib/isc-pkcs11/tests/hash_test.c +index 5b8a374..c1891c2 100644 +--- a/lib/isc-pkcs11/tests/hash_test.c ++++ b/lib/isc-pkcs11/tests/hash_test.c +@@ -74,7 +74,7 @@ typedef struct hash_testcase { + + typedef struct hash_test_key { + const char *key; +- const int len; ++ const unsigned len; + } hash_test_key_t; + + /* non-hmac tests */ +@@ -957,8 +957,11 @@ ATF_TC_BODY(isc_hmacsha1, tc) { + hash_test_key_t *test_key = test_keys; + + while (testcase->input != NULL && testcase->result != NULL) { ++ int len = ISC_MAX(test_key->len, ISC_SHA1_DIGESTLENGTH); ++ ++ memset(buffer, 0, ISC_SHA1_DIGESTLENGTH); + memmove(buffer, test_key->key, test_key->len); +- isc_hmacsha1_init(&hmacsha1, buffer, test_key->len); ++ isc_hmacsha1_init(&hmacsha1, buffer, len); + isc_hmacsha1_update(&hmacsha1, + (const isc_uint8_t *) testcase->input, + testcase->input_len); +@@ -1120,8 +1123,11 @@ ATF_TC_BODY(isc_hmacsha224, tc) { + hash_test_key_t *test_key = test_keys; + + while (testcase->input != NULL && testcase->result != NULL) { ++ int len = ISC_MAX(test_key->len, ISC_SHA224_DIGESTLENGTH); ++ ++ memset(buffer, 0, ISC_SHA224_DIGESTLENGTH); + memmove(buffer, test_key->key, test_key->len); +- isc_hmacsha224_init(&hmacsha224, buffer, test_key->len); ++ isc_hmacsha224_init(&hmacsha224, buffer, len); + isc_hmacsha224_update(&hmacsha224, + (const isc_uint8_t *) testcase->input, + testcase->input_len); +@@ -1283,8 +1289,11 @@ ATF_TC_BODY(isc_hmacsha256, tc) { + hash_test_key_t *test_key = test_keys; + + while (testcase->input != NULL && testcase->result != NULL) { ++ int len = ISC_MAX(test_key->len, ISC_SHA256_DIGESTLENGTH); ++ ++ memset(buffer, 0, ISC_SHA256_DIGESTLENGTH); + memmove(buffer, test_key->key, test_key->len); +- isc_hmacsha256_init(&hmacsha256, buffer, test_key->len); ++ isc_hmacsha256_init(&hmacsha256, buffer, len); + isc_hmacsha256_update(&hmacsha256, + (const isc_uint8_t *) testcase->input, + testcase->input_len); +@@ -1452,8 +1461,11 @@ ATF_TC_BODY(isc_hmacsha384, tc) { + hash_test_key_t *test_key = test_keys; + + while (testcase->input != NULL && testcase->result != NULL) { ++ int len = ISC_MAX(test_key->len, ISC_SHA384_DIGESTLENGTH); ++ ++ memset(buffer, 0, ISC_SHA384_DIGESTLENGTH); + memmove(buffer, test_key->key, test_key->len); +- isc_hmacsha384_init(&hmacsha384, buffer, test_key->len); ++ isc_hmacsha384_init(&hmacsha384, buffer, len); + isc_hmacsha384_update(&hmacsha384, + (const isc_uint8_t *) testcase->input, + testcase->input_len); +@@ -1621,8 +1633,11 @@ ATF_TC_BODY(isc_hmacsha512, tc) { + hash_test_key_t *test_key = test_keys; + + while (testcase->input != NULL && testcase->result != NULL) { ++ int len = ISC_MAX(test_key->len, ISC_SHA512_DIGESTLENGTH); ++ ++ memset(buffer, 0, ISC_SHA512_DIGESTLENGTH); + memmove(buffer, test_key->key, test_key->len); +- isc_hmacsha512_init(&hmacsha512, buffer, test_key->len); ++ isc_hmacsha512_init(&hmacsha512, buffer, len); + isc_hmacsha512_update(&hmacsha512, + (const isc_uint8_t *) testcase->input, + testcase->input_len); +@@ -1765,8 +1780,11 @@ ATF_TC_BODY(isc_hmacmd5, tc) { + hash_test_key_t *test_key = test_keys; + + while (testcase->input != NULL && testcase->result != NULL) { ++ int len = ISC_MAX(test_key->len, ISC_MD5_DIGESTLENGTH); ++ ++ memset(buffer, 0, ISC_MD5_DIGESTLENGTH); + memmove(buffer, test_key->key, test_key->len); +- isc_hmacmd5_init(&hmacmd5, buffer, test_key->len); ++ isc_hmacmd5_init(&hmacmd5, buffer, len); + isc_hmacmd5_update(&hmacmd5, + (const isc_uint8_t *) testcase->input, + testcase->input_len); +-- +2.14.3 + diff --git a/SOURCES/bind-9.11-libidn.patch b/SOURCES/bind-9.11-libidn.patch new file mode 100644 index 0000000..5471edc --- /dev/null +++ b/SOURCES/bind-9.11-libidn.patch @@ -0,0 +1,303 @@ +From fb4271f5881a83c2cfb639587597b9a80c536a6d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Tue, 29 Jan 2019 20:59:57 +0100 +Subject: [PATCH] Replace libidn2 support with libidn + +They should be more or less compatible. Try to maintain original +behaviour of old 9.11 libidn patch, ignore any in output filter. +--- + bin/dig/Makefile.in | 6 ++--- + bin/dig/dighost.c | 64 ++++++++++++++++++++++++++++++--------------- + config.h.in | 4 +-- + configure.in | 56 +++++++++++++++++++-------------------- + 4 files changed, 76 insertions(+), 54 deletions(-) + +diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in +index 3edd951..75441b0 100644 +--- a/bin/dig/Makefile.in ++++ b/bin/dig/Makefile.in +@@ -19,7 +19,7 @@ READLINE_LIB = @READLINE_LIB@ + + CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} \ + ${BIND9_INCLUDES} ${ISC_INCLUDES} \ +- ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} @LIBIDN2_CFLAGS@ @DST_OPENSSL_INC@ ++ ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} @LIBIDN_CFLAGS@ @DST_OPENSSL_INC@ + + CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@ + CWARNINGS = +@@ -41,10 +41,10 @@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} \ + ${ISCCFGDEPLIBS} ${LWRESDEPLIBS} + + LIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ +- ${ISCLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@ ++ ${ISCLIBS} @IDNKIT_LIBS@ @LIBIDN_LIBS@ @LIBS@ + + NOSYMLIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ +- ${ISCNOSYMLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@ ++ ${ISCNOSYMLIBS} @IDNKIT_LIBS@ @LIBIDN_LIBS@ @LIBS@ + + SUBDIRS = + +diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c +index ffc16c4..a345a21 100644 +--- a/bin/dig/dighost.c ++++ b/bin/dig/dighost.c +@@ -38,8 +38,9 @@ + #include + #endif + +-#ifdef WITH_LIBIDN2 +-#include ++#ifdef WITH_LIBIDN ++#include ++#include + #endif + #endif /* WITH_IDN_SUPPORT */ + +@@ -4761,7 +4762,7 @@ idn_ace_to_locale(const char *from, char *to, size_t tolen) { + } + #endif /* WITH_IDNKIT */ + +-#ifdef WITH_LIBIDN2 ++#ifdef WITH_LIBIDN + static void + idn_initialize(void) { + } +@@ -4769,16 +4770,25 @@ idn_initialize(void) { + static isc_result_t + idn_locale_to_ace(const char *from, char *to, size_t tolen) { + int res; ++ char *utf8_str; + char *tmp_str = NULL; + +- res = idn2_to_ascii_lz(from, &tmp_str, IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT); +- if (res == IDN2_DISALLOWED) { +- res = idn2_to_ascii_lz(from, &tmp_str, IDN2_TRANSITIONAL|IDN2_NFC_INPUT); ++ debug ("libidn_locale_to_utf8"); ++ utf8_str = stringprep_locale_to_utf8 (from); ++ if (utf8_str == NULL) { ++ debug ("libidn stringprep_locale_to_utf8 failure"); ++ return ISC_R_FAILURE; + } + +- if (res == IDN2_OK) { ++ int iresult; ++ ++ debug ("libidn_utf8_to_ascii"); ++ res = idna_to_ascii_8z (utf8_str, &tmp_str, 0); ++ free (utf8_str); ++ ++ if (res == IDNA_SUCCESS) { + /* +- * idn2_to_ascii_lz() normalizes all strings to lowerl case, ++ * idna_to_ascii_8z() normalizes all strings to lowerl case, + * but we generally don't want to lowercase all input strings; + * make sure to return the original case if the two strings + * differ only in case +@@ -4786,26 +4796,26 @@ idn_locale_to_ace(const char *from, char *to, size_t tolen) { + if (!strcasecmp(from, tmp_str)) { + if (strlen(from) >= tolen) { + debug("from string is too long"); +- idn2_free(tmp_str); ++ free(tmp_str); + return ISC_R_NOSPACE; + } +- idn2_free(tmp_str); ++ free(tmp_str); + (void) strlcpy(to, from, tolen); + return ISC_R_SUCCESS; + } + /* check the length */ + if (strlen(tmp_str) >= tolen) { + debug("ACE string is too long"); +- idn2_free(tmp_str); ++ free(tmp_str); + return ISC_R_NOSPACE; + } + + (void) strlcpy(to, tmp_str, tolen); +- idn2_free(tmp_str); ++ free(tmp_str); + return ISC_R_SUCCESS; + } + +- fatal("'%s' is not a legal IDN name (%s), use +noidnin", from, idn2_strerror(res)); ++ fatal("'%s' is not a legal IDN name (%s), use +noidnin", from, idna_strerror (res)); + return ISC_R_FAILURE; + } + +@@ -4813,29 +4823,41 @@ idn_locale_to_ace(const char *from, char *to, size_t tolen) { + static isc_result_t + idn_ace_to_locale(const char *from, char *to, size_t tolen) { + int res; ++ char *tmp2 = NULL; + char *tmp_str = NULL; + +- res = idn2_to_unicode_8zlz(from, &tmp_str, +- IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT); ++ res = idna_to_unicode_8z8z (from, &tmp2, 0); ++ if (res != IDNA_SUCCESS) { ++ debug ("output_filter: %s", idna_strerror (res)); ++ return ISC_R_SUCCESS; ++ } ++ ++ tmp_str = stringprep_utf8_to_locale (tmp2); ++ if (tmp_str == NULL) { ++ debug ("output_filter: stringprep_utf8_to_locale failed"); ++ res = idna_to_ascii_8z(tmp2, &tmp_str, 0); ++ } ++ ++ free(tmp2); + +- if (res == IDN2_OK) { ++ if (res == IDNA_SUCCESS) { + /* check the length */ + if (strlen(tmp_str) >= tolen) { + debug("encoded ASC string is too long"); +- idn2_free(tmp_str); ++ free(tmp_str); + return ISC_R_FAILURE; + } + + (void) strlcpy(to, tmp_str, tolen); +- idn2_free(tmp_str); ++ free(tmp_str); + return ISC_R_SUCCESS; + } +- +- fatal("'%s' is not a legal IDN name (%s), use +noidnout", from, idn2_strerror(res)); ++ // fatal("'%s' is not a legal IDN name (%s), use +noidnout", from, idna_strerror(res)); ++ free(tmp_str); + return ISC_R_FAILURE; + } + #endif /* WITH_IDN_OUT_SUPPORT */ +-#endif /* WITH_LIBIDN2 */ ++#endif /* WITH_LIBIDN */ + #endif /* WITH_IDN_SUPPORT */ + + #ifdef DIG_SIGCHASE +diff --git a/config.h.in b/config.h.in +index 1dc65cf..9eb8a16 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -615,8 +615,8 @@ int sigwait(const unsigned int *set, int *sig); + /* define if IDN input support is to be included. */ + #undef WITH_IDN_SUPPORT + +-/* define if libidn2 support is to be included. */ +-#undef WITH_LIBIDN2 ++/* define if libidn support is to be included. */ ++#undef WITH_LIBIDN + + /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +diff --git a/configure.in b/configure.in +index 9a1d16d..1397c50 100644 +--- a/configure.in ++++ b/configure.in +@@ -4864,36 +4864,36 @@ fi + AC_SUBST(IDNKIT_LIBS) + + # +-# IDN support using libidn2 ++# IDN support using libidn + # + +-LIBIDN2_CFLAGS= +-LIBIDN2_LDFLAGS= +-LIBIDN2_LIBS= +-AC_ARG_WITH(libidn2, +- AS_HELP_STRING([--with-libidn2[=PATH]], [enable IDN support using GNU libidn2 [yes|no|path]]), +- use_libidn2="$withval", use_libidn2="no") +-AS_CASE([$use_libidn2], ++LIBIDN_CFLAGS= ++LIBIDN_LDFLAGS= ++LIBIDN_LIBS= ++AC_ARG_WITH(libidn, ++ AS_HELP_STRING([--with-libidn[=PATH]], [enable IDN support using GNU libidn [yes|no|path]]), ++ use_libidn="$withval", use_libidn="no") ++AS_CASE([$use_libidn], + [no],[:], + [yes],[:], + [*],[ +- LIBIDN2_CFLAGS="-I$use_libidn2/include" +- LIBIDN2_LDFLAGS="-L$use_libidn2/lib" ++ LIBIDN_CFLAGS="-I$use_libidn/include" ++ LIBIDN_LDFLAGS="-L$use_libidn/lib" + ]) + +-AS_IF([test "$use_libidn2" != "no"], ++AS_IF([test "$use_libidn" != "no"], + [save_CFLAGS="$CFLAGS" + save_LIBS="$LIBS" + save_LDFLAGS="$LDFLAGS" +- CFLAGS="$LIBIDN2_CFLAGS $CFLAGS" +- LDFLAGS="$LIBIDN2_LDFLAGS $LDFLAGS" +- AC_SEARCH_LIBS([idn2_to_ascii_8z], [idn2], ++ CFLAGS="$LIBIDN_CFLAGS $CFLAGS" ++ LDFLAGS="$LIBIDN_LDFLAGS $LDFLAGS" ++ AC_SEARCH_LIBS([idna_to_ascii_8z], [idn], + [AC_DEFINE(WITH_IDN_SUPPORT, 1, [define if IDN input support is to be included.]) +- AC_DEFINE(WITH_LIBIDN2, 1, [define if libidn2 support is to be included.]) +- LIBIDN2_LIBS="$LIBIDN2_LDFLAGS -lidn2"], +- [AC_MSG_ERROR([libidn2 requested, but not found])]) +- AC_TRY_LINK([#include ], +- [idn2_to_unicode_8zlz(".", NULL, IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);], ++ AC_DEFINE(WITH_LIBIDN, 1, [define if libidn support is to be included.]) ++ LIBIDN_LIBS="$LIBIDN_LDFLAGS -lidn"], ++ [AC_MSG_ERROR([libidn requested, but not found])]) ++ AC_TRY_LINK([#include ], ++ [idna_to_unicode_8zlz(".", NULL, 0);], + [AC_MSG_RESULT(yes) + AC_DEFINE(WITH_IDN_OUT_SUPPORT, 1, [define if IDN output support is to be included.])], + [AC_MSG_RESULT([no])]) +@@ -4901,21 +4901,21 @@ AS_IF([test "$use_libidn2" != "no"], + LIBS="$save_LIBS" + LDFLAGS="$save_LDFLAGS" + ]) +-AC_SUBST([LIBIDN2_CFLAGS]) +-AC_SUBST([LIBIDN2_LIBS]) ++AC_SUBST([LIBIDN_CFLAGS]) ++AC_SUBST([LIBIDN_LIBS]) + + # + # IDN support in general + # + +-# check if idnkit and libidn2 are not used at the same time +-if test "$use_idnkit" != no && test "$use_libidn2" != no; then +- AC_MSG_ERROR([idnkit and libidn2 cannot be used at the same time.]) ++# check if idnkit and libidn are not used at the same time ++if test "$use_idnkit" != no && test "$use_libidn" != no; then ++ AC_MSG_ERROR([idnkit and libidn cannot be used at the same time.]) + fi + # the IDN support is on +-if test "$use_idnkit" != no || test "$use_libidn2" != no; then ++if test "$use_idnkit" != no || test "$use_libidn" != no; then + AC_DEFINE(WITH_IDN_SUPPORT, 1, [define if IDN input support is to be included.]) +- if test "$use_libidn2" = no || test "$use_libidn2_out" != no; then ++ if test "$use_libidn" = no || test "$use_libidn_out" != no; then + AC_DEFINE(WITH_IDN_OUT_SUPPORT, 1, [define if IDN output support is to be included.]) + fi + fi +@@ -5618,7 +5618,7 @@ report() { + test "X$JSONSTATS" = "X" || echo " JSON statistics (--with-libjson)" + test "X$ZLIB" = "X" || echo " HTTP zlib compression (--with-zlib)" + test "X$NZD_TOOLS" = "X" || echo " LMDB database to store configuration for 'addzone' zones (--with-lmdb)" +- test "no" = "$use_libidn2" || echo " IDN support (--with-libidn2)" ++ test "no" = "$use_libidn" || echo " IDN support (--with-libidn)" + fi + + if test "no" != "$use_pkcs11"; then +@@ -5716,7 +5716,7 @@ report() { + test "X$JSONSTATS" = "X" && echo " JSON statistics (--with-libjson)" + test "X$ZLIB" = "X" && echo " HTTP zlib compression (--with-zlib)" + test "X$NZD_TOOLS" = "X" && echo " LMDB database to store configuration for 'addzone' zones (--with-lmdb)" +- test "no" = "$use_libidn2" && echo " IDN support (--with-libidn2)" ++ test "no" = "$use_libidn" && echo " IDN support (--with-libidn)" + + echo "-------------------------------------------------------------------------------" + echo "Configured paths:" +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-no-default-cookies.patch b/SOURCES/bind-9.11-no-default-cookies.patch new file mode 100644 index 0000000..20618ea --- /dev/null +++ b/SOURCES/bind-9.11-no-default-cookies.patch @@ -0,0 +1,70 @@ +From 8963e300f7e465b3c96e859ba81e128fa508cefd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Mon, 21 Jan 2019 19:15:40 +0100 +Subject: [PATCH 1/5] Turn off sending cookies by default + +Upstream has default sending cookies on by default. For compatiblity +with bind 9.9.4, require inclusion of send-cookie in configuration or +dig +cookie parameter to send cookie. Would not send EDNS extension in +non-DNSSEC query by default. +--- + bin/dig/dig.c | 4 ++-- + bin/dig/dig.docbook | 4 ++-- + bin/named/config.c | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/bin/dig/dig.c b/bin/dig/dig.c +index c577e31..8b23676 100644 +--- a/bin/dig/dig.c ++++ b/bin/dig/dig.c +@@ -1429,7 +1429,7 @@ plus_option(const char *option, isc_boolean_t is_batchfile, + lookup->section_authority = ISC_TRUE; + lookup->section_question = ISC_FALSE; + lookup->dnssec = ISC_TRUE; +- lookup->sendcookie = ISC_TRUE; ++ lookup->sendcookie = ISC_FALSE; + usesearch = ISC_FALSE; + } + break; +@@ -1883,7 +1883,7 @@ parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only, + default_lookup = make_empty_lookup(); + default_lookup->adflag = ISC_TRUE; + default_lookup->edns = 0; +- default_lookup->sendcookie = ISC_TRUE; ++ default_lookup->sendcookie = ISC_FALSE; + + #ifndef NOPOSIX + /* +diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook +index d5dba72..575a308 100644 +--- a/bin/dig/dig.docbook ++++ b/bin/dig/dig.docbook +@@ -617,10 +617,10 @@ + Send a COOKIE EDNS option, with optional + value. Replaying a COOKIE from a previous response will + allow the server to identify a previous client. The +- default is . ++ default is . + + +- +cookie is also set when +trace ++ +nocookie is also set when +trace + is set to better emulate the default queries from a + nameserver. + +diff --git a/bin/named/config.c b/bin/named/config.c +index c50f759..7d97029 100644 +--- a/bin/named/config.c ++++ b/bin/named/config.c +@@ -102,7 +102,7 @@ options {\n\ + resolver-query-timeout 10;\n\ + rrset-order { order random; };\n\ + secroots-file \"named.secroots\";\n\ +- send-cookie true;\n\ ++ send-cookie false;\n\ + # serial-queries ;\n\ + serial-query-rate 20;\n\ + server-id none;\n\ +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-no-default-ipv6.patch b/SOURCES/bind-9.11-no-default-ipv6.patch new file mode 100644 index 0000000..1a3c2be --- /dev/null +++ b/SOURCES/bind-9.11-no-default-ipv6.patch @@ -0,0 +1,42 @@ +From 9fea3896c84d027271c2315af098dad319a444da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Mon, 21 Jan 2019 19:23:10 +0100 +Subject: [PATCH 2/5] Turn off listening on IPv6 by default + +To maintain behaviour of BIND 9.9, turn off listening on IPv6 by +default. To enable listening like upstream defaults, include +listen-on-v6 { any; }; in options. +--- + bin/named/config.c | 2 +- + doc/arm/Bv9ARM-book.xml | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/bin/named/config.c b/bin/named/config.c +index 7d97029..1d7aaa1 100644 +--- a/bin/named/config.c ++++ b/bin/named/config.c +@@ -77,7 +77,7 @@ options {\n\ + interface-interval 60;\n\ + # keep-response-order {none;};\n\ + listen-on {any;};\n\ +- listen-on-v6 {any;};\n\ ++ listen-on-v6 {none;};\n\ + # lock-file \"" NS_LOCALSTATEDIR "/run/named/named.lock\";\n\ + match-mapped-addresses no;\n\ + max-rsa-exponent-size 0; /* no limit */\n\ +diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml +index a5d9e2e..5e7d015 100644 +--- a/doc/arm/Bv9ARM-book.xml ++++ b/doc/arm/Bv9ARM-book.xml +@@ -7473,7 +7473,7 @@ listen-on port 1234 { !1.2.3.4; 1.2/16; }; + The listen-on-v6 option is used to + specify the interfaces and the ports on which the server will + listen for incoming queries sent using IPv6. If not specified, +- the server will listen on port 53 on all IPv6 interfaces. ++ the server will not listen on port 53 on any IPv6 interfaces. + + + +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-oot-manual.patch b/SOURCES/bind-9.11-oot-manual.patch new file mode 100644 index 0000000..b090b9f --- /dev/null +++ b/SOURCES/bind-9.11-oot-manual.patch @@ -0,0 +1,256 @@ +From e462d022a9dc52c40aece6f8ba3123ff3ffa59ed Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Wed, 25 Jul 2018 12:24:16 +0200 +Subject: [PATCH] Use make automatic variables to install updated manuals + +Make will choose modified manual from build directory or original from source +directory automagically. Take advantage of install tool feature. +Install all files in single command instead of iterating on each of them. +--- + bin/check/Makefile.in | 8 +++++--- + bin/confgen/Makefile.in | 9 +++++---- + bin/delv/Makefile.in | 6 ++++-- + bin/dig/Makefile.in | 8 ++++---- + bin/dnssec/Makefile.in | 6 ++++-- + bin/named/Makefile.in | 13 +++++++++---- + bin/pkcs11/Makefile.in | 9 ++++----- + bin/python/Makefile.in | 8 ++++---- + bin/tools/Makefile.in | 25 +++++++++++++++---------- + 9 files changed, 54 insertions(+), 38 deletions(-) + +diff --git a/bin/check/Makefile.in b/bin/check/Makefile.in +index 12f48d2d23..d8eac4c714 100644 +--- a/bin/check/Makefile.in ++++ b/bin/check/Makefile.in +@@ -83,12 +83,14 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +-install:: named-checkconf@EXEEXT@ named-checkzone@EXEEXT@ installdirs ++install-man8: ${MANPAGES} ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 ++ (cd ${DESTDIR}${mandir}/man8; rm -f named-compilezone.8; ${LINK_PROGRAM} named-checkzone.8 named-compilezone.8) ++ ++install:: named-checkconf@EXEEXT@ named-checkzone@EXEEXT@ installdirs install-man8 + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-checkconf@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-checkzone@EXEEXT@ ${DESTDIR}${sbindir} + (cd ${DESTDIR}${sbindir}; rm -f named-compilezone@EXEEXT@; ${LINK_PROGRAM} named-checkzone@EXEEXT@ named-compilezone@EXEEXT@) +- for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done +- (cd ${DESTDIR}${mandir}/man8; rm -f named-compilezone.8; ${LINK_PROGRAM} named-checkzone.8 named-compilezone.8) + + uninstall:: + rm -f ${DESTDIR}${mandir}/man8/named-compilezone.8 +diff --git a/bin/confgen/Makefile.in b/bin/confgen/Makefile.in +index 87f13dda4b..7865c0c73e 100644 +--- a/bin/confgen/Makefile.in ++++ b/bin/confgen/Makefile.in +@@ -95,13 +95,14 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +-install:: rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ installdirs ++install-man8: rndc-confgen.8 ddns-confgen.8 ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 ++ (cd ${DESTDIR}${mandir}/man8; rm -f tsig-keygen.8; ${LINK_PROGRAM} ddns-confgen.8 tsig-keygen.8) ++ ++install:: rndc-confgen@EXEEXT@ ddns-confgen@EXEEXT@ installdirs install-man8 + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc-confgen@EXEEXT@ ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} ddns-confgen@EXEEXT@ ${DESTDIR}${sbindir} +- ${INSTALL_DATA} ${srcdir}/rndc-confgen.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/ddns-confgen.8 ${DESTDIR}${mandir}/man8 + (cd ${DESTDIR}${sbindir}; rm -f tsig-keygen@EXEEXT@; ${LINK_PROGRAM} ddns-confgen@EXEEXT@ tsig-keygen@EXEEXT@) +- (cd ${DESTDIR}${mandir}/man8; rm -f tsig-keygen.8; ${LINK_PROGRAM} ddns-confgen.8 tsig-keygen.8) + + uninstall:: + rm -f ${DESTDIR}${mandir}/man8/tsig-keygen.8 +diff --git a/bin/delv/Makefile.in b/bin/delv/Makefile.in +index e2d2802262..19361a83ea 100644 +--- a/bin/delv/Makefile.in ++++ b/bin/delv/Makefile.in +@@ -63,10 +63,12 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 + +-install:: delv@EXEEXT@ installdirs ++install-man1: delv.1 ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man1 ++ ++install:: delv@EXEEXT@ installdirs install-man1 + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ + delv@EXEEXT@ ${DESTDIR}${bindir} +- ${INSTALL_DATA} ${srcdir}/delv.1 ${DESTDIR}${mandir}/man1 + + uninstall:: + rm -f ${DESTDIR}${mandir}/man1/delv.1 +diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in +index 773ac46395..3edd951e7e 100644 +--- a/bin/dig/Makefile.in ++++ b/bin/dig/Makefile.in +@@ -91,16 +91,16 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 + +-install:: dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@ installdirs ++install-man1: ${MANPAGES} ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man1 ++ ++install:: dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@ installdirs install-man1 + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ + dig@EXEEXT@ ${DESTDIR}${bindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ + host@EXEEXT@ ${DESTDIR}${bindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ + nslookup@EXEEXT@ ${DESTDIR}${bindir} +- for m in ${MANPAGES}; do \ +- ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man1; \ +- done + + uninstall:: + for m in ${MANPAGES}; do \ +diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in +index 1be1d5ffc6..1d0c4ce5c1 100644 +--- a/bin/dnssec/Makefile.in ++++ b/bin/dnssec/Makefile.in +@@ -110,9 +110,11 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +-install:: ${TARGETS} installdirs ++install-man8: ${MANPAGES} ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 ++ ++install:: ${TARGETS} installdirs install-man8 + for t in ${TARGETS}; do ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} $$t ${DESTDIR}${sbindir}; done +- for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done + + uninstall:: + for m in ${MANPAGES}; do rm -f ${DESTDIR}${mandir}/man8/$$m ; done +diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in +index 1c413973d0..03e4cb849b 100644 +--- a/bin/named/Makefile.in ++++ b/bin/named/Makefile.in +@@ -172,12 +172,17 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5 + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +-install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs ++install-man5: named.conf.5 ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man5 ++ ++install-man8: named.8 lwresd.8 ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 ++ ++install-man: install-man5 install-man8 ++ ++install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs install-man + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir} + (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@) +- ${INSTALL_DATA} ${srcdir}/named.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5 + + uninstall:: + rm -f ${DESTDIR}${mandir}/man5/named.conf.5 +diff --git a/bin/pkcs11/Makefile.in b/bin/pkcs11/Makefile.in +index ae9061626c..a058c91214 100644 +--- a/bin/pkcs11/Makefile.in ++++ b/bin/pkcs11/Makefile.in +@@ -71,7 +71,10 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +-install:: ${TARGETS} installdirs ++install-man8: ${MANPAGES} ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 ++ ++install:: ${TARGETS} installdirs install-man8 + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-list@EXEEXT@ \ + ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-destroy@EXEEXT@ \ +@@ -80,10 +83,6 @@ install:: ${TARGETS} installdirs + ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-tokens@EXEEXT@ \ + ${DESTDIR}${sbindir} +- ${INSTALL_DATA} ${srcdir}/pkcs11-list.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/pkcs11-destroy.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/pkcs11-keygen.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/pkcs11-tokens.8 ${DESTDIR}${mandir}/man8 + + uninstall:: + rm -f ${DESTDIR}${mandir}/man8/pkcs11-tokens.8 +diff --git a/bin/python/Makefile.in b/bin/python/Makefile.in +index aa678d47ab..064c404e2f 100644 +--- a/bin/python/Makefile.in ++++ b/bin/python/Makefile.in +@@ -47,13 +47,13 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +-install:: ${TARGETS} installdirs ++install-man8: ${MANPAGES} ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 ++ ++install:: ${TARGETS} installdirs install-man8 + ${INSTALL_SCRIPT} dnssec-checkds ${DESTDIR}${sbindir} + ${INSTALL_SCRIPT} dnssec-coverage ${DESTDIR}${sbindir} + ${INSTALL_SCRIPT} dnssec-keymgr ${DESTDIR}${sbindir} +- ${INSTALL_DATA} ${srcdir}/dnssec-checkds.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/dnssec-coverage.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/dnssec-keymgr.8 ${DESTDIR}${mandir}/man8 + if test -n "${PYTHON}" ; then \ + if test -n "${DESTDIR}" ; then \ + ${PYTHON} ${srcdir}/setup.py install --root=${DESTDIR} --prefix=${prefix} @PYTHON_INSTALL_LIB@ ; \ +diff --git a/bin/tools/Makefile.in b/bin/tools/Makefile.in +index 7bf2af4cea..c395bc7462 100644 +--- a/bin/tools/Makefile.in ++++ b/bin/tools/Makefile.in +@@ -119,17 +119,27 @@ installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 + +-nzd: ++nzd-man: named-nzd2nzf.8 ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 ++ ++nzd: nzd-man + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-nzd2nzf@EXEEXT@ \ + ${DESTDIR}${sbindir} +- ${INSTALL_DATA} ${srcdir}/named-nzd2nzf.8 ${DESTDIR}${mandir}/man8 + +-dnstap: ++dnstap-man: dnstap-read.1 ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man1 ++ ++dnstap: dnstap-man + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} dnstap-read@EXEEXT@ \ + ${DESTDIR}${bindir} +- ${INSTALL_DATA} ${srcdir}/dnstap-read.1 ${DESTDIR}${mandir}/man1 + +-install:: ${TARGETS} installdirs @DNSTAP@ @NZD_TOOLS@ ++install-man1: arpaname.1 named-rrchecker.1 mdig.1 ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man1 ++ ++install-man8: named-journalprint.8 nsec3hash.8 ++ ${INSTALL_DATA} $^ ${DESTDIR}${mandir}/man8 ++ ++install:: ${TARGETS} installdirs @DNSTAP@ @NZD_TOOLS@ install-man1 install-man8 + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} arpaname@EXEEXT@ \ + ${DESTDIR}${bindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-journalprint@EXEEXT@ \ +@@ -144,13 +154,8 @@ install:: ${TARGETS} installdirs @DNSTAP@ @NZD_TOOLS@ + ${DESTDIR}${sbindir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} mdig@EXEEXT@ \ + ${DESTDIR}${bindir} +- ${INSTALL_DATA} ${srcdir}/arpaname.1 ${DESTDIR}${mandir}/man1 + ${INSTALL_DATA} ${srcdir}/isc-hmac-fixup.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/named-journalprint.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/named-rrchecker.1 ${DESTDIR}${mandir}/man1 +- ${INSTALL_DATA} ${srcdir}/nsec3hash.8 ${DESTDIR}${mandir}/man8 + ${INSTALL_DATA} ${srcdir}/genrandom.8 ${DESTDIR}${mandir}/man8 +- ${INSTALL_DATA} ${srcdir}/mdig.1 ${DESTDIR}${mandir}/man1 + + uninstall:: + rm -f ${DESTDIR}${mandir}/man1/mdig.1 +-- +2.14.4 + diff --git a/SOURCES/bind-9.11-pk11.patch b/SOURCES/bind-9.11-pk11.patch new file mode 100644 index 0000000..d802314 --- /dev/null +++ b/SOURCES/bind-9.11-pk11.patch @@ -0,0 +1,27 @@ +diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h +index 640519a..fc40472 100644 +--- a/lib/dns/dst_internal.h ++++ b/lib/dns/dst_internal.h +@@ -59,6 +59,9 @@ + #include + #include + #endif ++#if PKCS11CRYPTO ++#include ++#endif + + ISC_LANG_BEGINDECLS + +diff --git a/lib/isc/include/pk11/internal.h b/lib/isc/include/pk11/internal.h +index aa8907a..603712a 100644 +--- a/lib/isc/include/pk11/internal.h ++++ b/lib/isc/include/pk11/internal.h +@@ -13,6 +13,8 @@ + #ifndef PK11_INTERNAL_H + #define PK11_INTERNAL_H 1 + ++#include ++ + /*! \file pk11/internal.h */ + + ISC_LANG_BEGINDECLS diff --git a/SOURCES/bind-9.11-rh1205168.patch b/SOURCES/bind-9.11-rh1205168.patch new file mode 100644 index 0000000..181cec9 --- /dev/null +++ b/SOURCES/bind-9.11-rh1205168.patch @@ -0,0 +1,120 @@ +From 90416594843a56550e40b11561807786219ce1c4 Mon Sep 17 00:00:00 2001 +From: Evan Hunt +Date: Mon, 11 Sep 2017 15:01:36 -0700 +Subject: [PATCH] remap getaddrinfo() to irs_getgetaddrinfo() + +The libirs version of getaddrinfo() cannot be called from within BIND9. + +fix prototypes +--- + lib/irs/include/irs/netdb.h.in | 94 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 94 insertions(+) + +diff --git a/lib/irs/include/irs/netdb.h.in b/lib/irs/include/irs/netdb.h.in +index 23dcd37..f36113d 100644 +--- a/lib/irs/include/irs/netdb.h.in ++++ b/lib/irs/include/irs/netdb.h.in +@@ -150,6 +150,100 @@ struct addrinfo { + #define NI_DGRAM 0x00000010 + + /* ++ * Define to map into irs_ namespace. ++ */ ++ ++#define IRS_NAMESPACE ++ ++#ifdef IRS_NAMESPACE ++ ++/* ++ * Use our versions not the ones from the C library. ++ */ ++ ++#ifdef getnameinfo ++#undef getnameinfo ++#endif ++#define getnameinfo irs_getnameinfo ++ ++#ifdef getaddrinfo ++#undef getaddrinfo ++#endif ++#define getaddrinfo irs_getaddrinfo ++ ++#ifdef freeaddrinfo ++#undef freeaddrinfo ++#endif ++#define freeaddrinfo irs_freeaddrinfo ++ ++#ifdef gai_strerror ++#undef gai_strerror ++#endif ++#define gai_strerror irs_gai_strerror ++ ++#endif ++ ++extern int getaddrinfo (const char *name, ++ const char *service, ++ const struct addrinfo *req, ++ struct addrinfo **pai); ++extern int getnameinfo (const struct sockaddr *sa, ++ socklen_t salen, char *host, ++ socklen_t hostlen, char *serv, ++ socklen_t servlen, int flags); ++extern void freeaddrinfo (struct addrinfo *ai); ++extern const char *gai_strerror (int ecode); ++ ++/* ++ * Define to map into irs_ namespace. ++ */ ++ ++#define IRS_NAMESPACE ++ ++#ifdef IRS_NAMESPACE ++ ++/* ++ * Use our versions not the ones from the C library. ++ */ ++ ++#ifdef getnameinfo ++#undef getnameinfo ++#endif ++#define getnameinfo irs_getnameinfo ++ ++#ifdef getaddrinfo ++#undef getaddrinfo ++#endif ++#define getaddrinfo irs_getaddrinfo ++ ++#ifdef freeaddrinfo ++#undef freeaddrinfo ++#endif ++#define freeaddrinfo irs_freeaddrinfo ++ ++#ifdef gai_strerror ++#undef gai_strerror ++#endif ++#define gai_strerror irs_gai_strerror ++ ++int ++getaddrinfo(const char *hostname, const char *servname, ++ const struct addrinfo *hints, struct addrinfo **res); ++ ++int ++getnameinfo(const struct sockaddr *sa, IRS_GETNAMEINFO_SOCKLEN_T salen, ++ char *host, IRS_GETNAMEINFO_BUFLEN_T hostlen, ++ char *serv, IRS_GETNAMEINFO_BUFLEN_T servlen, ++ IRS_GETNAMEINFO_FLAGS_T flags); ++ ++void freeaddrinfo (struct addrinfo *ai); ++ ++IRS_GAISTRERROR_RETURN_T ++gai_strerror(int ecode); ++ ++#endif ++ ++/* + * Tell Emacs to use C mode on this file. + * Local variables: + * mode: c +-- +2.9.5 + diff --git a/SOURCES/bind-9.11-rh1410433.patch b/SOURCES/bind-9.11-rh1410433.patch new file mode 100644 index 0000000..b7fdc48 --- /dev/null +++ b/SOURCES/bind-9.11-rh1410433.patch @@ -0,0 +1,14 @@ +diff --git a/lib/dns/dyndb.c b/lib/dns/dyndb.c +index 0ce5e42..556d920 100644 +--- a/lib/dns/dyndb.c ++++ b/lib/dns/dyndb.c +@@ -130,9 +130,6 @@ load_library(isc_mem_t *mctx, const char *filename, const char *instname, + instname, filename); + + flags = RTLD_NOW|RTLD_LOCAL; +-#ifdef RTLD_DEEPBIND +- flags |= RTLD_DEEPBIND; +-#endif + + handle = dlopen(filename, flags); + if (handle == NULL) diff --git a/SOURCES/bind-9.11-rh1624100.patch b/SOURCES/bind-9.11-rh1624100.patch new file mode 100644 index 0000000..954661c --- /dev/null +++ b/SOURCES/bind-9.11-rh1624100.patch @@ -0,0 +1,288 @@ +From 25ff8ab2b0772262d358272a3ed70a24fc6e4887 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Wed, 25 Apr 2018 14:04:31 +0200 +Subject: [PATCH] Replace isc_safe routines with their OpenSSL counter parts + +(cherry picked from commit 66ba2fdad583d962a1f4971c85d58381f0849e4d) + +Remove isc_safe_memcompare, it's not needed anywhere and can't be replaced with CRYPTO_memcmp() + +(cherry picked from commit b105ccee68ccc3c18e6ea530063b3c8e5a42571c) + +Fix the isc_safe_memwipe() usage with (NULL, >0) + +(cherry picked from commit 083461d3329ff6f2410745848a926090586a9846) +--- + bin/dnssec/dnssec-signzone.c | 2 +- + lib/dns/nsec3.c | 4 +-- + lib/dns/spnego.c | 4 +-- + lib/isc/Makefile.in | 8 ++--- + lib/isc/include/isc/safe.h | 18 ++++------ + lib/isc/safe.c | 81 -------------------------------------------- + lib/isc/tests/safe_test.c | 20 ----------- + 7 files changed, 13 insertions(+), 124 deletions(-) + delete mode 100644 lib/isc/safe.c + +diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c +index 53be1f5c60..351296a356 100644 +--- a/bin/dnssec/dnssec-signzone.c ++++ b/bin/dnssec/dnssec-signzone.c +@@ -786,7 +786,7 @@ hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name, + + static int + hashlist_comp(const void *a, const void *b) { +- return (isc_safe_memcompare(a, b, hash_length + 1)); ++ return (memcmp(a, b, hash_length + 1)); + } + + static void +diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c +index d364308aaf..37b6a8a7fe 100644 +--- a/lib/dns/nsec3.c ++++ b/lib/dns/nsec3.c +@@ -1950,7 +1950,7 @@ dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name, + * Work out what this NSEC3 covers. + * Inside (<0) or outside (>=0). + */ +- scope = isc_safe_memcompare(owner, nsec3.next, nsec3.next_length); ++ scope = memcmp(owner, nsec3.next, nsec3.next_length); + + /* + * Prepare to compute all the hashes. +@@ -1974,7 +1974,7 @@ dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name, + return (ISC_R_IGNORE); + } + +- order = isc_safe_memcompare(hash, owner, length); ++ order = memcmp(hash, owner, length); + if (first && order == 0) { + /* + * The hashes are the same. +diff --git a/lib/dns/spnego.c b/lib/dns/spnego.c +index ce3e42d650..079d4c1b4a 100644 +--- a/lib/dns/spnego.c ++++ b/lib/dns/spnego.c +@@ -369,7 +369,7 @@ gssapi_spnego_decapsulate(OM_uint32 *, + + /* mod_auth_kerb.c */ + +-static int ++static isc_boolean_t + cmp_gss_type(gss_buffer_t token, gss_OID gssoid) + { + unsigned char *p; +@@ -393,7 +393,7 @@ cmp_gss_type(gss_buffer_t token, gss_OID gssoid) + if (((OM_uint32) *p++) != gssoid->length) + return (GSS_S_DEFECTIVE_TOKEN); + +- return (isc_safe_memcompare(p, gssoid->elements, gssoid->length)); ++ return (!isc_safe_memequal(p, gssoid->elements, gssoid->length)); + } + + /* accept_sec_context.c */ +diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in +index ba53ef1091..98acffffc9 100644 +--- a/lib/isc/Makefile.in ++++ b/lib/isc/Makefile.in +@@ -60,7 +60,7 @@ OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \ + parseint.@O@ portset.@O@ quota.@O@ radix.@O@ random.@O@ \ + ratelimiter.@O@ refcount.@O@ region.@O@ regex.@O@ result.@O@ \ + rwlock.@O@ \ +- safe.@O@ serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ \ ++ serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ stats.@O@ \ + string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \ + tm.@O@ timer.@O@ version.@O@ \ + ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS} +@@ -79,7 +79,7 @@ SRCS = @ISC_EXTRA_SRCS@ @ISC_PK11_C@ @ISC_PK11_RESULT_C@ \ + netaddr.c netscope.c pool.c ondestroy.c \ + parseint.c portset.c quota.c radix.c random.c ${CHACHASRCS} \ + ratelimiter.c refcount.c region.c regex.c result.c rwlock.c \ +- safe.c serial.c sha1.c sha2.c sockaddr.c stats.c string.c \ ++ serial.c sha1.c sha2.c sockaddr.c stats.c string.c \ + strtoul.c symtab.c task.c taskpool.c timer.c \ + tm.c version.c + +@@ -95,10 +95,6 @@ TESTDIRS = @UNITTESTS@ + + @BIND9_MAKE_RULES@ + +-safe.@O@: safe.c +- ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} @CCNOOPT@ \ +- -c ${srcdir}/safe.c +- + version.@O@: version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ +diff --git a/lib/isc/include/isc/safe.h b/lib/isc/include/isc/safe.h +index f29f00bac6..b8a0b2290c 100644 +--- a/lib/isc/include/isc/safe.h ++++ b/lib/isc/include/isc/safe.h +@@ -15,27 +15,21 @@ + + /*! \file isc/safe.h */ + +-#include +-#include ++#include ++#include ++ ++#include + + ISC_LANG_BEGINDECLS + +-isc_boolean_t +-isc_safe_memequal(const void *s1, const void *s2, size_t n); ++#define isc_safe_memequal(s1, s2, n) ISC_TF(!CRYPTO_memcmp(s1, s2, n)) + /*%< + * Returns ISC_TRUE iff. two blocks of memory are equal, otherwise + * ISC_FALSE. + * + */ + +-int +-isc_safe_memcompare(const void *b1, const void *b2, size_t len); +-/*%< +- * Clone of libc memcmp() which is safe to differential timing attacks. +- */ +- +-void +-isc_safe_memwipe(void *ptr, size_t len); ++#define isc_safe_memwipe(ptr, len) OPENSSL_cleanse(ptr, len) + /*%< + * Clear the memory of length `len` pointed to by `ptr`. + * +diff --git a/lib/isc/safe.c b/lib/isc/safe.c +deleted file mode 100644 +index 5c9e1e2d13..0000000000 +--- a/lib/isc/safe.c ++++ /dev/null +@@ -1,81 +0,0 @@ +-/* +- * Copyright (C) Internet Systems Consortium, Inc. ("ISC") +- * +- * This Source Code Form is subject to the terms of the Mozilla Public +- * License, v. 2.0. If a copy of the MPL was not distributed with this +- * file, You can obtain one at http://mozilla.org/MPL/2.0/. +- * +- * See the COPYRIGHT file distributed with this work for additional +- * information regarding copyright ownership. +- */ +- +-/*! \file */ +- +-#include +- +-#include +-#include +-#include +- +-#ifdef WIN32 +-#include +-#endif +- +-#ifdef _MSC_VER +-#pragma optimize("", off) +-#endif +- +-isc_boolean_t +-isc_safe_memequal(const void *s1, const void *s2, size_t n) { +- isc_uint8_t acc = 0; +- +- if (n != 0U) { +- const isc_uint8_t *p1 = s1, *p2 = s2; +- +- do { +- acc |= *p1++ ^ *p2++; +- } while (--n != 0U); +- } +- return (ISC_TF(acc == 0)); +-} +- +- +-int +-isc_safe_memcompare(const void *b1, const void *b2, size_t len) { +- const unsigned char *p1 = b1, *p2 = b2; +- size_t i; +- int res = 0, done = 0; +- +- for (i = 0; i < len; i++) { +- /* lt is -1 if p1[i] < p2[i]; else 0. */ +- int lt = (p1[i] - p2[i]) >> CHAR_BIT; +- +- /* gt is -1 if p1[i] > p2[i]; else 0. */ +- int gt = (p2[i] - p1[i]) >> CHAR_BIT; +- +- /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */ +- int cmp = lt - gt; +- +- /* set res = cmp if !done. */ +- res |= cmp & ~done; +- +- /* set done if p1[i] != p2[i]. */ +- done |= lt | gt; +- } +- +- return (res); +-} +- +-void +-isc_safe_memwipe(void *ptr, size_t len) { +- if (ISC_UNLIKELY(ptr == NULL || len == 0)) +- return; +- +-#ifdef WIN32 +- SecureZeroMemory(ptr, len); +-#elif HAVE_EXPLICIT_BZERO +- explicit_bzero(ptr, len); +-#else +- memset(ptr, 0, len); +-#endif +-} +diff --git a/lib/isc/tests/safe_test.c b/lib/isc/tests/safe_test.c +index f721cd1096..ea3e61f98d 100644 +--- a/lib/isc/tests/safe_test.c ++++ b/lib/isc/tests/safe_test.c +@@ -39,24 +39,6 @@ ATF_TC_BODY(isc_safe_memequal, tc) { + "\x00\x00\x00\x00", 4)); + } + +-ATF_TC(isc_safe_memcompare); +-ATF_TC_HEAD(isc_safe_memcompare, tc) { +- atf_tc_set_md_var(tc, "descr", "safe memcompare()"); +-} +-ATF_TC_BODY(isc_safe_memcompare, tc) { +- UNUSED(tc); +- +- ATF_CHECK(isc_safe_memcompare("test", "test", 4) == 0); +- ATF_CHECK(isc_safe_memcompare("test", "tesc", 4) > 0); +- ATF_CHECK(isc_safe_memcompare("test", "tesy", 4) < 0); +- ATF_CHECK(isc_safe_memcompare("\x00\x00\x00\x00", +- "\x00\x00\x00\x00", 4) == 0); +- ATF_CHECK(isc_safe_memcompare("\x00\x00\x00\x00", +- "\x00\x00\x00\x01", 4) < 0); +- ATF_CHECK(isc_safe_memcompare("\x00\x00\x00\x02", +- "\x00\x00\x00\x00", 4) > 0); +-} +- + ATF_TC(isc_safe_memwipe); + ATF_TC_HEAD(isc_safe_memwipe, tc) { + atf_tc_set_md_var(tc, "descr", "isc_safe_memwipe()"); +@@ -67,7 +49,6 @@ ATF_TC_BODY(isc_safe_memwipe, tc) { + /* These should pass. */ + isc_safe_memwipe(NULL, 0); + isc_safe_memwipe((void *) -1, 0); +- isc_safe_memwipe(NULL, 42); + + /* + * isc_safe_memwipe(ptr, size) should function same as +@@ -106,7 +87,6 @@ ATF_TC_BODY(isc_safe_memwipe, tc) { + */ + ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, isc_safe_memequal); +- ATF_TP_ADD_TC(tp, isc_safe_memcompare); + ATF_TP_ADD_TC(tp, isc_safe_memwipe); + return (atf_no_error()); + } +-- +2.14.4 + diff --git a/SOURCES/bind-9.11-rh1685940.patch b/SOURCES/bind-9.11-rh1685940.patch new file mode 100644 index 0000000..6771880 --- /dev/null +++ b/SOURCES/bind-9.11-rh1685940.patch @@ -0,0 +1,72 @@ +From 9fcd066217e8b6f52b601bdd8a0cb6455f98b88c Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Thu, 7 Mar 2019 14:33:28 +0100 +Subject: [PATCH] Do not replace random generator on single thread + +DHCP builds fails to initialize dst library entropy generator. It does +not require it for anything. Instead of initializing it, skip replacing +custom random generator in single thread builds. Should use OpenSSL +default random generator in case of SSL. + +Related: rhbz#1685940 +--- + lib/dns/openssl_link.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c +index ec6dc7f..ca3ffbc 100644 +--- a/lib/dns/openssl_link.c ++++ b/lib/dns/openssl_link.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -220,6 +221,7 @@ dst__openssl_init(const char *engine) { + ERR_load_crypto_strings(); + #endif + ++#ifdef ISC_PLATFORM_USETHREADS + rm = mem_alloc(sizeof(RAND_METHOD) FILELINE); + if (rm == NULL) { + result = ISC_R_NOMEMORY; +@@ -231,6 +233,7 @@ dst__openssl_init(const char *engine) { + rm->add = entropy_add; + rm->pseudorand = entropy_getpseudo; + rm->status = entropy_status; ++#endif + + #if !defined(OPENSSL_NO_ENGINE) + #if !defined(CONF_MFLAGS_DEFAULT_SECTION) +@@ -264,6 +267,7 @@ dst__openssl_init(const char *engine) { + } + } + ++#ifdef ISC_PLATFORM_USETHREADS + re = ENGINE_get_default_RAND(); + if (re == NULL) { + re = ENGINE_new(); +@@ -276,6 +280,7 @@ dst__openssl_init(const char *engine) { + ENGINE_free(re); + } else + ENGINE_finish(re); ++#endif + #else + RAND_set_rand_method(rm); + #endif /* !defined(OPENSSL_NO_ENGINE) */ +@@ -286,7 +291,8 @@ dst__openssl_init(const char *engine) { + if (e != NULL) + ENGINE_free(e); + e = NULL; +- mem_free(rm FILELINE); ++ if (rm != NULL) ++ mem_free(rm FILELINE); + rm = NULL; + #endif + cleanup_mutexinit: +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-unit-disable-random.patch b/SOURCES/bind-9.11-unit-disable-random.patch new file mode 100644 index 0000000..5658d12 --- /dev/null +++ b/SOURCES/bind-9.11-unit-disable-random.patch @@ -0,0 +1,45 @@ +From c89b0e288f923af69b97e8acc29250b262be7d1e Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Thu, 21 Feb 2019 22:42:27 +0100 +Subject: [PATCH] Disable random_test + +It fails too often on some architecture, failing the whole build along. +Because it runs two times for pkcs11 and normal build and any of +subtests can occasionally fail, stop it. + +It can be used again by defining 'unstable' variable in Kyuafile. +--- + lib/isc/tests/Atffile | 3 ++- + lib/isc/tests/Kyuafile | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/isc/tests/Atffile b/lib/isc/tests/Atffile +index 8681844..74a4a77 100644 +--- a/lib/isc/tests/Atffile ++++ b/lib/isc/tests/Atffile +@@ -20,7 +20,8 @@ tp: pool_test + tp: print_test + tp: queue_test + tp: radix_test +-tp: random_test ++# random test fails too often ++#tp: random_test + tp: regex_test + tp: result_test + tp: safe_test +diff --git a/lib/isc/tests/Kyuafile b/lib/isc/tests/Kyuafile +index 1c510c1..a86824a 100644 +--- a/lib/isc/tests/Kyuafile ++++ b/lib/isc/tests/Kyuafile +@@ -19,7 +19,7 @@ atf_test_program{name='pool_test'} + atf_test_program{name='print_test'} + atf_test_program{name='queue_test'} + atf_test_program{name='radix_test'} +-atf_test_program{name='random_test'} ++atf_test_program{name='random_test', required_configs='unstable'} + atf_test_program{name='regex_test'} + atf_test_program{name='result_test'} + atf_test_program{name='safe_test'} +-- +2.20.1 + diff --git a/SOURCES/bind-9.11-zone2ldap.patch b/SOURCES/bind-9.11-zone2ldap.patch new file mode 100644 index 0000000..e576c03 --- /dev/null +++ b/SOURCES/bind-9.11-zone2ldap.patch @@ -0,0 +1,196 @@ +From 738d12594972ad816e8cff9821f760aa0682fd08 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Tue, 18 Dec 2018 16:06:26 +0100 +Subject: [PATCH] Make absolute hostname by dns API instead of strings + +Duplicate all strings in dc_list. Free allocated memory on each record. +--- + bin/sdb_tools/zone2ldap.c | 72 +++++++++++++++++++++++++++++------------------ + 1 file changed, 45 insertions(+), 27 deletions(-) + +diff --git a/bin/sdb_tools/zone2ldap.c b/bin/sdb_tools/zone2ldap.c +index acf160b..cc482dc 100644 +--- a/bin/sdb_tools/zone2ldap.c ++++ b/bin/sdb_tools/zone2ldap.c +@@ -87,6 +87,10 @@ int get_attr_list_size (char **tmp); + /* Get a DN */ + char *build_dn_from_dc_list (char **dc_list, unsigned int ttl, int flag, char *zone); + ++/* Free a DN list */ ++static void ++free_dc_list(char **dc_list); ++ + /* Add to RR list */ + void add_to_rr_list (char *dn, char *name, char *type, char *data, + unsigned int ttl, unsigned int flags); +@@ -123,6 +127,7 @@ static char dNSTTL []="dNSTTL"; + static char zoneName []="zoneName"; + static char dc []="dc"; + static char sameZone []="@"; ++static char dot []="."; + /* LDAPMod mod_values: */ + static char *objectClasses []= { &(topClass[0]), &(dNSZoneClass[0]), NULL }; + static char *topObjectClasses []= { &(topClass[0]), &(dcObjectClass[0]), &(dNSZoneClass[0]), NULL }; +@@ -396,6 +401,8 @@ main (int argc, char **argv) + } + + } ++ ++ free_dc_list(dc_list); + } + else + { +@@ -451,12 +458,17 @@ generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, unsigned int ttl) + char data[2048]; + char **dc_list; + char *dn; ++ size_t argzone_len; ++ isc_boolean_t omit_dot; + + isc_buffer_t buff; + isc_result_t result; + + isc_buffer_init (&buff, name, sizeof (name)); +- result = dns_name_totext (dnsname, ISC_TRUE, &buff); ++ argzone_len = strlen(argzone); ++ /* If argzone is absolute, output absolute name too */ ++ omit_dot = ISC_TF(!(argzone_len > 0 && argzone[argzone_len-1] == '.')); ++ result = dns_name_totext (dnsname, omit_dot, &buff); + isc_result_check (result, "dns_name_totext"); + name[isc_buffer_usedlength (&buff)] = 0; + +@@ -478,6 +490,7 @@ generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, unsigned int ttl) + printf ("Adding %s (%s %s) to run queue list.\n", dn, type, data); + + add_to_rr_list (dn, dc_list[len], (char*)type, (char*)data, ttl, DNS_OBJECT); ++ free_dc_list(dc_list); + } + + +@@ -538,12 +551,9 @@ add_to_rr_list (char *dn, char *name, char *type, + if (tmp->attrs == (LDAPMod **) NULL) + fatal("calloc"); + +- for (i = 0; i < (int)flags; i++) +- { +- tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod)); +- if (tmp->attrs[i] == (LDAPMod *) NULL) +- fatal("malloc"); +- } ++ tmp->attrs[0] = (LDAPMod *) malloc (sizeof (LDAPMod)); ++ if (tmp->attrs[0] == (LDAPMod *) NULL) ++ fatal("malloc"); + tmp->attrs[0]->mod_op = LDAP_MOD_ADD; + tmp->attrs[0]->mod_type = objectClass; + +@@ -559,9 +569,18 @@ add_to_rr_list (char *dn, char *name, char *type, + return; + } + ++ for (i = 1; i < (int)flags-1; i++) ++ { ++ tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod)); ++ if (tmp->attrs[i] == (LDAPMod *) NULL) ++ fatal("malloc"); ++ } ++ tmp->attrs[i] = NULL; ++ ++ + tmp->attrs[1]->mod_op = LDAP_MOD_ADD; + tmp->attrs[1]->mod_type = relativeDomainName; +- tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 2); ++ tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 3); + + if (tmp->attrs[1]->mod_values == (char **)NULL) + fatal("calloc"); +@@ -705,25 +724,16 @@ char ** + hostname_to_dn_list (char *hostname, char *zone, unsigned int flags) + { + char *tmp; +- int i = 0; ++ int i = 0, j = 0; + char *hname=0L, *last=0L; + int hlen=strlen(hostname), zlen=(strlen(zone)); + + /* printf("hostname: %s zone: %s\n",hostname, zone); */ +- hname=0L; + if(flags == DNS_OBJECT) + { +- if( (zone[ zlen - 1 ] == '.') && (hostname[hlen - 1] != '.') ) +- { +- hname=(char*)malloc(hlen + 1); +- hlen += 1; +- sprintf(hname, "%s.", hostname); +- hostname = hname; +- } + if(strcmp(hostname, zone) == 0) + { +- if( hname == 0 ) +- hname=strdup(hostname); ++ hname=strdup(hostname); + last = strdup(sameZone); + }else + { +@@ -731,8 +741,6 @@ hostname_to_dn_list (char *hostname, char *zone, unsigned int flags) + ||( strcmp( hostname + (hlen - zlen), zone ) != 0) + ) + { +- if( hname != 0 ) +- free(hname); + hname=(char*)malloc( hlen + zlen + 1); + if( *zone == '.' ) + sprintf(hname, "%s%s", hostname, zone); +@@ -740,8 +748,7 @@ hostname_to_dn_list (char *hostname, char *zone, unsigned int flags) + sprintf(hname,"%s",zone); + }else + { +- if( hname == 0 ) +- hname = strdup(hostname); ++ hname = strdup(hostname); + } + last = hname; + } +@@ -754,18 +761,21 @@ hostname_to_dn_list (char *hostname, char *zone, unsigned int flags) + for (tmp = strrchr (hname, '.'); tmp != (char *) 0; + tmp = strrchr (hname, '.')) + { +- if( *( tmp + 1 ) != '\0' ) ++ tmp[0] = '\0'; ++ if( tmp[1] != '\0' ) + { +- *tmp = '\0'; + dn_buffer[i++] = ++tmp; + }else + { /* trailing '.' ! */ +- dn_buffer[i++] = strdup("."); +- *tmp = '\0'; ++ dn_buffer[i++] = dot; + if( tmp == hname ) + break; + } + } ++ for (j=0; j - #include - #include -+#include - #include - - #include -@@ -61,6 +62,9 @@ ldap_info; +diff --git a/bin/sdb_tools/zone2ldap.c b/bin/sdb_tools/zone2ldap.c +index 23dd873..d56bc56 100644 +--- a/bin/sdb_tools/zone2ldap.c ++++ b/bin/sdb_tools/zone2ldap.c +@@ -65,6 +66,9 @@ ldap_info; /* usage Info */ void usage (void); @@ -54,7 +49,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd /* Add to the ldap dit */ void add_ldap_values (ldap_info * ldinfo); -@@ -77,7 +81,7 @@ char **hostname_to_dn_list (char *hostna +@@ -81,7 +85,7 @@ char **hostname_to_dn_list (char *hostname, char *zone, unsigned int flags); int get_attr_list_size (char **tmp); /* Get a DN */ @@ -63,7 +58,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd /* Add to RR list */ void add_to_rr_list (char *dn, char *name, char *type, char *data, -@@ -99,11 +103,27 @@ void +@@ -103,11 +107,27 @@ void init_ldap_conn (); void usage(); @@ -96,7 +91,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd LDAP *conn; unsigned int debug = 0; -@@ -119,12 +139,12 @@ main (int argc, char **argv) +@@ -131,12 +151,12 @@ main (int argc, char **argv) isc_result_t result; char *basedn; ldap_info *tmp; @@ -112,38 +107,35 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd dns_fixedname_t fixedzone, fixedname; dns_rdataset_t rdataset; char **dc_list; -@@ -137,7 +157,7 @@ main (int argc, char **argv) +@@ -149,7 +169,7 @@ main (int argc, char **argv) extern char *optarg; extern int optind, opterr, optopt; int create_base = 0; - int topt; + int topt, dcn, zdn, znlen; - if ((int) argc < 2) + if (argc < 2) { -@@ -145,7 +165,7 @@ main (int argc, char **argv) +@@ -157,7 +177,7 @@ main (int argc, char **argv) exit (-1); } -- while ((topt = getopt ((int) argc, argv, "D:w:b:z:f:h:?dcv")) != -1) -+ while ((topt = getopt ((int) argc, argv, "D:Ww:b:z:f:h:?dcv")) != -1) +- while ((topt = getopt (argc, argv, "D:w:b:z:f:h:?dcv")) != -1) ++ while ((topt = getopt (argc, argv, "D:Ww:b:z:f:h:?dcv")) != -1) { switch (topt) { -@@ -164,8 +184,11 @@ main (int argc, char **argv) - case 'w': - bindpw = strdup (optarg); +@@ -180,6 +200,9 @@ main (int argc, char **argv) + if (bindpw == NULL) + fatal("strdup"); break; + case 'W': + bindpw = getpass("Enter LDAP Password: "); + break; case 'b': -- ldapbase = strdup (optarg); -+ ldapbase = strdup (optarg); - break; - case 'z': - argzone = strdup (optarg); -@@ -277,27 +300,62 @@ main (int argc, char **argv) + ldapbase = strdup (optarg); + if (ldapbase == NULL) +@@ -301,27 +324,62 @@ main (int argc, char **argv) { if (debug) printf ("Creating base zone DN %s\n", argzone); @@ -216,7 +208,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd } else { -@@ -306,8 +364,13 @@ main (int argc, char **argv) +@@ -330,8 +388,13 @@ main (int argc, char **argv) else sprintf (fullbasedn, "%s", ctmp); } @@ -230,7 +222,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd } } -@@ -383,14 +446,14 @@ generate_ldap (dns_name_t * dnsname, dns +@@ -409,14 +472,14 @@ generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, unsigned int ttl) isc_result_check (result, "dns_rdata_totext"); data[isc_buffer_usedlength (&buff)] = 0; @@ -248,7 +240,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd } -@@ -430,7 +493,8 @@ add_to_rr_list (char *dn, char *name, ch +@@ -456,7 +519,8 @@ add_to_rr_list (char *dn, char *name, char *type, int attrlist; char ldap_type_buffer[128]; char charttl[64]; @@ -258,8 +250,8 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd if ((tmp = locate_by_dn (dn)) == NULL) { -@@ -465,13 +529,13 @@ add_to_rr_list (char *dn, char *name, ch - } +@@ -483,13 +547,13 @@ add_to_rr_list (char *dn, char *name, char *type, + fatal("malloc"); } tmp->attrs[0]->mod_op = LDAP_MOD_ADD; - tmp->attrs[0]->mod_type = (char*)"objectClass"; @@ -275,7 +267,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd tmp->attrs[1] = NULL; tmp->attrcnt = 2; tmp->next = ldap_info_base; -@@ -480,7 +544,7 @@ add_to_rr_list (char *dn, char *name, ch +@@ -498,7 +562,7 @@ add_to_rr_list (char *dn, char *name, char *type, } tmp->attrs[1]->mod_op = LDAP_MOD_ADD; @@ -284,8 +276,8 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 2); if (tmp->attrs[1]->mod_values == (char **)NULL) -@@ -502,7 +566,7 @@ add_to_rr_list (char *dn, char *name, ch - tmp->attrs[2]->mod_values[1] = NULL; +@@ -527,7 +591,7 @@ add_to_rr_list (char *dn, char *name, char *type, + fatal("strdup"); tmp->attrs[3]->mod_op = LDAP_MOD_ADD; - tmp->attrs[3]->mod_type = (char*)"dNSTTL"; @@ -293,9 +285,9 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd tmp->attrs[3]->mod_values = (char **) calloc (sizeof (char *), 2); if (tmp->attrs[3]->mod_values == (char **)NULL) -@@ -512,10 +576,21 @@ add_to_rr_list (char *dn, char *name, ch - tmp->attrs[3]->mod_values[0] = strdup (charttl); - tmp->attrs[3]->mod_values[1] = NULL; +@@ -540,14 +604,25 @@ add_to_rr_list (char *dn, char *name, char *type, + if (tmp->attrs[3]->mod_values[0] == NULL) + fatal("strdup"); + znlen=strlen(gbl_zone); + if ( *(gbl_zone + (znlen-1)) == '.' ) @@ -312,12 +304,16 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd - tmp->attrs[4]->mod_type = (char*)"zoneName"; + tmp->attrs[4]->mod_type = zoneName; tmp->attrs[4]->mod_values = (char **)calloc(sizeof(char *), 2); + + if (tmp->attrs[4]->mod_values == (char **)NULL) + fatal("calloc"); + - tmp->attrs[4]->mod_values[0] = gbl_zone; + tmp->attrs[4]->mod_values[0] = zn; tmp->attrs[4]->mod_values[1] = NULL; tmp->attrs[5] = NULL; -@@ -526,7 +601,7 @@ add_to_rr_list (char *dn, char *name, ch +@@ -558,7 +633,7 @@ add_to_rr_list (char *dn, char *name, char *type, else { @@ -326,7 +322,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd { sprintf (ldap_type_buffer, "%sRecord", type); if (!strncmp -@@ -595,69 +670,105 @@ char ** +@@ -632,44 +707,70 @@ char ** hostname_to_dn_list (char *hostname, char *zone, unsigned int flags) { char *tmp; @@ -336,17 +332,19 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd - char *hnamebuff; - - zname = strdup (hostname); +- if (zname == NULL) +- fatal("strdup"); - - if (flags == DNS_OBJECT) - { -+ char *hname=0L, *last=0L; -+ int hlen=strlen(hostname), zlen=(strlen(zone)); - +- - if (strlen (zname) != strlen (zone)) - { - tmp = &zname[strlen (zname) - strlen (zone)]; - *--tmp = '\0'; - hnamebuff = strdup (zname); +- if (hnamebuff == NULL) +- fatal("strdup"); - zname = ++tmp; - } - else @@ -366,6 +364,9 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd - } - dn_buffer[i++] = zname; - dn_buffer[i++] = hnamebuff; ++ char *hname=0L, *last=0L; ++ int hlen=strlen(hostname), zlen=(strlen(zone)); ++ +/* printf("hostname: %s zone: %s\n",hostname, zone); */ + hname=0L; + if(flags == DNS_OBJECT) @@ -427,13 +428,9 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd + dn_buffer[i++] = hname; + dn_buffer[i++] = last; dn_buffer[i] = NULL; -- - return dn_buffer; - } -- - /* build an sdb compatible LDAP DN from a "dc_list" (char **). - * will append dNSTTL information to each RR Record, with the + return dn_buffer; +@@ -681,24 +782,32 @@ hostname_to_dn_list (char *hostname, char *zone, unsigned int flags) * exception of "@"/SOA. */ char * @@ -470,7 +467,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd else sprintf(tmp,"dc=%s,", dc_list[x]); } -@@ -683,6 +794,7 @@ void +@@ -724,6 +833,7 @@ void init_ldap_conn () { int result; @@ -478,7 +475,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd conn = ldap_open (ldapsystem, LDAP_PORT); if (conn == NULL) { -@@ -692,7 +804,7 @@ init_ldap_conn () +@@ -733,7 +843,7 @@ init_ldap_conn () } result = ldap_simple_bind_s (conn, binddn, bindpw); @@ -487,7 +484,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd } /* Like isc_result_check, only for LDAP */ -@@ -709,8 +821,6 @@ ldap_result_check (const char *msg, char +@@ -750,8 +860,6 @@ ldap_result_check (const char *msg, char *dn, int err) } } @@ -496,7 +493,7 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd /* For running the ldap_info run queue. */ void add_ldap_values (ldap_info * ldinfo) -@@ -718,14 +828,14 @@ add_ldap_values (ldap_info * ldinfo) +@@ -759,14 +867,14 @@ add_ldap_values (ldap_info * ldinfo) int result; char dnbuffer[1024]; @@ -513,12 +510,10 @@ diff -up bind-9.5.1b1/bin/sdb_tools/zone2ldap.c.fix_sdb_ldap bind-9.5.1b1/bin/sd } -@@ -736,7 +846,7 @@ void +@@ -777,5 +885,5 @@ void usage () { fprintf (stderr, -- "zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST]\n" -+ "zone2ldap -D [BIND DN] [-w BIND PASSWORD | -W:prompt] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST]\n" - "\t[-c Create LDAP Base structure][-d Debug Output (lots !)]\n " - ); - } +- "zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST] " ++ "zone2ldap -D [BIND DN] [-w BIND PASSWORD | -W:prompt] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST] " + "[-c Create LDAP Base structure][-d Debug Output (lots !)] \n ");} diff --git a/SOURCES/bind-9.3.2b2-sdbsrc.patch b/SOURCES/bind-9.3.2b2-sdbsrc.patch index bd0ed32..46e183c 100644 --- a/SOURCES/bind-9.3.2b2-sdbsrc.patch +++ b/SOURCES/bind-9.3.2b2-sdbsrc.patch @@ -1,6 +1,21 @@ ---- bind-9.3.2b2/contrib/sdb/ldap/zone2ldap.c.sdbsrc 2005-08-16 00:43:03.000000000 -0400 -+++ bind-9.3.2b2/contrib/sdb/ldap/zone2ldap.c 2005-11-15 12:57:44.000000000 -0500 -@@ -59,16 +59,16 @@ +diff --git a/contrib/sdb/bdb/bdb.c b/contrib/sdb/bdb/bdb.c +index 23594bb..b3c6619 100644 +--- a/contrib/sdb/bdb/bdb.c ++++ b/contrib/sdb/bdb/bdb.c +@@ -43,7 +43,7 @@ + #include + #include + +-#include ++#include "bdb.h" + #include + #include + +diff --git a/contrib/sdb/ldap/zone2ldap.c b/contrib/sdb/ldap/zone2ldap.c +index 07c89bc..23dd873 100644 +--- a/contrib/sdb/ldap/zone2ldap.c ++++ b/contrib/sdb/ldap/zone2ldap.c +@@ -63,16 +63,16 @@ typedef struct LDAP_INFO ldap_info; /* usage Info */ @@ -20,7 +35,7 @@ /* Put a hostname into a char ** array */ char **hostname_to_dn_list (char *hostname, char *zone, unsigned int flags); -@@ -84,7 +84,7 @@ +@@ -88,7 +88,7 @@ void add_to_rr_list (char *dn, char *name, char *type, char *data, unsigned int ttl, unsigned int flags); /* Error checking */ @@ -29,7 +44,7 @@ /* Generate LDIF Format files */ void generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, -@@ -93,11 +93,17 @@ +@@ -97,11 +97,17 @@ void generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, /* head pointer to the list */ ldap_info *ldap_info_base = NULL; @@ -50,16 +65,7 @@ LDAP *conn; unsigned int debug = 0; -@@ -106,7 +112,7 @@ - #endif - - int --main (int *argc, char **argv) -+main (int argc, char **argv) - { - isc_mem_t *mctx = NULL; - isc_entropy_t *ectx = NULL; -@@ -116,7 +122,7 @@ +@@ -128,7 +134,7 @@ main (int argc, char **argv) LDAPMod *base_attrs[2]; LDAPMod base; isc_buffer_t buff; @@ -68,7 +74,7 @@ char fullbasedn[1024]; char *ctmp; dns_fixedname_t fixedzone, fixedname; -@@ -280,9 +286,9 @@ +@@ -304,9 +310,9 @@ main (int argc, char **argv) if ((*ctmp == ',') || (ctmp == &basedn[0])) { base.mod_op = LDAP_MOD_ADD; @@ -81,7 +87,7 @@ base_attrs[1] = NULL; if (ldapbase) -@@ -337,7 +343,7 @@ +@@ -363,7 +369,7 @@ main (int argc, char **argv) * I should probably rename this function, as not to cause any * confusion with the isc* routines. Will exit on error. */ void @@ -90,17 +96,16 @@ { if (res != ISC_R_SUCCESS) { -@@ -449,7 +455,7 @@ - exit (-1); - } +@@ -470,20 +476,20 @@ add_to_rr_list (char *dn, char *name, char *type, + if (tmp->attrs == (LDAPMod **) NULL) + fatal("calloc"); - for (i = 0; i < flags; i++) + for (i = 0; i < (int)flags; i++) { tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod)); if (tmp->attrs[i] == (LDAPMod *) NULL) -@@ -459,13 +465,13 @@ - } + fatal("malloc"); } tmp->attrs[0]->mod_op = LDAP_MOD_ADD; - tmp->attrs[0]->mod_type = "objectClass"; @@ -116,7 +121,7 @@ tmp->attrs[1] = NULL; tmp->attrcnt = 2; tmp->next = ldap_info_base; -@@ -474,7 +480,7 @@ +@@ -492,7 +498,7 @@ add_to_rr_list (char *dn, char *name, char *type, } tmp->attrs[1]->mod_op = LDAP_MOD_ADD; @@ -125,8 +130,8 @@ tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 2); if (tmp->attrs[1]->mod_values == (char **)NULL) -@@ -496,7 +502,7 @@ - tmp->attrs[2]->mod_values[1] = NULL; +@@ -521,7 +527,7 @@ add_to_rr_list (char *dn, char *name, char *type, + fatal("strdup"); tmp->attrs[3]->mod_op = LDAP_MOD_ADD; - tmp->attrs[3]->mod_type = "dNSTTL"; @@ -134,16 +139,16 @@ tmp->attrs[3]->mod_values = (char **) calloc (sizeof (char *), 2); if (tmp->attrs[3]->mod_values == (char **)NULL) -@@ -507,7 +513,7 @@ - tmp->attrs[3]->mod_values[1] = NULL; +@@ -535,7 +541,7 @@ add_to_rr_list (char *dn, char *name, char *type, + fatal("strdup"); tmp->attrs[4]->mod_op = LDAP_MOD_ADD; - tmp->attrs[4]->mod_type = "zoneName"; + tmp->attrs[4]->mod_type = (char*)"zoneName"; tmp->attrs[4]->mod_values = (char **)calloc(sizeof(char *), 2); - tmp->attrs[4]->mod_values[0] = gbl_zone; - tmp->attrs[4]->mod_values[1] = NULL; -@@ -607,7 +613,7 @@ + + if (tmp->attrs[4]->mod_values == (char **)NULL) +@@ -648,7 +654,7 @@ hostname_to_dn_list (char *hostname, char *zone, unsigned int flags) zname = ++tmp; } else @@ -152,7 +157,7 @@ } else { -@@ -686,12 +692,12 @@ +@@ -727,12 +733,12 @@ init_ldap_conn () } result = ldap_simple_bind_s (conn, binddn, bindpw); @@ -167,30 +172,10 @@ { if ((err != LDAP_SUCCESS) && (err != LDAP_ALREADY_EXISTS)) { -@@ -730,5 +736,8 @@ - usage () - { - fprintf (stderr, -- "zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST] -- [-c Create LDAP Base structure][-d Debug Output (lots !)] \n ");} -+ "zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST]\n" -+ "\t[-c Create LDAP Base structure][-d Debug Output (lots !)]\n " -+ ); -+} -+ ---- bind-9.3.2b2/contrib/sdb/bdb/bdb.c.sdbsrc 2002-07-02 00:45:34.000000000 -0400 -+++ bind-9.3.2b2/contrib/sdb/bdb/bdb.c 2005-11-15 12:57:44.000000000 -0500 -@@ -43,7 +43,7 @@ - #include - #include - --#include -+#include "bdb.h" - #include - #include - ---- bind-9.3.2b2/contrib/sdb/pgsql/pgsqldb.c.sdbsrc 2004-03-08 04:04:22.000000000 -0500 -+++ bind-9.3.2b2/contrib/sdb/pgsql/pgsqldb.c 2005-11-15 12:57:44.000000000 -0500 +diff --git a/contrib/sdb/pgsql/pgsqldb.c b/contrib/sdb/pgsql/pgsqldb.c +index 50d3cba..516eb9f 100644 +--- a/contrib/sdb/pgsql/pgsqldb.c ++++ b/contrib/sdb/pgsql/pgsqldb.c @@ -23,7 +23,7 @@ #include #include @@ -200,8 +185,10 @@ #include #include ---- bind-9.3.2b2/contrib/sdb/pgsql/zonetodb.c.sdbsrc 2005-09-05 22:12:40.000000000 -0400 -+++ bind-9.3.2b2/contrib/sdb/pgsql/zonetodb.c 2005-11-15 12:58:12.000000000 -0500 +diff --git a/contrib/sdb/pgsql/zonetodb.c b/contrib/sdb/pgsql/zonetodb.c +index b8f5912..ff2d135 100644 +--- a/contrib/sdb/pgsql/zonetodb.c ++++ b/contrib/sdb/pgsql/zonetodb.c @@ -37,7 +37,7 @@ #include #include @@ -211,7 +198,7 @@ /* * Generate a PostgreSQL table from a zone. -@@ -54,6 +54,9 @@ +@@ -54,6 +54,9 @@ char *dbname, *dbtable; char str[10240]; void @@ -221,7 +208,7 @@ closeandexit(int status) { if (conn != NULL) PQfinish(conn); -@@ -61,6 +64,9 @@ +@@ -61,6 +64,9 @@ closeandexit(int status) { } void @@ -231,7 +218,7 @@ check_result(isc_result_t result, const char *message) { if (result != ISC_R_SUCCESS) { fprintf(stderr, "%s: %s\n", message, -@@ -84,7 +90,8 @@ +@@ -84,7 +90,8 @@ quotestring(const unsigned char *source, unsigned char *dest) { } *dest++ = 0; } diff --git a/SOURCES/bind-9.5-dlz-64bit.patch b/SOURCES/bind-9.5-dlz-64bit.patch index 0e726d8..ec064c6 100644 --- a/SOURCES/bind-9.5-dlz-64bit.patch +++ b/SOURCES/bind-9.5-dlz-64bit.patch @@ -1,6 +1,7 @@ -diff -up bind-9.9.0/contrib/dlz/config.dlz.in.64bit bind-9.9.0/contrib/dlz/config.dlz.in ---- bind-9.9.0/contrib/dlz/config.dlz.in.64bit 2011-11-05 06:14:28.000000000 +0100 -+++ bind-9.9.0/contrib/dlz/config.dlz.in 2012-04-24 14:52:08.398511143 +0200 +diff --git a/contrib/dlz/config.dlz.in b/contrib/dlz/config.dlz.in +index 47525af..eefe3c3 100644 +--- a/contrib/dlz/config.dlz.in ++++ b/contrib/dlz/config.dlz.in @@ -17,6 +17,13 @@ # dlzdir='${DLZ_DRIVER_DIR}' @@ -15,33 +16,19 @@ diff -up bind-9.9.0/contrib/dlz/config.dlz.in.64bit bind-9.9.0/contrib/dlz/confi # # Private autoconf macro to simplify configuring drivers: # -@@ -135,9 +142,9 @@ then - then - use_dlz_mysql=$d - mysql_include=$d/include/mysql -- if test -d $d/lib/mysql -+ if test -d $d/${target_lib}/mysql - then -- mysql_lib=$d/lib/mysql -+ mysql_lib=$d/${target_lib}/mysql - else - mysql_lib=$d/lib - fi -@@ -274,11 +281,11 @@ case "$use_dlz_bdb" in - bdb_libnames="db48 db-4.8 db47 db-4.7 db46 db-4.6 db45 db-4.5 db44 db-4.4 db43 db-4.3 db42 db-4.2 db41 db-4.1 db" - for d in $bdb_libnames - do -- if test -f "$dd/lib/lib${d}.so" -+ if test -f "$dd/${target_lib}/lib${d}.so" - then - if test "$dd" != "/usr" +@@ -292,9 +299,9 @@ case "$use_dlz_bdb" in then -- dlz_bdb_libs="-L${dd}/lib " -+ dlz_bdb_libs="-L${dd}/${target_lib} " - else - dlz_bdb_libs="" + break fi -@@ -383,7 +390,7 @@ case "$use_dlz_ldap" in +- elif test -f "$dd/lib/lib${d}.so" ++ elif test -f "$dd/${target_lib}/lib${d}.so" + then +- dlz_bdb_libs="-L${dd}/lib -l${d}" ++ dlz_bdb_libs="-L${dd}/${target_lib} -l${d}" + break + fi + done +@@ -396,7 +403,7 @@ case "$use_dlz_ldap" in *) DLZ_ADD_DRIVER(LDAP, dlz_ldap_driver, [-I$use_dlz_ldap/include], @@ -50,21 +37,17 @@ diff -up bind-9.9.0/contrib/dlz/config.dlz.in.64bit bind-9.9.0/contrib/dlz/confi AC_MSG_RESULT( [using LDAP from $use_dlz_ldap/lib and $use_dlz_ldap/include]) -@@ -407,7 +414,7 @@ then - odbcdirs="/usr /usr/local /usr/pkg" - for d in $odbcdirs - do -- if test -f $d/include/sql.h -a -f $d/lib/libodbc.a -+ if test -f $d/include/sql.h -a -f $d/${target_lib}/libodbc.a - then - use_dlz_odbc=$d - break -@@ -427,7 +434,7 @@ case "$use_dlz_odbc" in - *) - DLZ_ADD_DRIVER(ODBC, dlz_odbc_driver, - [-I$use_dlz_odbc/include], -- [-L$use_dlz_odbc/lib -lodbc]) -+ [-L$use_dlz_odbc/${target_lib} -lodbc]) - - AC_MSG_RESULT([using ODBC from $use_dlz_odbc]) - ;; +@@ -432,11 +439,11 @@ then + odbcdirs="/usr /usr/local /usr/pkg" + for d in $odbcdirs + do +- if test -f $d/include/sql.h -a -f $d/lib/libodbc.a ++ if test -f $d/include/sql.h -a -f $d/${target_lib}/libodbc.a + then + use_dlz_odbc=$d + dlz_odbc_include="-I$use_dlz_odbc/include" +- dlz_odbc_libs="-L$use_dlz_odbc/lib -lodbc" ++ dlz_odbc_libs="-L$use_dlz_odbc/${target_lib} -lodbc" + break + fi + done diff --git a/SOURCES/bind-9.5-libidn.patch b/SOURCES/bind-9.5-libidn.patch deleted file mode 100644 index e0831e4..0000000 --- a/SOURCES/bind-9.5-libidn.patch +++ /dev/null @@ -1,270 +0,0 @@ -diff -up bind-9.7.0b1/bin/dig/dighost.c.libidn bind-9.7.0b1/bin/dig/dighost.c ---- bind-9.7.0b1/bin/dig/dighost.c.libidn 2009-09-16 01:48:09.000000000 +0200 -+++ bind-9.7.0b1/bin/dig/dighost.c 2009-10-20 10:49:26.719056220 +0200 -@@ -44,6 +44,11 @@ - #include - #endif - -+#ifdef WITH_LIBIDN -+#include -+#include -+#endif -+ - #include - #ifdef DIG_SIGCHASE - #include -@@ -153,6 +158,14 @@ static void idn_check_result(idn_result - int idnoptions = 0; - #endif - -+#ifdef WITH_LIBIDN -+static isc_result_t libidn_locale_to_utf8 (const char* from, char **to); -+static isc_result_t libidn_utf8_to_ascii (const char* from, char *to); -+static isc_result_t output_filter (isc_buffer_t *buffer, -+ unsigned int used_org, -+ isc_boolean_t absolute); -+#endif -+ - /*% - * Exit Codes: - * -@@ -1184,6 +1197,9 @@ setup_system(void) { - dig_searchlist_t *domain = NULL; - lwres_result_t lwresult; - unsigned int lwresflags; -+#ifdef WITH_LIBIDN -+ isc_result_t result; -+#endif - - debug("setup_system()"); - -@@ -1242,8 +1258,15 @@ setup_system(void) { - - #ifdef WITH_IDN - initialize_idn(); -+ -+#endif -+#ifdef WITH_LIBIDN -+ result = dns_name_settotextfilter(output_filter); -+ check_result(result, "dns_name_settotextfilter"); -+#ifdef HAVE_SETLOCALE -+ setlocale (LC_ALL, ""); -+#endif - #endif -- - if (keyfile[0] != 0) - setup_file_key(); - else if (keysecret[0] != 0) -@@ -1957,12 +1980,18 @@ setup_lookup(dig_lookup_t *lookup) { - idn_result_t mr; - char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME]; - #endif -+#ifdef WITH_LIBIDN -+ char *utf8_str = NULL, utf8_name[MXNAME], ascii_name[MXNAME]; -+#endif - - #ifdef WITH_IDN - result = dns_name_settotextfilter(output_filter); - check_result(result, "dns_name_settotextfilter"); - #endif -- -+#ifdef WITH_LIBIDN -+ result = dns_name_settotextfilter (output_filter); -+ check_result(result, "dns_name_settotextfilter"); -+#endif - REQUIRE(lookup != NULL); - INSIST(!free_now); - -@@ -1999,6 +2028,16 @@ setup_lookup(dig_lookup_t *lookup) { - mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname, - utf8_textname, sizeof(utf8_textname)); - idn_check_result(mr, "convert textname to UTF-8"); -+#elif defined (WITH_LIBIDN) -+ result = libidn_locale_to_utf8 (lookup->textname, &utf8_str); -+ check_result (result, "converting textname to UTF-8"); -+ len = strlen (utf8_str); -+ if (len < MXNAME) { -+ (void) strcpy (utf8_name, utf8_str); -+ } else { -+ fatal ("Too long name"); -+ } -+ isc_mem_free (mctx, utf8_str); - #endif - - /* -@@ -2018,6 +2057,15 @@ setup_lookup(dig_lookup_t *lookup) { - lookup->origin = ISC_LIST_HEAD(search_list); - lookup->need_search = ISC_FALSE; - } -+#elif defined (WITH_LIBIDN) -+ if ((count_dots(utf8_name) >= ndots) || !usesearch) { -+ lookup->origin = NULL; /* Force abs lookup */ -+ lookup->done_as_is = ISC_TRUE; -+ lookup->need_search = usesearch; -+ } else if (lookup->origin == NULL && usesearch) { -+ lookup->origin = ISC_LIST_HEAD(search_list); -+ lookup->need_search = ISC_FALSE; -+ } - #else - if ((count_dots(lookup->textname) >= ndots) || !usesearch) { - lookup->origin = NULL; /* Force abs lookup */ -@@ -2044,6 +2092,20 @@ setup_lookup(dig_lookup_t *lookup) { - IDN_IDNCONV | IDN_LENCHECK, utf8_textname, - idn_textname, sizeof(idn_textname)); - idn_check_result(mr, "convert UTF-8 textname to IDN encoding"); -+#elif defined (WITH_LIBIDN) -+ if (lookup->origin != NULL) { -+ result = libidn_locale_to_utf8 (lookup->origin->origin, &utf8_str); -+ check_result (result, "convert origin to UTF-8"); -+ if (len + strlen (utf8_str) + 1 < MXNAME) { -+ utf8_name[len++] = '.'; -+ (void) strcpy (utf8_name + len, utf8_str); -+ } else { -+ fatal ("Too long name + origin"); -+ } -+ isc_mem_free (mctx, utf8_str); -+ } -+ -+ result = libidn_utf8_to_ascii (utf8_name, ascii_name); - #else - if (lookup->origin != NULL) { - debug("trying origin %s", lookup->origin->origin); -@@ -2099,6 +2161,13 @@ setup_lookup(dig_lookup_t *lookup) { - result = dns_name_fromtext(lookup->name, &b, - dns_rootname, 0, - &lookup->namebuf); -+#elif defined (WITH_LIBIDN) -+ len = strlen (ascii_name); -+ isc_buffer_init(&b, ascii_name, len); -+ isc_buffer_add(&b, len); -+ result = dns_name_fromtext(lookup->name, &b, -+ dns_rootname, 0, -+ &lookup->namebuf); - #else - len = strlen(lookup->textname); - isc_buffer_init(&b, lookup->textname, len); -@@ -3617,7 +3686,7 @@ destroy_libs(void) { - void * ptr; - dig_message_t *chase_msg; - #endif --#ifdef WITH_IDN -+#if defined (WITH_IDN) || defined (WITH_LIBIDN) - isc_result_t result; - #endif - -@@ -3656,6 +3725,10 @@ destroy_libs(void) { - result = dns_name_settotextfilter(NULL); - check_result(result, "dns_name_settotextfilter"); - #endif -+#ifdef WITH_LIBIDN -+ result = dns_name_settotextfilter (NULL); -+ check_result(result, "clearing dns_name_settotextfilter"); -+#endif - dns_name_destroy(); - - if (commctx != NULL) { -@@ -3834,6 +3907,79 @@ idn_check_result(idn_result_t r, const c - } - } - #endif /* WITH_IDN */ -+#ifdef WITH_LIBIDN -+/* If stringprep_locale_to_utf8 fails simple copy string */ -+static isc_result_t -+libidn_locale_to_utf8 (const char *from, char **to) { -+ char *utf8_str; -+ -+ utf8_str = stringprep_locale_to_utf8 (from); -+ if (utf8_str == NULL) { -+ *to = isc_mem_allocate (mctx, strlen (from) + 1); -+ if (*to == NULL) -+ return (ISC_R_NOMEMORY); -+ (void) strcpy (*to, from); -+ } else { -+ *to = isc_mem_allocate (mctx, strlen (utf8_str) + 1); -+ if (*to == NULL) -+ return (ISC_R_NOMEMORY); -+ (void) strcpy (*to, utf8_str); -+ free (utf8_str); -+ } -+ return (ISC_R_SUCCESS); -+} -+static isc_result_t -+libidn_utf8_to_ascii (const char *from, char *to) { -+ char *ascii; -+ -+ if (idna_to_ascii_8z (from, &ascii, 0) != IDNA_SUCCESS) -+ return (ISC_R_FAILURE); -+ -+ (void) strcpy (to, ascii); -+ free (ascii); -+ return (ISC_R_SUCCESS); -+} -+/* based on idnkit's code*/ -+static isc_result_t -+output_filter (isc_buffer_t *buffer, unsigned int used_org, -+ isc_boolean_t absolute) { -+ char tmp1[MXNAME], *tmp2; -+ size_t fromlen, tolen; -+ isc_boolean_t end_with_dot; -+ -+ fromlen = isc_buffer_usedlength(buffer) - used_org; -+ if (fromlen >= MXNAME) -+ return (ISC_R_SUCCESS); -+ memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen); -+ end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE; -+ if (absolute && !end_with_dot) { -+ fromlen++; -+ if (fromlen >= MXNAME) -+ return (ISC_R_SUCCESS); -+ tmp1[fromlen - 1] = '.'; -+ } -+ tmp1[fromlen] = '\0'; -+ -+ if (idna_to_unicode_lzlz (tmp1, &tmp2, 0) != IDNA_SUCCESS) -+ return (ISC_R_SUCCESS); -+ -+ (void) strcpy (tmp1, tmp2); -+ free (tmp2); -+ -+ tolen = strlen(tmp1); -+ if (absolute && !end_with_dot && tmp1[tolen - 1] == '.') -+ tolen--; -+ -+ if (isc_buffer_length(buffer) < used_org + tolen) -+ return (ISC_R_NOSPACE); -+ -+ isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org); -+ memcpy(isc_buffer_used(buffer), tmp1, tolen); -+ isc_buffer_add(buffer, tolen); -+ -+ return (ISC_R_SUCCESS); -+} -+#endif /* WITH_LIBIDN*/ - - #ifdef DIG_SIGCHASE - void -diff -up bind-9.7.0b1/bin/dig/Makefile.in.libidn bind-9.7.0b1/bin/dig/Makefile.in ---- bind-9.7.0b1/bin/dig/Makefile.in.libidn 2009-09-22 10:47:55.000000000 +0200 -+++ bind-9.7.0b1/bin/dig/Makefile.in 2009-10-20 10:50:06.201543709 +0200 -@@ -46,10 +46,10 @@ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} - ${LWRESDEPLIBS} - - LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ -- ${ISCLIBS} @IDNLIBS@ @LIBS@ -+ ${ISCLIBS} @IDNLIBS@ @LIBS@ -lidn - - NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ -- ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ -+ ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ -lidn - - SUBDIRS = - -@@ -67,6 +67,8 @@ HTMLPAGES = dig.html host.html nslookup. - - MANOBJS = ${MANPAGES} ${HTMLPAGES} - -+EXT_CFLAGS = -DWITH_LIBIDN -+ - @BIND9_MAKE_RULES@ - - dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} diff --git a/SOURCES/bind-9.5-libidn2.patch b/SOURCES/bind-9.5-libidn2.patch deleted file mode 100644 index 785b6eb..0000000 --- a/SOURCES/bind-9.5-libidn2.patch +++ /dev/null @@ -1,221 +0,0 @@ -diff -up bind-9.5.0b1/bin/dig/dighost.c.libidn2 bind-9.5.0b1/bin/dig/dighost.c ---- bind-9.5.0b1/bin/dig/dighost.c.libidn2 2007-12-10 13:12:26.000000000 +0100 -+++ bind-9.5.0b1/bin/dig/dighost.c 2007-12-10 14:21:09.000000000 +0100 -@@ -153,7 +153,7 @@ int idnoptions = 0; - #endif - - #ifdef WITH_LIBIDN --static isc_result_t libidn_locale_to_utf8 (const char* from, char **to); -+static isc_result_t libidn_locale_to_utf8 (const char* from, char *to); - static isc_result_t libidn_utf8_to_ascii (const char* from, char *to); - static isc_result_t output_filter (isc_buffer_t *buffer, - unsigned int used_org, -@@ -1764,17 +1764,13 @@ setup_lookup(dig_lookup_t *lookup) { - char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME]; - #endif - #ifdef WITH_LIBIDN -- char *utf8_str = NULL, utf8_name[MXNAME], ascii_name[MXNAME]; -+ char utf8_str[MXNAME], utf8_name[MXNAME], ascii_name[MXNAME]; - #endif - --#ifdef WITH_IDN -+#if defined (WITH_IDN) || defined (WITH_LIBIDN) - result = dns_name_settotextfilter(output_filter); - check_result(result, "dns_name_settotextfilter"); - #endif --#ifdef WITH_LIBIDN -- result = dns_name_settotextfilter (output_filter); -- check_result(result, "dns_name_settotextfilter"); --#endif - REQUIRE(lookup != NULL); - INSIST(!free_now); - -@@ -1812,15 +1808,13 @@ setup_lookup(dig_lookup_t *lookup) { - utf8_textname, sizeof(utf8_textname)); - idn_check_result(mr, "convert textname to UTF-8"); - #elif defined (WITH_LIBIDN) -- result = libidn_locale_to_utf8 (lookup->textname, &utf8_str); -- check_result (result, "converting textname to UTF-8"); -+ result = libidn_locale_to_utf8 (lookup->textname, utf8_str); -+ check_result (result, "convert textname to UTF-8"); - len = strlen (utf8_str); -- if (len < MXNAME) { -+ if (len < MXNAME) - (void) strcpy (utf8_name, utf8_str); -- } else { -+ else - fatal ("Too long name"); -- } -- isc_mem_free (mctx, utf8_str); - #endif - - /* -@@ -1833,24 +1827,11 @@ setup_lookup(dig_lookup_t *lookup) { - if (lookup->new_search) { - #ifdef WITH_IDN - if ((count_dots(utf8_textname) >= ndots) || !usesearch) { -- lookup->origin = NULL; /* Force abs lookup */ -- lookup->done_as_is = ISC_TRUE; -- lookup->need_search = usesearch; -- } else if (lookup->origin == NULL && usesearch) { -- lookup->origin = ISC_LIST_HEAD(search_list); -- lookup->need_search = ISC_FALSE; -- } - #elif defined (WITH_LIBIDN) - if ((count_dots(utf8_name) >= ndots) || !usesearch) { -- lookup->origin = NULL; /* Force abs lookup */ -- lookup->done_as_is = ISC_TRUE; -- lookup->need_search = usesearch; -- } else if (lookup->origin == NULL && usesearch) { -- lookup->origin = ISC_LIST_HEAD(search_list); -- lookup->need_search = ISC_FALSE; -- } - #else - if ((count_dots(lookup->textname) >= ndots) || !usesearch) { -+#endif - lookup->origin = NULL; /* Force abs lookup */ - lookup->done_as_is = ISC_TRUE; - lookup->need_search = usesearch; -@@ -1858,7 +1839,6 @@ setup_lookup(dig_lookup_t *lookup) { - lookup->origin = ISC_LIST_HEAD(search_list); - lookup->need_search = ISC_FALSE; - } --#endif - } - - #ifdef WITH_IDN -@@ -1877,15 +1857,12 @@ setup_lookup(dig_lookup_t *lookup) { - idn_check_result(mr, "convert UTF-8 textname to IDN encoding"); - #elif defined (WITH_LIBIDN) - if (lookup->origin != NULL) { -- result = libidn_locale_to_utf8 (lookup->origin->origin, &utf8_str); -+ result = libidn_locale_to_utf8 (lookup->origin->origin, utf8_str); - check_result (result, "convert origin to UTF-8"); -- if (len + strlen (utf8_str) + 1 < MXNAME) { -- utf8_name[len++] = '.'; -+ if (len + strlen (utf8_str) < MXNAME) - (void) strcpy (utf8_name + len, utf8_str); -- } else { -+ else - fatal ("Too long name + origin"); -- } -- isc_mem_free (mctx, utf8_str); - } - - result = libidn_utf8_to_ascii (utf8_name, ascii_name); -@@ -3600,76 +3577,85 @@ idn_check_result(idn_result_t r, const c - } - #endif /* WITH_IDN */ - #ifdef WITH_LIBIDN --/* If stringprep_locale_to_utf8 fails simple copy string */ - static isc_result_t --libidn_locale_to_utf8 (const char *from, char **to) { -+libidn_locale_to_utf8 (const char *from, char *to) { - char *utf8_str; - -+ debug ("libidn_locale_to_utf8"); - utf8_str = stringprep_locale_to_utf8 (from); -- if (utf8_str == NULL) { -- *to = isc_mem_allocate (mctx, strlen (from) + 1); -- if (*to == NULL) -- return (ISC_R_NOMEMORY); -- (void) strcpy (*to, from); -- } else { -- *to = isc_mem_allocate (mctx, strlen (utf8_str) + 1); -- if (*to == NULL) -- return (ISC_R_NOMEMORY); -- (void) strcpy (*to, utf8_str); -+ if (utf8_str != NULL) { -+ (void) strcpy (to, utf8_str); - free (utf8_str); -+ return ISC_R_SUCCESS; - } -- return (ISC_R_SUCCESS); -+ -+ debug ("libidn_locale_to_utf8: failure"); -+ return ISC_R_FAILURE; - } - static isc_result_t - libidn_utf8_to_ascii (const char *from, char *to) { - char *ascii; -+ int iresult; - -- if (idna_to_ascii_8z (from, &ascii, 0) != IDNA_SUCCESS) -- return (ISC_R_FAILURE); -+ debug ("libidn_utf8_to_ascii"); -+ iresult = idna_to_ascii_8z (from, &ascii, 0); -+ if (iresult != IDNA_SUCCESS) { -+ debug ("idna_to_ascii_8z: %s", idna_strerror (iresult)); -+ return ISC_R_FAILURE; -+ } - - (void) strcpy (to, ascii); - free (ascii); -- return (ISC_R_SUCCESS); -+ return ISC_R_SUCCESS; - } --/* based on idnkit's code*/ -+ - static isc_result_t - output_filter (isc_buffer_t *buffer, unsigned int used_org, - isc_boolean_t absolute) { -+ - char tmp1[MXNAME], *tmp2; - size_t fromlen, tolen; - isc_boolean_t end_with_dot; -+ int iresult; -+ -+ debug ("output_filter"); - -- fromlen = isc_buffer_usedlength(buffer) - used_org; -+ fromlen = isc_buffer_usedlength (buffer) - used_org; - if (fromlen >= MXNAME) -- return (ISC_R_SUCCESS); -- memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen); -+ return ISC_R_SUCCESS; -+ memcpy (tmp1, (char *) isc_buffer_base (buffer) + used_org, fromlen); - end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE; - if (absolute && !end_with_dot) { - fromlen++; - if (fromlen >= MXNAME) -- return (ISC_R_SUCCESS); -+ return ISC_R_SUCCESS; - tmp1[fromlen - 1] = '.'; - } - tmp1[fromlen] = '\0'; - -- if (idna_to_unicode_lzlz (tmp1, &tmp2, 0) != IDNA_SUCCESS) -- return (ISC_R_SUCCESS); -+ iresult = idna_to_unicode_8z8z (tmp1, &tmp2, 0); -+ if (iresult != IDNA_SUCCESS) { -+ debug ("output_filter: %s", idna_strerror (iresult)); -+ return ISC_R_SUCCESS; -+ } - - (void) strcpy (tmp1, tmp2); - free (tmp2); - -- tolen = strlen(tmp1); -+ tolen = strlen (tmp1); - if (absolute && !end_with_dot && tmp1[tolen - 1] == '.') - tolen--; - -- if (isc_buffer_length(buffer) < used_org + tolen) -- return (ISC_R_NOSPACE); -+ if (isc_buffer_length (buffer) < used_org + tolen) -+ return ISC_R_NOSPACE; -+ -+ debug ("%s", tmp1); - -- isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org); -- memcpy(isc_buffer_used(buffer), tmp1, tolen); -- isc_buffer_add(buffer, tolen); -+ isc_buffer_subtract (buffer, isc_buffer_usedlength (buffer) - used_org); -+ memcpy (isc_buffer_used (buffer), tmp1, tolen); -+ isc_buffer_add (buffer, tolen); - -- return (ISC_R_SUCCESS); -+ return ISC_R_SUCCESS; - } - #endif /* WITH_LIBIDN*/ - diff --git a/SOURCES/bind-9.5-libidn3.patch b/SOURCES/bind-9.5-libidn3.patch deleted file mode 100644 index 3fd5573..0000000 --- a/SOURCES/bind-9.5-libidn3.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up bind-9.5.0b1/bin/dig/dighost.c.libidn3 bind-9.5.0b1/bin/dig/dighost.c ---- bind-9.5.0b1/bin/dig/dighost.c.libidn3 2007-12-20 13:24:27.000000000 +0100 -+++ bind-9.5.0b1/bin/dig/dighost.c 2007-12-20 13:27:10.000000000 +0100 -@@ -1859,10 +1859,13 @@ setup_lookup(dig_lookup_t *lookup) { - if (lookup->origin != NULL) { - result = libidn_locale_to_utf8 (lookup->origin->origin, utf8_str); - check_result (result, "convert origin to UTF-8"); -- if (len + strlen (utf8_str) < MXNAME) -- (void) strcpy (utf8_name + len, utf8_str); -- else -- fatal ("Too long name + origin"); -+ if (len > 0 && utf8_name[len - 1] != '.') { -+ utf8_name[len++] = '.'; -+ if (len + strlen (utf8_str) < MXNAME) -+ (void) strcpy (utf8_name + len, utf8_str); -+ else -+ fatal ("Too long name + origin"); -+ } - } - - result = libidn_utf8_to_ascii (utf8_name, ascii_name); diff --git a/SOURCES/bind-9.5-parallel-build.patch b/SOURCES/bind-9.5-parallel-build.patch deleted file mode 100644 index 53e34ca..0000000 --- a/SOURCES/bind-9.5-parallel-build.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff -up bind-9.5.0b1/lib/dns/Makefile.in.parallel bind-9.5.0b1/lib/dns/Makefile.in ---- bind-9.5.0b1/lib/dns/Makefile.in.parallel 2008-01-17 18:27:38.000000000 +0100 -+++ bind-9.5.0b1/lib/dns/Makefile.in 2008-01-17 18:27:45.000000000 +0100 -@@ -19,10 +19,6 @@ srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ - --# Attempt to disable parallel processing. --.NOTPARALLEL: --.NO_PARALLEL: -- - @BIND9_VERSION@ - - @LIBDNS_API@ diff --git a/SOURCES/bind-9.5-sdb-sqlite-bld.patch b/SOURCES/bind-9.5-sdb-sqlite-bld.patch deleted file mode 100644 index 768af1c..0000000 --- a/SOURCES/bind-9.5-sdb-sqlite-bld.patch +++ /dev/null @@ -1,102 +0,0 @@ -diff -up bind-9.8.1rc1/bin/named-sdb/main.c.sdb-sqlite-bld bind-9.8.1rc1/bin/named-sdb/main.c ---- bind-9.8.1rc1/bin/named-sdb/main.c.sdb-sqlite-bld 2011-08-31 14:41:15.646020840 +0200 -+++ bind-9.8.1rc1/bin/named-sdb/main.c 2011-08-31 14:41:35.132019452 +0200 -@@ -85,6 +85,7 @@ - /* #include "xxdb.h" */ - #include "ldapdb.h" - #include "pgsqldb.h" -+#include "sqlitedb.h" - #include "dirdb.h" - - #ifdef CONTRIB_DLZ -@@ -792,6 +793,7 @@ setup(void) { - - ldapdb_clear(); - pgsqldb_clear(); -+ sqlitedb_clear(); - dirdb_clear(); - - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -@@ -921,6 +923,23 @@ setup(void) { - ISC_LOG_NOTICE, "SDB postgreSQL DB zone database module loaded." - ); - -+ result = sqlitedb_init(); -+ if (result != ISC_R_SUCCESS) -+ { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_ERROR, -+ "SDB sqlite3 module initialisation failed: %s.", -+ isc_result_totext(result) -+ ); -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_ERROR, -+ "SDB sqlite3 zone database will be unavailable." -+ ); -+ }else -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_NOTICE, "SDB sqlite3 DB zone database module loaded." -+ ); -+ - result = dirdb_init(); - if (result != ISC_R_SUCCESS) - { -@@ -971,6 +990,7 @@ cleanup(void) { - - ldapdb_clear(); - pgsqldb_clear(); -+ sqlitedb_clear(); - dirdb_clear(); - - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -diff -up bind-9.8.1rc1/bin/named-sdb/Makefile.in.sdb-sqlite-bld bind-9.8.1rc1/bin/named-sdb/Makefile.in ---- bind-9.8.1rc1/bin/named-sdb/Makefile.in.sdb-sqlite-bld 2011-08-31 14:41:15.646020840 +0200 -+++ bind-9.8.1rc1/bin/named-sdb/Makefile.in 2011-08-31 14:41:15.658020839 +0200 -@@ -28,10 +28,10 @@ top_srcdir = @top_srcdir@ - # - # Add database drivers here. - # --DBDRIVER_OBJS = ldapdb.@O@ pgsqldb.@O@ dirdb.@O@ --DBDRIVER_SRCS = ldapdb.c pgsqldb.c dirdb.c -+DBDRIVER_OBJS = ldapdb.@O@ pgsqldb.@O@ sqlitedb.@O@ dirdb.@O@ -+DBDRIVER_SRCS = ldapdb.c pgsqldb.c sqlitedb.c dirdb.c - DBDRIVER_INCLUDES = --DBDRIVER_LIBS = -lldap -llber -lpq -+DBDRIVER_LIBS = -lldap -llber -lpq -lsqlite3 - - DLZ_DRIVER_DIR = ${top_srcdir}/contrib/dlz/drivers - -diff -up bind-9.8.1rc1/bin/sdb_tools/Makefile.in.sdb-sqlite-bld bind-9.8.1rc1/bin/sdb_tools/Makefile.in ---- bind-9.8.1rc1/bin/sdb_tools/Makefile.in.sdb-sqlite-bld 2011-08-31 14:41:15.651020840 +0200 -+++ bind-9.8.1rc1/bin/sdb_tools/Makefile.in 2011-08-31 14:41:15.658020839 +0200 -@@ -32,11 +32,11 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} - LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ - ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} ${DBDRIVER_LIBS} @LIBS@ - --TARGETS = zone2ldap@EXEEXT@ ldap2zone@EXEEXT@ zonetodb@EXEEXT@ -+TARGETS = zone2ldap@EXEEXT@ ldap2zone@EXEEXT@ zonetodb@EXEEXT@ zone2sqlite@EXEEXT@ - --OBJS = zone2ldap.@O@ ldap2zone.@O@ zonetodb.@O@ -+OBJS = zone2ldap.@O@ ldap2zone.@O@ zonetodb.@O@ zone2sqlite.@O@ - --SRCS = zone2ldap.c ldap2zone.c zonetodb.c -+SRCS = zone2ldap.c ldap2zone.c zonetodb.c zone2sqlite.c - - MANPAGES = zone2ldap.1 - -@@ -50,6 +50,9 @@ zone2ldap@EXEEXT@: zone2ldap.@O@ ${DEPLI - zonetodb@EXEEXT@: zonetodb.@O@ ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ zonetodb.@O@ -lpq ${LIBS} - -+zone2sqlite@EXEEXT@: zone2sqlite.@O@ ${DEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ zone2sqlite.@O@ -lsqlite3 -lssl ${LIBS} -+ - ldap2zone@EXEEXT@: ldap2zone.@O@ ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ ldap2zone.@O@ -lldap -llber ${LIBS} - -@@ -64,4 +67,5 @@ install:: ${TARGETS} installdirs - ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} zone2ldap@EXEEXT@ ${DESTDIR}${sbindir} - ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} ldap2zone@EXEEXT@ ${DESTDIR}${sbindir} - ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} zonetodb@EXEEXT@ ${DESTDIR}${sbindir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} zone2sqlite@EXEEXT@ ${DESTDIR}${sbindir} - ${INSTALL_DATA} ${srcdir}/zone2ldap.1 ${DESTDIR}${mandir}/man1/zone2ldap.1 diff --git a/SOURCES/bind-9.5-sdb.patch b/SOURCES/bind-9.5-sdb.patch deleted file mode 100644 index 3abf457..0000000 --- a/SOURCES/bind-9.5-sdb.patch +++ /dev/null @@ -1,240 +0,0 @@ -diff --git a/bin/Makefile.in b/bin/Makefile.in -index 187ec23..e6179e7 100644 ---- a/bin/Makefile.in -+++ b/bin/Makefile.in -@@ -19,8 +19,8 @@ srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ - --SUBDIRS = named named-pkcs11 rndc dig dnssec dnssec-pkcs11 tools tests nsupdate \ -- check confgen @PYTHON_TOOLS@ @PKCS11_TOOLS@ -+SUBDIRS = named named-pkcs11 named-sdb rndc dig dnssec dnssec-pkcs11 tools tests nsupdate \ -+ check confgen @PYTHON_TOOLS@ @PKCS11_TOOLS@ sdb_tools - TARGETS = - - @BIND9_MAKE_RULES@ -diff --git a/bin/named-sdb/Makefile.in b/bin/named-sdb/Makefile.in -index 5ba3f56..1868418 100644 ---- a/bin/named-sdb/Makefile.in -+++ b/bin/named-sdb/Makefile.in -@@ -32,10 +32,10 @@ top_srcdir = @top_srcdir@ - # - # Add database drivers here. - # --DBDRIVER_OBJS = --DBDRIVER_SRCS = -+DBDRIVER_OBJS = ldapdb.@O@ pgsqldb.@O@ dirdb.@O@ -+DBDRIVER_SRCS = ldapdb.c pgsqldb.c dirdb.c - DBDRIVER_INCLUDES = --DBDRIVER_LIBS = -+DBDRIVER_LIBS = -lldap -llber -lpq - - DLZ_DRIVER_DIR = ${top_srcdir}/contrib/dlz/drivers - -@@ -81,7 +81,7 @@ NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ - - SUBDIRS = unix - --TARGETS = named@EXEEXT@ lwresd@EXEEXT@ -+TARGETS = named-sdb@EXEEXT@ - - GEOIPLINKOBJS = geoip.@O@ - -@@ -145,7 +145,7 @@ config.@O@: config.c bind.keys.h - -DNS_SYSCONFDIR=\"${sysconfdir}\" \ - -c ${srcdir}/config.c - --named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS} -+named-sdb@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS} - export MAKE_SYMTABLE="yes"; \ - export BASEOBJS="${OBJS} ${UOBJS}"; \ - ${FINALBUILDCMD} -@@ -176,15 +176,9 @@ statschannel.@O@: bind9.xsl.h bind9.ver3.xsl.h - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} -- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5 -- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 -- --install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir} -- (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@) -- ${INSTALL_DATA} ${srcdir}/named.8 ${DESTDIR}${mandir}/man8 -- ${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8 -- ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5 -+ -+install:: named-sdb@EXEEXT@ installdirs -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-sdb@EXEEXT@ ${DESTDIR}${sbindir} - - @DLZ_DRIVER_RULES@ - -diff --git a/bin/named-sdb/main.c b/bin/named-sdb/main.c -index d26783f..75691ed 100644 ---- a/bin/named-sdb/main.c -+++ b/bin/named-sdb/main.c -@@ -86,6 +86,9 @@ - * Include header files for database drivers here. - */ - /* #include "xxdb.h" */ -+#include "ldapdb.h" -+#include "pgsqldb.h" -+#include "dirdb.h" - - #ifdef CONTRIB_DLZ - /* -@@ -817,6 +820,10 @@ setup(void) { - ns_main_earlyfatal("isc_app_start() failed: %s", - isc_result_totext(result)); - -+ ldapdb_clear(); -+ pgsqldb_clear(); -+ dirdb_clear(); -+ - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, - ISC_LOG_NOTICE, "starting %s %s%s", ns_g_product, - ns_g_version, saved_command_line); -@@ -929,6 +936,57 @@ setup(void) { - isc_result_totext(result)); - #endif - -+ result = ldapdb_init(); -+ if (result != ISC_R_SUCCESS) -+ { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_ERROR, -+ "SDB ldap module initialisation failed: %s.", -+ isc_result_totext(result) -+ ); -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_ERROR, -+ "SDB ldap zone database will be unavailable." -+ ); -+ }else -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_NOTICE, "SDB ldap zone database module loaded." -+ ); -+ -+ result = pgsqldb_init(); -+ if (result != ISC_R_SUCCESS) -+ { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_ERROR, -+ "SDB pgsql module initialisation failed: %s.", -+ isc_result_totext(result) -+ ); -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_ERROR, -+ "SDB pgsql zone database will be unavailable." -+ ); -+ }else -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_NOTICE, "SDB postgreSQL DB zone database module loaded." -+ ); -+ -+ result = dirdb_init(); -+ if (result != ISC_R_SUCCESS) -+ { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_ERROR, -+ "SDB directory DB module initialisation failed: %s.", -+ isc_result_totext(result) -+ ); -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_ERROR, -+ "SDB directory DB zone database will be unavailable." -+ ); -+ }else -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, -+ ISC_LOG_NOTICE, "SDB directory DB zone database module loaded." -+ ); -+ - ns_server_create(ns_g_mctx, &ns_g_server); - } - -@@ -960,6 +1018,10 @@ cleanup(void) { - - dns_name_destroy(); - -+ ldapdb_clear(); -+ pgsqldb_clear(); -+ dirdb_clear(); -+ - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, - ISC_LOG_NOTICE, "exiting"); - ns_log_shutdown(); -diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in -index 5ba3f56..4beeaf0 100644 ---- a/bin/named/Makefile.in -+++ b/bin/named/Makefile.in -@@ -49,7 +49,7 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ - ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ - ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ - --CDEFINES = @CONTRIB_DLZ@ @CRYPTO@ -+CDEFINES = @CRYPTO@ - - CWARNINGS = - -@@ -73,11 +73,11 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ - - LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ - ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ -- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ -+ @LIBS@ - - NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ - ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \ -- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ -+ @LIBS@ - - SUBDIRS = unix - -@@ -92,8 +92,7 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ - tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ - zoneconf.@O@ \ - lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \ -- lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \ -- ${DLZDRIVER_OBJS} ${DBDRIVER_OBJS} -+ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ - - UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ - -@@ -108,8 +107,7 @@ SRCS = builtin.c client.c config.c control.c \ - tkeyconf.c tsigconf.c update.c xfrout.c \ - zoneconf.c \ - lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ -- lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \ -- ${DLZDRIVER_SRCS} ${DBDRIVER_SRCS} -+ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c - - MANPAGES = named.8 lwresd.8 named.conf.5 - -@@ -186,7 +184,5 @@ install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs - ${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8 - ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5 - --@DLZ_DRIVER_RULES@ -- - named-symtbl.@O@: named-symtbl.c - ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c named-symtbl.c -diff --git a/configure.in b/configure.in -index d72f635..1aae803 100644 ---- a/configure.in -+++ b/configure.in -@@ -4050,6 +4050,8 @@ AC_CONFIG_FILES([ - bin/named-pkcs11/Makefile - bin/named-pkcs11/unix/Makefile - bin/named/unix/Makefile -+ bin/named-sdb/Makefile -+ bin/named-sdb/unix/Makefile - bin/nsupdate/Makefile - bin/pkcs11/Makefile - bin/python/Makefile -@@ -4060,6 +4062,7 @@ AC_CONFIG_FILES([ - bin/python/dnssec-coverage.py - bin/python/dnssec-keymgr.py - bin/rndc/Makefile -+ bin/sdb_tools/Makefile - bin/tests/Makefile - bin/tests/atomic/Makefile - bin/tests/db/Makefile diff --git a/SOURCES/bind-9.9-allow_external_dnskey.patch b/SOURCES/bind-9.9-allow_external_dnskey.patch deleted file mode 100644 index 37b3d9f..0000000 --- a/SOURCES/bind-9.9-allow_external_dnskey.patch +++ /dev/null @@ -1,1727 +0,0 @@ -From 0c91911b4d1e872b87eaf6431ed47fe24d18dd43 Mon Sep 17 00:00:00 2001 -From: Mark Andrews -Date: Wed, 4 Sep 2013 13:53:02 +1000 -Subject: [PATCH] 3642. [func] Allow externally generated DNSKEY to - be imported into the DNSKEY management framework. A - new tool dnssec-importkey is used to this. [RT - #34698] - ---- - CHANGES | 4 + - bin/dnssec/.gitignore | 1 + - bin/dnssec/Makefile.in | 8 +- - bin/dnssec/dnssec-importkey.8 | 112 +++++++++ - bin/dnssec/dnssec-importkey.c | 399 +++++++++++++++++++++++++++++++++ - bin/dnssec/dnssec-importkey.docbook | 185 +++++++++++++++ - bin/dnssec/dnssec-importkey.html | 112 +++++++++ - bin/dnssec/dnssec-settime.c | 4 +- - bin/tests/system/conf.sh.in | 1 + - bin/tests/system/inline/clean.sh | 3 + - bin/tests/system/inline/ns1/root.db.in | 3 + - bin/tests/system/inline/ns3/named.conf | 8 + - bin/tests/system/inline/ns3/sign.sh | 29 +++ - bin/tests/system/inline/setup.sh | 1 + - bin/tests/system/inline/tests.sh | 17 +- - lib/dns/dnssec.c | 96 ++++---- - lib/dns/dst_api.c | 10 + - lib/dns/dst_internal.h | 1 + - lib/dns/dst_parse.c | 63 ++++-- - lib/dns/dst_result.c | 2 +- - lib/dns/include/dns/master.h | 1 + - lib/dns/include/dst/dst.h | 6 + - lib/dns/master.c | 4 +- - lib/dns/openssldsa_link.c | 19 ++ - lib/dns/opensslecdsa_link.c | 53 +++-- - lib/dns/opensslgost_link.c | 27 ++- - lib/dns/opensslrsa_link.c | 18 +- - lib/dns/zone.c | 4 + - 28 files changed, 1108 insertions(+), 83 deletions(-) - create mode 100644 bin/dnssec/dnssec-importkey.8 - create mode 100644 bin/dnssec/dnssec-importkey.c - create mode 100644 bin/dnssec/dnssec-importkey.docbook - create mode 100644 bin/dnssec/dnssec-importkey.html - -diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in -index 4f8bceb..ecb0fae 100644 ---- a/bin/dnssec/Makefile.in -+++ b/bin/dnssec/Makefile.in -@@ -45,13 +45,13 @@ NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ - TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \ - dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \ - dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ \ -- dnssec-verify@EXEEXT@ -+ dnssec-verify@EXEEXT@ dnssec-importkey@EXEEXT@ - - OBJS = dnssectool.@O@ - - SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \ - dnssec-revoke.c dnssec-settime.c dnssec-signzone.c \ -- dnssec-verify.c dnssectool.c -+ dnssec-verify.c dnssec-importkey.c dnssectool.c - - MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \ - dnssec-revoke.8 dnssec-settime.8 dnssec-signzone.8 \ -@@ -102,6 +102,10 @@ dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-settime.@O@ ${OBJS} ${LIBS} - -+dnssec-importkey@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ -+ dnssec-importkey.@O@ ${OBJS} ${LIBS} -+ - doc man:: ${MANOBJS} - - docclean manclean maintainer-clean:: -diff --git a/bin/dnssec/dnssec-importkey.8 b/bin/dnssec/dnssec-importkey.8 -new file mode 100644 -index 0000000..33a3ef4 ---- /dev/null -+++ b/bin/dnssec/dnssec-importkey.8 -@@ -0,0 +1,112 @@ -+.\" Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+.\" -+.\" Permission to use, copy, modify, and/or distribute this software for any -+.\" purpose with or without fee is hereby granted, provided that the above -+.\" copyright notice and this permission notice appear in all copies. -+.\" -+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+.\" PERFORMANCE OF THIS SOFTWARE. -+.\" -+.\" $Id$ -+.\" -+.hy 0 -+.ad l -+'\" t -+.\" Title: dnssec-importkey -+.\" Author: [see the "AUTHOR" section] -+.\" Generator: DocBook XSL Stylesheets v1.78.1 -+.\" Date: August 30, 2013 -+.\" Manual: BIND9 -+.\" Source: BIND9 -+.\" Language: English -+.\" -+.TH "DNSSEC\-IMPORTKEY" "8" "August 30, 2013" "BIND9" "BIND9" -+.\" ----------------------------------------------------------------- -+.\" * Define some portability stuff -+.\" ----------------------------------------------------------------- -+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+.\" http://bugs.debian.org/507673 -+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html -+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+.ie \n(.g .ds Aq \(aq -+.el .ds Aq ' -+.\" ----------------------------------------------------------------- -+.\" * set default formatting -+.\" ----------------------------------------------------------------- -+.\" disable hyphenation -+.nh -+.\" disable justification (adjust text to left margin only) -+.ad l -+.\" ----------------------------------------------------------------- -+.\" * MAIN CONTENT STARTS HERE * -+.\" ----------------------------------------------------------------- -+.SH "NAME" -+dnssec-importkey \- Import DNSKEY records from external systems so they can be managed\&. -+.SH "SYNOPSIS" -+.HP 17 -+\fBdnssec\-importkey\fR [\fB\-f\ \fR\fB\fIfilename\fR\fR] [\fB\-K\ \fR\fB\fIdirectory\fR\fR] [\fB\-P\ \fR\fB\fIdate/offset\fR\fR] [\fB\-D\ \fR\fB\fIdate/offset\fR\fR] [\fB\-h\fR] [\fB\-v\ \fR\fB\fIlevel\fR\fR] [\fBkeyname\fR] -+.SH "DESCRIPTION" -+.PP -+\fBdnssec\-importkey\fR -+read a DNSKEY record and generated a \&.key/\&.private key pair\&. Publication (\fB\-P\fR) and deletions (\fB\-D\fR) times can be set for the key\&. -+.SH "OPTIONS" -+.PP -+\-f \fIfilename\fR -+.RS 4 -+Filename to read the key from\&. -+.RE -+.PP -+\-K \fIdirectory\fR -+.RS 4 -+Sets the directory in which the key files are to reside\&. -+.RE -+.PP -+\-L \fIttl\fR -+.RS 4 -+Sets the default TTL to use for this key when it is converted into a DNSKEY RR\&. If the key is imported into a zone, this is the TTL that will be used for it, unless there was already a DNSKEY RRset in place, in which case the existing TTL would take precedence\&. importkey the default TTL to -+0 -+or -+none -+removes it\&. -+.RE -+.PP -+\-h -+.RS 4 -+Emit usage message and exit\&. -+.RE -+.PP -+\-v \fIlevel\fR -+.RS 4 -+Sets the debugging level\&. -+.RE -+.SH "TIMING OPTIONS" -+.PP -+Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS\&. If the argument begins with a \*(Aq+\*(Aq or \*(Aq\-\*(Aq, it is interpreted as an offset from the present time\&. For convenience, if such an offset is followed by one of the suffixes \*(Aqy\*(Aq, \*(Aqmo\*(Aq, \*(Aqw\*(Aq, \*(Aqd\*(Aq, \*(Aqh\*(Aq, or \*(Aqmi\*(Aq, then the offset is computed in years (defined as 365 24\-hour days, ignoring leap years), months (defined as 30 24\-hour days), weeks, days, hours, or minutes, respectively\&. Without a suffix, the offset is computed in seconds\&. To unset a date, use \*(Aqnone\*(Aq\&. -+.PP -+\-P \fIdate/offset\fR -+.RS 4 -+Sets the date on which a key is to be published to the zone\&. After that date, the key will be included in the zone but will not be used to sign it\&. -+.RE -+.PP -+\-D \fIdate/offset\fR -+.RS 4 -+Sets the date on which the key is to be deleted\&. After that date, the key will no longer be included in the zone\&. (It may remain in the key repository, however\&.) -+.RE -+.SH "SEE ALSO" -+.PP -+\fBdnssec-keygen\fR(8), -+\fBdnssec-signzone\fR(8), -+BIND 9 Administrator Reference Manual, -+RFC 5011\&. -+.SH "AUTHOR" -+.PP -+Internet Systems Consortium -+.SH "COPYRIGHT" -+.br -+Copyright \(co 2013 Internet Systems Consortium, Inc. ("ISC") -+.br -diff --git a/bin/dnssec/dnssec-importkey.c b/bin/dnssec/dnssec-importkey.c -new file mode 100644 -index 0000000..3491828 ---- /dev/null -+++ b/bin/dnssec/dnssec-importkey.c -@@ -0,0 +1,399 @@ -+/* -+ * Copyright (C) 2008-2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "dnssectool.h" -+ -+#ifndef PATH_MAX -+#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */ -+#endif -+ -+const char *program = "dnssec-importkey"; -+int verbose; -+ -+static dns_rdataclass_t rdclass; -+static dns_fixedname_t fixed; -+static dns_name_t *name = NULL; -+static isc_mem_t *mctx = NULL; -+static isc_boolean_t setpub = ISC_FALSE, setdel = ISC_FALSE; -+static isc_stdtime_t pub = 0, del = 0; -+ -+static isc_result_t -+initname(char *setname) { -+ isc_result_t result; -+ isc_buffer_t buf; -+ -+ dns_fixedname_init(&fixed); -+ name = dns_fixedname_name(&fixed); -+ -+ isc_buffer_init(&buf, setname, strlen(setname)); -+ isc_buffer_add(&buf, strlen(setname)); -+ result = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); -+ return (result); -+} -+ -+static void -+db_load_from_stream(dns_db_t *db, FILE *fp) { -+ isc_result_t result; -+ dns_rdatacallbacks_t callbacks; -+ -+ dns_rdatacallbacks_init(&callbacks); -+ result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private); -+ if (result != ISC_R_SUCCESS) -+ fatal("dns_db_beginload failed: %s", isc_result_totext(result)); -+ -+ result = dns_master_loadstream(fp, name, name, rdclass, 0, -+ &callbacks, mctx); -+ if (result != ISC_R_SUCCESS) -+ fatal("can't load from input: %s", isc_result_totext(result)); -+ -+ result = dns_db_endload(db, &callbacks.add_private); -+ if (result != ISC_R_SUCCESS) -+ fatal("dns_db_endload failed: %s", isc_result_totext(result)); -+} -+ -+static isc_result_t -+loadset(const char *filename, dns_rdataset_t *rdataset) { -+ isc_result_t result; -+ dns_db_t *db = NULL; -+ dns_dbnode_t *node = NULL; -+ char setname[DNS_NAME_FORMATSIZE]; -+ -+ dns_name_format(name, setname, sizeof(setname)); -+ -+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone, -+ rdclass, 0, NULL, &db); -+ if (result != ISC_R_SUCCESS) -+ fatal("can't create database"); -+ -+ if (strcmp(filename, "-") == 0) { -+ db_load_from_stream(db, stdin); -+ filename = "input"; -+ } else { -+ result = dns_db_load3(db, filename, dns_masterformat_text, -+ DNS_MASTER_NOTTL); -+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) -+ fatal("can't load %s: %s", filename, -+ isc_result_totext(result)); -+ } -+ -+ result = dns_db_findnode(db, name, ISC_FALSE, &node); -+ if (result != ISC_R_SUCCESS) -+ fatal("can't find %s node in %s", setname, filename); -+ -+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, -+ 0, 0, rdataset, NULL); -+ -+ if (result == ISC_R_NOTFOUND) -+ fatal("no DNSKEY RR for %s in %s", setname, filename); -+ else if (result != ISC_R_SUCCESS) -+ fatal("dns_db_findrdataset"); -+ -+ if (node != NULL) -+ dns_db_detachnode(db, &node); -+ if (db != NULL) -+ dns_db_detach(&db); -+ return (result); -+} -+ -+static void -+loadkey(char *filename, unsigned char *key_buf, unsigned int key_buf_size, -+ dns_rdata_t *rdata) -+{ -+ isc_result_t result; -+ dst_key_t *key = NULL; -+ isc_buffer_t keyb; -+ isc_region_t r; -+ -+ dns_rdata_init(rdata); -+ -+ isc_buffer_init(&keyb, key_buf, key_buf_size); -+ -+ result = dst_key_fromnamedfile(filename, NULL, DST_TYPE_PUBLIC, -+ mctx, &key); -+ if (result != ISC_R_SUCCESS) -+ fatal("invalid keyfile name %s: %s", -+ filename, isc_result_totext(result)); -+ -+ if (verbose > 2) { -+ char keystr[DST_KEY_FORMATSIZE]; -+ -+ dst_key_format(key, keystr, sizeof(keystr)); -+ fprintf(stderr, "%s: %s\n", program, keystr); -+ } -+ -+ result = dst_key_todns(key, &keyb); -+ if (result != ISC_R_SUCCESS) -+ fatal("can't decode key"); -+ -+ isc_buffer_usedregion(&keyb, &r); -+ dns_rdata_fromregion(rdata, dst_key_class(key), -+ dns_rdatatype_dnskey, &r); -+ -+ rdclass = dst_key_class(key); -+ -+ dns_fixedname_init(&fixed); -+ name = dns_fixedname_name(&fixed); -+ result = dns_name_copy(dst_key_name(key), name, NULL); -+ if (result != ISC_R_SUCCESS) -+ fatal("can't copy name"); -+ -+ dst_key_free(&key); -+} -+ -+static void -+emit(const char *dir, dns_rdata_t *rdata) { -+ isc_result_t result; -+ char keystr[DST_KEY_FORMATSIZE]; -+ char newname[1024]; -+ isc_buffer_t buf; -+ dst_key_t *key = NULL; -+ -+ isc_buffer_init(&buf, rdata->data, rdata->length); -+ isc_buffer_add(&buf, rdata->length); -+ result = dst_key_fromdns(name, rdclass, &buf, mctx, &key); -+ if (result != ISC_R_SUCCESS) { -+ fatal("dst_key_fromdns: %s", isc_result_totext(result)); -+ } -+ -+ dst_key_setexternal(key, ISC_TRUE); -+ if (setpub) -+ dst_key_settime(key, DST_TIME_PUBLISH, pub); -+ if (setdel) -+ dst_key_settime(key, DST_TIME_DELETE, del); -+ -+ isc_buffer_init(&buf, newname, sizeof(newname)); -+ result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); -+ if (result != ISC_R_SUCCESS) { -+ fatal("Failed to build public key filename: %s", -+ isc_result_totext(result)); -+ } -+ -+ result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, -+ dir); -+ if (result != ISC_R_SUCCESS) { -+ dst_key_format(key, keystr, sizeof(keystr)); -+ fatal("Failed to write key %s: %s", keystr, -+ isc_result_totext(result)); -+ } -+ -+ printf("%s\n", newname); -+ -+ isc_buffer_clear(&buf); -+ result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); -+ if (result != ISC_R_SUCCESS) { -+ fatal("Failed to build private key filename: %s", -+ isc_result_totext(result)); -+ } -+ printf("%s\n", newname); -+ dst_key_free(&key); -+} -+ -+ISC_PLATFORM_NORETURN_PRE static void -+usage(void) ISC_PLATFORM_NORETURN_POST; -+ -+static void -+usage(void) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, " %s options [-K dir] file\n\n", program); -+ fprintf(stderr, "Version: %s\n", VERSION); -+ fprintf(stderr, "Options:\n"); -+ fprintf(stderr, " -v \n"); -+ fprintf(stderr, " -K : directory in which to store " -+ "the keyset files\n"); -+ fprintf(stderr, " -f file: read keyset from zone file\n"); -+ -+ exit (-1); -+} -+ -+int -+main(int argc, char **argv) { -+ char *classname = NULL; -+ char *filename = NULL, *dir = NULL, *namestr; -+ char *endp; -+ int ch; -+ isc_result_t result; -+ isc_log_t *log = NULL; -+ isc_entropy_t *ectx = NULL; -+ dns_rdataset_t rdataset; -+ dns_rdata_t rdata; -+ isc_stdtime_t now; -+ -+ dns_rdata_init(&rdata); -+ isc_stdtime_get(&now); -+ -+ if (argc == 1) -+ usage(); -+ -+ result = isc_mem_create(0, 0, &mctx); -+ if (result != ISC_R_SUCCESS) -+ fatal("out of memory"); -+ -+ dns_result_register(); -+ -+ isc_commandline_errprint = ISC_FALSE; -+ -+ while ((ch = isc_commandline_parse(argc, argv, "D:f:hK:P:v:")) != -1) { -+ switch (ch) { -+ case 'D': -+ if (setdel) -+ fatal("-D specified more than once"); -+ -+ setdel = ISC_TRUE; -+ del = strtotime(isc_commandline_argument, now, now); -+ break; -+ case 'K': -+ dir = isc_commandline_argument; -+ if (strlen(dir) == 0U) -+ fatal("directory must be non-empty string"); -+ break; -+ case 'P': -+ if (setpub) -+ fatal("-P specified more than once"); -+ -+ setpub = ISC_TRUE; -+ pub = strtotime(isc_commandline_argument, now, now); -+ break; -+ case 'f': -+ filename = isc_commandline_argument; -+ break; -+ case 'v': -+ verbose = strtol(isc_commandline_argument, &endp, 0); -+ if (*endp != '\0') -+ fatal("-v must be followed by a number"); -+ break; -+ case '?': -+ if (isc_commandline_option != '?') -+ fprintf(stderr, "%s: invalid argument -%c\n", -+ program, isc_commandline_option); -+ /* FALLTHROUGH */ -+ case 'h': -+ usage(); -+ -+ default: -+ fprintf(stderr, "%s: unhandled option -%c\n", -+ program, isc_commandline_option); -+ exit(1); -+ } -+ } -+ -+ rdclass = strtoclass(classname); -+ -+ if (argc < isc_commandline_index + 1 && filename == NULL) -+ fatal("the key file name was not specified"); -+ if (argc > isc_commandline_index + 1) -+ fatal("extraneous arguments"); -+ -+ if (ectx == NULL) -+ setup_entropy(mctx, NULL, &ectx); -+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE); -+ if (result != ISC_R_SUCCESS) -+ fatal("could not initialize hash"); -+ result = dst_lib_init(mctx, ectx, -+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY); -+ if (result != ISC_R_SUCCESS) -+ fatal("could not initialize dst: %s", -+ isc_result_totext(result)); -+ isc_entropy_stopcallbacksources(ectx); -+ -+ setup_logging(verbose, mctx, &log); -+ -+ dns_rdataset_init(&rdataset); -+ -+ if (filename != NULL) { -+ if (argc < isc_commandline_index + 1 && filename != NULL) { -+ /* using zone name as the zone file name */ -+ namestr = filename; -+ } else -+ namestr = argv[isc_commandline_index]; -+ -+ result = initname(namestr); -+ if (result != ISC_R_SUCCESS) -+ fatal("could not initialize name %s", namestr); -+ -+ result = loadset(filename, &rdataset); -+ -+ if (result != ISC_R_SUCCESS) -+ fatal("could not load DNSKEY set: %s\n", -+ isc_result_totext(result)); -+ -+ for (result = dns_rdataset_first(&rdataset); -+ result == ISC_R_SUCCESS; -+ result = dns_rdataset_next(&rdataset)) { -+ -+ dns_rdata_init(&rdata); -+ dns_rdataset_current(&rdataset, &rdata); -+ emit(dir, &rdata); -+ } -+ } else { -+ unsigned char key_buf[DST_KEY_MAXSIZE]; -+ -+ loadkey(argv[isc_commandline_index], key_buf, -+ DST_KEY_MAXSIZE, &rdata); -+ -+ emit(dir, &rdata); -+ } -+ -+ if (dns_rdataset_isassociated(&rdataset)) -+ dns_rdataset_disassociate(&rdataset); -+ cleanup_logging(&log); -+ dst_lib_destroy(); -+ isc_hash_destroy(); -+ cleanup_entropy(&ectx); -+ dns_name_destroy(); -+ if (verbose > 10) -+ isc_mem_stats(mctx, stdout); -+ isc_mem_destroy(&mctx); -+ -+ fflush(stdout); -+ if (ferror(stdout)) { -+ fprintf(stderr, "write error\n"); -+ return (1); -+ } else -+ return (0); -+} -diff --git a/bin/dnssec/dnssec-importkey.docbook b/bin/dnssec/dnssec-importkey.docbook -new file mode 100644 -index 0000000..b8d160c ---- /dev/null -+++ b/bin/dnssec/dnssec-importkey.docbook -@@ -0,0 +1,185 @@ -+]> -+ -+ -+ -+ -+ -+ August 30, 2013 -+ -+ -+ -+ dnssec-importkey -+ 8 -+ BIND9 -+ -+ -+ -+ dnssec-importkey -+ Import DNSKEY records from external systems so they can be managed. -+ -+ -+ -+ -+ 2013 -+ Internet Systems Consortium, Inc. ("ISC") -+ -+ -+ -+ -+ -+ dnssec-importkey -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ DESCRIPTION -+ dnssec-importkey -+ read a DNSKEY record and generated a .key/.private key pair. -+ Publication () and deletions () -+ times can be set for the key. -+ -+ -+ -+ -+ OPTIONS -+ -+ -+ -+ -f filename -+ -+ -+ Filename to read the key from. -+ -+ -+ -+ -+ -+ -K directory -+ -+ -+ Sets the directory in which the key files are to reside. -+ -+ -+ -+ -+ -+ -L ttl -+ -+ -+ Sets the default TTL to use for this key when it is converted -+ into a DNSKEY RR. If the key is imported into a zone, -+ this is the TTL that will be used for it, unless there was -+ already a DNSKEY RRset in place, in which case the existing TTL -+ would take precedence. importkey the default TTL to -+ 0 or none removes it. -+ -+ -+ -+ -+ -+ -h -+ -+ -+ Emit usage message and exit. -+ -+ -+ -+ -+ -+ -v level -+ -+ -+ Sets the debugging level. -+ -+ -+ -+ -+ -+ -+ -+ -+ TIMING OPTIONS -+ -+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. -+ If the argument begins with a '+' or '-', it is interpreted as -+ an offset from the present time. For convenience, if such an offset -+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', -+ then the offset is computed in years (defined as 365 24-hour days, -+ ignoring leap years), months (defined as 30 24-hour days), weeks, -+ days, hours, or minutes, respectively. Without a suffix, the offset -+ is computed in seconds. To unset a date, use 'none'. -+ -+ -+ -+ -+ -P date/offset -+ -+ -+ Sets the date on which a key is to be published to the zone. -+ After that date, the key will be included in the zone but will -+ not be used to sign it. -+ -+ -+ -+ -+ -+ -D date/offset -+ -+ -+ Sets the date on which the key is to be deleted. After that -+ date, the key will no longer be included in the zone. (It -+ may remain in the key repository, however.) -+ -+ -+ -+ -+ -+ -+ -+ -+ SEE ALSO -+ -+ dnssec-keygen8 -+ , -+ -+ dnssec-signzone8 -+ , -+ BIND 9 Administrator Reference Manual, -+ RFC 5011. -+ -+ -+ -+ -+ AUTHOR -+ Internet Systems Consortium -+ -+ -+ -+ -diff --git a/bin/dnssec/dnssec-importkey.html b/bin/dnssec/dnssec-importkey.html -new file mode 100644 -index 0000000..f74be50 ---- /dev/null -+++ b/bin/dnssec/dnssec-importkey.html -@@ -0,0 +1,112 @@ -+ -+ -+ -+ -+ -+dnssec-importkey -+ -+ -+
-+
-+
-+

Name

-+

dnssec-importkey — Import DNSKEY records from external systems so they can be managed.

-+
-+
-+

Synopsis

-+

dnssec-importkey [-f filename] [-K directory] [-P date/offset] [-D date/offset] [-h] [-v level] [keyname]

-+
-+
-+

DESCRIPTION

-+

dnssec-importkey -+ read a DNSKEY record and generated a .key/.private key pair. -+ Publication (-P) and deletions (-D) -+ times can be set for the key. -+

-+
-+
-+

OPTIONS

-+
-+
-f filename
-+

-+ Filename to read the key from. -+

-+
-K directory
-+

-+ Sets the directory in which the key files are to reside. -+

-+
-L ttl
-+

-+ Sets the default TTL to use for this key when it is converted -+ into a DNSKEY RR. If the key is imported into a zone, -+ this is the TTL that will be used for it, unless there was -+ already a DNSKEY RRset in place, in which case the existing TTL -+ would take precedence. importkey the default TTL to -+ 0 or none removes it. -+

-+
-h
-+

-+ Emit usage message and exit. -+

-+
-v level
-+

-+ Sets the debugging level. -+

-+
-+
-+
-+

TIMING OPTIONS

-+

-+ Dates can be expressed in the format YYYYMMDD or YYYYMMDDHHMMSS. -+ If the argument begins with a '+' or '-', it is interpreted as -+ an offset from the present time. For convenience, if such an offset -+ is followed by one of the suffixes 'y', 'mo', 'w', 'd', 'h', or 'mi', -+ then the offset is computed in years (defined as 365 24-hour days, -+ ignoring leap years), months (defined as 30 24-hour days), weeks, -+ days, hours, or minutes, respectively. Without a suffix, the offset -+ is computed in seconds. To unset a date, use 'none'. -+

-+
-+
-P date/offset
-+

-+ Sets the date on which a key is to be published to the zone. -+ After that date, the key will be included in the zone but will -+ not be used to sign it. -+

-+
-D date/offset
-+

-+ Sets the date on which the key is to be deleted. After that -+ date, the key will no longer be included in the zone. (It -+ may remain in the key repository, however.) -+

-+
-+
-+
-+

SEE ALSO

-+

dnssec-keygen(8), -+ dnssec-signzone(8), -+ BIND 9 Administrator Reference Manual, -+ RFC 5011. -+

-+
-+
-+

AUTHOR

-+

Internet Systems Consortium -+

-+
-+
-+ -diff --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c -index 4c88a07..108d803 100644 ---- a/bin/dnssec/dnssec-settime.c -+++ b/bin/dnssec/dnssec-settime.c -@@ -370,7 +370,7 @@ main(int argc, char **argv) { - if (result != ISC_R_SUCCESS) - fatal("Invalid keyfile %s: %s", - filename, isc_result_totext(result)); -- if (!dst_key_isprivate(prevkey)) -+ if (!dst_key_isprivate(prevkey) && !dst_key_isexternal(prevkey)) - fatal("%s is not a private key", filename); - - name = dst_key_name(prevkey); -@@ -462,7 +462,7 @@ main(int argc, char **argv) { - fatal("Invalid keyfile %s: %s", - filename, isc_result_totext(result)); - -- if (!dst_key_isprivate(key)) -+ if (!dst_key_isprivate(key) && !dst_key_isexternal(key)) - fatal("%s is not a private key", filename); - - dst_key_format(key, keystr, sizeof(keystr)); -diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in -index 60f22f8..b15853d 100644 ---- a/bin/tests/system/conf.sh.in -+++ b/bin/tests/system/conf.sh.in -@@ -43,6 +43,7 @@ SIGNER=$TOP/bin/dnssec/dnssec-signzone - REVOKE=$TOP/bin/dnssec/dnssec-revoke - SETTIME=$TOP/bin/dnssec/dnssec-settime - DSFROMKEY=$TOP/bin/dnssec/dnssec-dsfromkey -+IMPORTKEY=$TOP/bin/dnssec/dnssec-importkey - CHECKDS=$TOP/bin/python/dnssec-checkds - COVERAGE=$TOP/bin/python/dnssec-coverage - CHECKZONE=$TOP/bin/check/named-checkzone -diff --git a/bin/tests/system/inline/clean.sh b/bin/tests/system/inline/clean.sh -index 8ef3e2c..412031a 100644 ---- a/bin/tests/system/inline/clean.sh -+++ b/bin/tests/system/inline/clean.sh -@@ -60,6 +60,9 @@ rm -f ns3/retransfer.bk - rm -f ns3/retransfer.bk.jnl - rm -f ns3/retransfer.bk.signed - rm -f ns3/retransfer.bk.signed.jnl -+rm -f ns3/externalkey.db -+rm -f ns3/externalkey.db.signed -+rm -f ns3/externalkey.db.signed.jnl - rm -f ns4/K* - rm -f ns4/noixfr.db - rm -f ns4/noixfr.db.jnl -diff --git a/bin/tests/system/inline/ns1/root.db.in b/bin/tests/system/inline/ns1/root.db.in -index 8d3af51..a08db51 100644 ---- a/bin/tests/system/inline/ns1/root.db.in -+++ b/bin/tests/system/inline/ns1/root.db.in -@@ -50,3 +50,6 @@ ns3.retransfer. A 10.53.0.3 - - nsec3. NS ns3.nsec3. - ns3.nsec3. A 10.53.0.3 -+ -+externalkey. NS ns3.externalkey. -+ns3.externalkey. A 10.53.0.3 -diff --git a/bin/tests/system/inline/ns3/named.conf b/bin/tests/system/inline/ns3/named.conf -index a17384c..7c23edd 100644 ---- a/bin/tests/system/inline/ns3/named.conf -+++ b/bin/tests/system/inline/ns3/named.conf -@@ -103,3 +103,11 @@ zone "nsec3" { - allow-update { any; }; - file "nsec3.db"; - }; -+ -+zone "externalkey" { -+ type master; -+ inline-signing yes; -+ auto-dnssec maintain; -+ allow-update { any; }; -+ file "externalkey.db"; -+}; -diff --git a/bin/tests/system/inline/ns3/sign.sh b/bin/tests/system/inline/ns3/sign.sh -index bbd11af..f695973 100644 ---- a/bin/tests/system/inline/ns3/sign.sh -+++ b/bin/tests/system/inline/ns3/sign.sh -@@ -92,3 +92,32 @@ do - keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone` - keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -f KSK $zone` - done -+ -+zone=externalkey -+rm -f K${zone}.+*+*.key -+rm -f K${zone}.+*+*.private -+ -+for alg in ECDSAP256SHA256 NSEC3RSASHA1 DSA ECCGOST -+do -+ -+if test $alg = ECCGOST -+then -+ sh ../../gost/prereq.sh 2> /dev/null || continue -+fi -+ -+k1=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone -f KSK $zone` -+k2=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone $zone` -+k3=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone $zone` -+k4=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone $zone` -+keyname=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone $zone` -+keyname=`$KEYGEN -q -r $RANDFILE -a $alg -b 1024 -n zone -f KSK $zone` -+$DSFROMKEY -T 1200 $keyname >> ../ns1/root.db -+rm -f ${k3}.* ${k4}.* -+ -+# -+# Convert k1 and k2 in to External Keys. -+rm -f $k1.private -+$IMPORTKEY -P now -D now+3600 -f $k1.key $zone -+rm -f $k2.private -+$IMPORTKEY -f $k2.key $zone -+done -diff --git a/bin/tests/system/inline/setup.sh b/bin/tests/system/inline/setup.sh -index 9fa42ab..adee4ff 100644 ---- a/bin/tests/system/inline/setup.sh -+++ b/bin/tests/system/inline/setup.sh -@@ -29,6 +29,7 @@ cp ns3/master.db.in ns3/dynamic.db - cp ns3/master.db.in ns3/updated.db - cp ns3/master.db.in ns3/expired.db - cp ns3/master.db.in ns3/nsec3.db -+cp ns3/master.db.in ns3/externalkey.db - - touch ns4/trusted.conf - cp ns4/noixfr.db.in ns4/noixfr.db -diff --git a/bin/tests/system/inline/tests.sh b/bin/tests/system/inline/tests.sh -index 7e2e3d2..8acdee2 100644 ---- a/bin/tests/system/inline/tests.sh -+++ b/bin/tests/system/inline/tests.sh -@@ -809,7 +809,22 @@ $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 addzone test-$zone \ - $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 delzone test-$zone - done - --if [ $ret != 0 ]; then echo "I:failed"; fi -+n=`expr $n + 1` -+echo "I:testing adding external keys to a inline zone ($n)" -+ret=0 -+$DIG $DIGOPTS @10.53.0.3 -p 5300 dnskey externalkey > dig.out.ns3.test$n -+for alg in 3 7 12 13 -+do -+if test $alg = 12 -+then -+ sh ../gost/prereq.sh 2>/dev/null || continue; -+fi -+ -+dnskeys=`grep "IN.DNSKEY.25[67] [0-9]* $alg " dig.out.ns3.test$n | wc -l` -+rrsigs=`grep "RRSIG.DNSKEY $alg " dig.out.ns3.test$n | wc -l` -+test ${dnskeys:-0} -eq 3 || { echo "I: failed $alg (dnskeys ${dnskeys:-0})"; ret=1; } -+test ${rrsigs:-0} -eq 2 || { echo "I: failed $alg (rrsigs ${rrsigs:-0})"; ret=1; } -+done - status=`expr $status + $ret` - - exit $status -diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c -index a1c5c69..cf97404 100644 ---- a/lib/dns/dnssec.c -+++ b/lib/dns/dnssec.c -@@ -684,6 +684,7 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, - isc_stdtime_get(&now); - - *nkeys = 0; -+ memset(keys, 0, sizeof(*keys) * maxkeys); - dns_rdataset_init(&rdataset); - RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, - &rdataset, NULL)); -@@ -1312,9 +1313,9 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, - isc_dir_t dir; - dns_dnsseckey_t *key = NULL; - dst_key_t *dstkey = NULL; -- char namebuf[DNS_NAME_FORMATSIZE], *p; -+ char namebuf[DNS_NAME_FORMATSIZE]; - isc_buffer_t b; -- unsigned int len; -+ unsigned int len, i; - isc_stdtime_t now; - - REQUIRE(keylist != NULL); -@@ -1334,49 +1335,62 @@ dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, - isc_stdtime_get(&now); - - while (isc_dir_read(&dir) == ISC_R_SUCCESS) { -- if (dir.entry.name[0] == 'K' && -- dir.entry.length > len + 1 && -- dir.entry.name[len + 1] == '+' && -- strncasecmp(dir.entry.name + 1, namebuf, len) == 0) { -- p = strrchr(dir.entry.name, '.'); -- if (p != NULL && strcmp(p, ".private") != 0) -- continue; -+ if (dir.entry.name[0] != 'K' || -+ dir.entry.length < len + 1 || -+ dir.entry.name[len + 1] != '+' || -+ strncasecmp(dir.entry.name + 1, namebuf, len) != 0) -+ continue; -+ -+ for (i = len + 1 + 1; i < dir.entry.length ; i++) -+ if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9') -+ break; -+ -+ if (i == len + 1 + 1 || i >= dir.entry.length || -+ dir.entry.name[i] != '+') -+ continue; -+ -+ for (i++ ; i < dir.entry.length ; i++) -+ if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9') -+ break; - -- dstkey = NULL; -- result = dst_key_fromnamedfile(dir.entry.name, -- directory, -- DST_TYPE_PUBLIC | -- DST_TYPE_PRIVATE, -- mctx, &dstkey); -- -- if (result != ISC_R_SUCCESS) { -- isc_log_write(dns_lctx, -- DNS_LOGCATEGORY_GENERAL, -- DNS_LOGMODULE_DNSSEC, -- ISC_LOG_WARNING, -- "dns_dnssec_findmatchingkeys: " -- "error reading key file %s: %s", -- dir.entry.name, -- isc_result_totext(result)); -+ if (strcmp(dir.entry.name + i, ".private") != 0) - continue; -- } - -- RETERR(dns_dnsseckey_create(mctx, &dstkey, &key)); -- key->source = dns_keysource_repository; -- get_hints(key, now); -+ dstkey = NULL; -+ result = dst_key_fromnamedfile(dir.entry.name, -+ directory, -+ DST_TYPE_PUBLIC | -+ DST_TYPE_PRIVATE, -+ mctx, &dstkey); - -- if (key->legacy) { -- dns_dnsseckey_destroy(mctx, &key); -- } else { -- ISC_LIST_APPEND(list, key, link); -- key = NULL; -- } -+ if (result != ISC_R_SUCCESS) { -+ isc_log_write(dns_lctx, -+ DNS_LOGCATEGORY_GENERAL, -+ DNS_LOGMODULE_DNSSEC, -+ ISC_LOG_WARNING, -+ "dns_dnssec_findmatchingkeys: " -+ "error reading key file %s: %s", -+ dir.entry.name, -+ isc_result_totext(result)); -+ continue; -+ } -+ -+ RETERR(dns_dnsseckey_create(mctx, &dstkey, &key)); -+ key->source = dns_keysource_repository; -+ get_hints(key, now); -+ -+ if (key->legacy) { -+ dns_dnsseckey_destroy(mctx, &key); -+ } else { -+ ISC_LIST_APPEND(list, key, link); -+ key = NULL; - } - } - -- if (!ISC_LIST_EMPTY(list)) -+ if (!ISC_LIST_EMPTY(list)) { -+ result = ISC_R_SUCCESS; - ISC_LIST_APPENDLIST(*keylist, list, link); -- else -+ } else - result = ISC_R_NOTFOUND; - - failure: -@@ -1794,7 +1808,13 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, - for (key2 = ISC_LIST_HEAD(*keys); - key2 != NULL; - key2 = ISC_LIST_NEXT(key2, link)) { -- if (dst_key_pubcompare(key1->key, key2->key, -+ int f1 = dst_key_flags(key1->key); -+ int f2 = dst_key_flags(key2->key); -+ int nr1 = f1 & ~DNS_KEYFLAG_REVOKE; -+ int nr2 = f2 & ~DNS_KEYFLAG_REVOKE; -+ if (nr1 == nr2 && -+ dst_key_alg(key1->key) == dst_key_alg(key2->key) && -+ dst_key_pubcompare(key1->key, key2->key, - ISC_TRUE)) { - int r1, r2; - r1 = dst_key_flags(key1->key) & -diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c -index c310be5..4c174f3 100644 ---- a/lib/dns/dst_api.c -+++ b/lib/dns/dst_api.c -@@ -448,6 +448,16 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory) { - return (ISC_R_SUCCESS); - } - -+void -+dst_key_setexternal(dst_key_t *key, isc_boolean_t value) { -+ key->external = value; -+} -+ -+isc_boolean_t -+dst_key_isexternal(dst_key_t *key) { -+ return (key->external); -+} -+ - isc_result_t - dst_key_fromfile(dns_name_t *name, dns_keytag_t id, - unsigned int alg, int type, const char *directory, -diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h -index 48ce9b8..49ca424 100644 ---- a/lib/dns/dst_internal.h -+++ b/lib/dns/dst_internal.h -@@ -128,6 +128,7 @@ struct dst_key { - isc_boolean_t numset[DST_MAX_NUMERIC + 1]; /*%< data set? */ - isc_boolean_t inactive; /*%< private key not present as it is - inactive */ -+ isc_boolean_t external; /*%< external key */ - - int fmt_major; /*%< private key format, major version */ - int fmt_minor; /*%< private key format, minor version */ -diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c -index ca43cb3..6348cc1 100644 ---- a/lib/dns/dst_parse.c -+++ b/lib/dns/dst_parse.c -@@ -178,14 +178,18 @@ find_numericdata(const char *s) { - } - - static int --check_rsa(const dst_private_t *priv) { -+check_rsa(const dst_private_t *priv, isc_boolean_t external) { - int i, j; - isc_boolean_t have[RSA_NTAGS]; - isc_boolean_t ok; - unsigned int mask; - -+ if (external) -+ return ((priv->nelements == 0) ? 0 : -1); -+ - for (i = 0; i < RSA_NTAGS; i++) - have[i] = ISC_FALSE; -+ - for (j = 0; j < priv->nelements; j++) { - for (i = 0; i < RSA_NTAGS; i++) - if (priv->elements[j].tag == TAG(DST_ALG_RSAMD5, i)) -@@ -231,10 +235,15 @@ check_dh(const dst_private_t *priv) { - } - - static int --check_dsa(const dst_private_t *priv) { -+check_dsa(const dst_private_t *priv, isc_boolean_t external) { - int i, j; -+ -+ if (external) -+ return ((priv->nelements == 0)? 0 : -1); -+ - if (priv->nelements != DSA_NTAGS) - return (-1); -+ - for (i = 0; i < DSA_NTAGS; i++) { - for (j = 0; j < priv->nelements; j++) - if (priv->elements[j].tag == TAG(DST_ALG_DSA, i)) -@@ -246,7 +255,11 @@ check_dsa(const dst_private_t *priv) { - } - - static int --check_gost(const dst_private_t *priv) { -+check_gost(const dst_private_t *priv, isc_boolean_t external) { -+ -+ if (external) -+ return ((priv->nelements == 0)? 0 : -1); -+ - if (priv->nelements != GOST_NTAGS) - return (-1); - if (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) -@@ -255,7 +268,11 @@ check_gost(const dst_private_t *priv) { - } - - static int --check_ecdsa(const dst_private_t *priv) { -+check_ecdsa(const dst_private_t *priv, isc_boolean_t external) { -+ -+ if (external) -+ return ((priv->nelements == 0) ? 0 : -1); -+ - if (priv->nelements != ECDSA_NTAGS) - return (-1); - if (priv->elements[0].tag != TAG(DST_ALG_ECDSA256, 0)) -@@ -309,7 +326,7 @@ check_hmac_sha(const dst_private_t *priv, unsigned int ntags, - - static int - check_data(const dst_private_t *priv, const unsigned int alg, -- isc_boolean_t old) -+ isc_boolean_t old, isc_boolean_t external) - { - /* XXXVIX this switch statement is too sparse to gen a jump table. */ - switch (alg) { -@@ -318,17 +335,17 @@ check_data(const dst_private_t *priv, const unsigned int alg, - case DST_ALG_NSEC3RSASHA1: - case DST_ALG_RSASHA256: - case DST_ALG_RSASHA512: -- return (check_rsa(priv)); -+ return (check_rsa(priv, external)); - case DST_ALG_DH: - return (check_dh(priv)); - case DST_ALG_DSA: - case DST_ALG_NSEC3DSA: -- return (check_dsa(priv)); -+ return (check_dsa(priv, external)); - case DST_ALG_ECCGOST: -- return (check_gost(priv)); -+ return (check_gost(priv, external)); - case DST_ALG_ECDSA256: - case DST_ALG_ECDSA384: -- return (check_ecdsa(priv)); -+ return (check_ecdsa(priv, external)); - case DST_ALG_HMACMD5: - return (check_hmac_md5(priv, old)); - case DST_ALG_HMACSHA1: -@@ -372,6 +389,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, - unsigned int opt = ISC_LEXOPT_EOL; - isc_stdtime_t when; - isc_result_t ret; -+ isc_boolean_t external = ISC_FALSE; - - REQUIRE(priv != NULL); - -@@ -467,9 +485,15 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, - - if (token.type != isc_tokentype_string) { - ret = DST_R_INVALIDPRIVATEKEY; -+ NEXTTOKEN(lex, opt, &token); - goto fail; - } - -+ if (strcmp(DST_AS_STR(token), "External:") == 0) { -+ external = ISC_TRUE; -+ goto next; -+ } -+ - /* Numeric metadata */ - tag = find_numericdata(DST_AS_STR(token)); - if (tag >= 0) { -@@ -534,8 +558,14 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, - READLINE(lex, opt, &token); - data = NULL; - } -+ - done: -- check = check_data(priv, alg, ISC_TRUE); -+ if (external && priv->nelements != 0) { -+ ret = DST_R_INVALIDPRIVATEKEY; -+ goto fail; -+ } -+ -+ check = check_data(priv, alg, ISC_TRUE, external); - if (check < 0) { - ret = DST_R_INVALIDPRIVATEKEY; - goto fail; -@@ -544,6 +574,8 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, - goto fail; - } - -+ key->external = external; -+ - return (ISC_R_SUCCESS); - - fail: -@@ -573,7 +605,7 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, - - REQUIRE(priv != NULL); - -- ret = check_data(priv, dst_key_alg(key), ISC_FALSE); -+ ret = check_data(priv, dst_key_alg(key), ISC_FALSE, key->external); - if (ret < 0) - return (DST_R_INVALIDPRIVATEKEY); - else if (ret != ISC_R_SUCCESS) -@@ -691,6 +723,9 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, - fprintf(fp, "%s %.*s\n", s, (int)r.length, r.base); - } - -+ if (key->external) -+ fprintf(fp, "External:\n"); -+ - /* Add the metadata tags */ - if (major > 1 || (major == 1 && minor >= 3)) { - for (i = 0; i < NUMERIC_NTAGS; i++) { -@@ -706,14 +741,14 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, - - isc_buffer_init(&b, buffer, sizeof(buffer)); - result = dns_time32_totext(when, &b); -- if (result != ISC_R_SUCCESS) { -+ if (result != ISC_R_SUCCESS) { - fclose(fp); - return (DST_R_INVALIDPRIVATEKEY); -- } -+ } - - isc_buffer_usedregion(&b, &r); - -- fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length, -+ fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length, - r.base); - } - } -diff --git a/lib/dns/dst_result.c b/lib/dns/dst_result.c -index 297e809..30aa1fa 100644 ---- a/lib/dns/dst_result.c -+++ b/lib/dns/dst_result.c -@@ -35,7 +35,7 @@ static const char *text[DST_R_NRESULTS] = { - "illegal operation for a null key", /*%< 3 */ - "public key is invalid", /*%< 4 */ - "private key is invalid", /*%< 5 */ -- "UNUSED6", /*%< 6 */ -+ "external key", /*%< 6 */ - "error occurred writing key to disk", /*%< 7 */ - "invalid algorithm specific parameter", /*%< 8 */ - "UNUSED9", /*%< 9 */ -diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h -index 6abcb7e..931e930 100644 ---- a/lib/dns/include/dns/master.h -+++ b/lib/dns/include/dns/master.h -@@ -57,6 +57,7 @@ - - #define DNS_MASTER_RESIGN 0x00002000 - #define DNS_MASTER_KEY 0x00004000 /*%< Loading a key zone master file. */ -+#define DNS_MASTER_NOTTL 0x00008000 /*%< Don't require ttl. */ - - ISC_LANG_BEGINDECLS - -diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h -index 6ce3a0c..8676d1a 100644 ---- a/lib/dns/include/dst/dst.h -+++ b/lib/dns/include/dst/dst.h -@@ -953,6 +953,12 @@ dst_key_setinactive(dst_key_t *key, isc_boolean_t inactive); - * 'key' to be valid. - */ - -+void -+dst_key_setexternal(dst_key_t *key, isc_boolean_t value); -+ -+isc_boolean_t -+dst_key_isexternal(dst_key_t *key); -+ - ISC_LANG_ENDDECLS - - #endif /* DST_DST_H */ -diff --git a/lib/dns/master.c b/lib/dns/master.c -index aa8f1ac..1a2c84a 100644 ---- a/lib/dns/master.c -+++ b/lib/dns/master.c -@@ -592,9 +592,9 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, - isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE); - } - -- lctx->ttl_known = ISC_FALSE; -+ lctx->ttl_known = ISC_TF((options & DNS_MASTER_NOTTL) != 0); - lctx->ttl = 0; -- lctx->default_ttl_known = ISC_FALSE; -+ lctx->default_ttl_known = lctx->ttl_known; - lctx->default_ttl = 0; - lctx->warn_1035 = ISC_TRUE; /* XXX Argument? */ - lctx->warn_tcr = ISC_TRUE; /* XXX Argument? */ -diff --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c -index 8bea1c0..a24baae 100644 ---- a/lib/dns/openssldsa_link.c -+++ b/lib/dns/openssldsa_link.c -@@ -522,6 +522,11 @@ openssldsa_tofile(const dst_key_t *key, const char *directory) { - - if (key->keydata.dsa == NULL) - return (DST_R_NULLKEY); -+ -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } - - dsa = key->keydata.dsa; - -@@ -569,6 +574,7 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - #define DST_RET(a) {ret = a; goto err;} - - UNUSED(pub); -+ - /* read private key file */ - ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv); - if (ret != ISC_R_SUCCESS) -@@ -607,6 +613,19 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - } - dst__privstruct_free(&priv, mctx); - -+ if (key->external) { -+ if (pub == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ dsa->q = pub->keydata.dsa->q; -+ pub->keydata.dsa->q = NULL; -+ dsa->p = pub->keydata.dsa->p; -+ pub->keydata.dsa->p = NULL; -+ dsa->g = pub->keydata.dsa->g; -+ pub->keydata.dsa->g = NULL; -+ dsa->pub_key = pub->keydata.dsa->pub_key; -+ pub->keydata.dsa->pub_key = NULL; -+ } -+ - key->key_size = BN_num_bits(dsa->p); - - return (ISC_R_SUCCESS); -diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c -index c3f5061..7eff9a0 100644 ---- a/lib/dns/opensslecdsa_link.c -+++ b/lib/dns/opensslecdsa_link.c -@@ -453,6 +453,11 @@ opensslecdsa_tofile(const dst_key_t *key, const char *directory) { - if (key->keydata.pkey == NULL) - return (DST_R_NULLKEY); - -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } -+ - pkey = key->keydata.pkey; - eckey = EVP_PKEY_get1_EC_KEY(pkey); - if (eckey == NULL) -@@ -514,8 +519,9 @@ static isc_result_t - opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - dst_private_t priv; - isc_result_t ret; -- EVP_PKEY *pkey; -- EC_KEY *eckey = NULL; -+ EVP_PKEY *pkey, *pubpkey; -+ EC_KEY *eckey = NULL, *pubeckey = NULL; -+ const EC_POINT *pubkey; - BIGNUM *privkey; - int group_nid; - isc_mem_t *mctx = key->mctx; -@@ -537,17 +543,36 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (ret != ISC_R_SUCCESS) - goto err; - -- privkey = BN_bin2bn(priv.elements[0].data, -- priv.elements[0].length, NULL); -- if (privkey == NULL) -- DST_RET(ISC_R_NOMEMORY); -- if (!EC_KEY_set_private_key(eckey, privkey)) -- DST_RET(ISC_R_NOMEMORY); -- if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS) -- DST_RET(DST_R_INVALIDPRIVATEKEY); -- dst__privstruct_free(&priv, mctx); -- memset(&priv, 0, sizeof(priv)); -- -+ if (key->external) { -+ /* -+ * Copy the public key to this new key. -+ */ -+ if (pub == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ pubpkey = pub->keydata.pkey; -+ pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey); -+ if (pubeckey == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ pubkey = EC_KEY_get0_public_key(pubeckey); -+ if (pubkey == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ if (EC_KEY_set_public_key(eckey, pubkey) != 1) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ if (EC_KEY_check_key(eckey) != 1) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ } else { -+ privkey = BN_bin2bn(priv.elements[0].data, -+ priv.elements[0].length, NULL); -+ if (privkey == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ if (!EC_KEY_set_private_key(eckey, privkey)) -+ DST_RET(ISC_R_NOMEMORY); -+ if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ } -+ - pkey = EVP_PKEY_new(); - if (pkey == NULL) - DST_RET (ISC_R_NOMEMORY); -@@ -561,6 +586,8 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - err: - if (eckey != NULL) - EC_KEY_free(eckey); -+ if (pubeckey != NULL) -+ EC_KEY_free(pubeckey); - dst__privstruct_free(&priv, mctx); - memset(&priv, 0, sizeof(priv)); - return (ret); -diff --git a/lib/dns/opensslgost_link.c b/lib/dns/opensslgost_link.c -index 1ce4405..325a7c0 100644 ---- a/lib/dns/opensslgost_link.c -+++ b/lib/dns/opensslgost_link.c -@@ -296,6 +296,11 @@ opensslgost_tofile(const dst_key_t *key, const char *directory) { - if (key->keydata.pkey == NULL) - return (DST_R_NULLKEY); - -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } -+ - pkey = key->keydata.pkey; - - len = i2d_PrivateKey(pkey, NULL); -@@ -337,13 +342,21 @@ opensslgost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (ret != ISC_R_SUCCESS) - return (ret); - -- INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1); -- p = priv.elements[0].data; -- if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, -- (long) priv.elements[0].length) == NULL) -- DST_RET(dst__openssl_toresult2("d2i_PrivateKey", -- DST_R_INVALIDPRIVATEKEY)); -- key->keydata.pkey = pkey; -+ if (key->external) { -+ INSIST(priv.nelements == 0); -+ if (pub == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ key->keydata.pkey = pub->keydata.pkey; -+ pub->keydata.pkey = NULL; -+ } else { -+ INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1); -+ p = priv.elements[0].data; -+ if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, -+ (long) priv.elements[0].length) == NULL) -+ DST_RET(dst__openssl_toresult2("d2i_PrivateKey", -+ DST_R_INVALIDPRIVATEKEY)); -+ key->keydata.pkey = pkey; -+ } - key->key_size = EVP_PKEY_bits(pkey); - dst__privstruct_free(&priv, mctx); - memset(&priv, 0, sizeof(priv)); -diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c -index fa7412c..894c7ae 100644 ---- a/lib/dns/opensslrsa_link.c -+++ b/lib/dns/opensslrsa_link.c -@@ -1048,8 +1048,14 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) { - return (DST_R_NULLKEY); - rsa = key->keydata.rsa; - #endif -- - memset(bufs, 0, sizeof(bufs)); -+ -+ if (key->external) { -+ priv.nelements = 0; -+ result = dst__privstruct_writefile(key, &priv, directory); -+ goto fail; -+ } -+ - for (i = 0; i < 8; i++) { - bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n)); - if (bufs[i] == NULL) { -@@ -1205,6 +1211,9 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (ret != ISC_R_SUCCESS) - goto err; - -+ if (key->external && priv.nelements != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ - for (i = 0; i < priv.nelements; i++) { - switch (priv.elements[i].tag) { - case TAG_RSA_ENGINE: -@@ -1217,6 +1226,7 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - break; - } - } -+ - /* - * Is this key is stored in a HSM? - * See if we can fetch it. -@@ -1328,8 +1338,10 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) - DST_RET(DST_R_INVALIDPRIVATEKEY); -- if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) -- DST_RET(ISC_R_RANGE); -+ if (!key->external) { -+ if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) -+ DST_RET(ISC_R_RANGE); -+ } - key->key_size = BN_num_bits(rsa->n); - if (pubrsa != NULL) - RSA_free(pubrsa); -diff --git a/lib/dns/zone.c b/lib/dns/zone.c -index daf495b..b82ad58 100644 ---- a/lib/dns/zone.c -+++ b/lib/dns/zone.c -@@ -5545,6 +5545,7 @@ find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, - const char *directory = dns_zone_getkeydirectory(zone); - - CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); -+ memset(keys, 0, sizeof(*keys) * maxkeys); - result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db), - directory, mctx, maxkeys, keys, - nkeys); -@@ -13132,6 +13133,7 @@ sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, - - static void - receive_secure_serial(isc_task_t *task, isc_event_t *event) { -+ static char me[] = "receive_secure_serial"; - isc_result_t result; - dns_journal_t *rjournal = NULL; - isc_uint32_t start, end; -@@ -13147,6 +13149,8 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { - end = ((struct secure_event *)event)->serial; - isc_event_free(&event); - -+ ENTER; -+ - LOCK_ZONE(zone); - - dns_diff_init(zone->mctx, &diff); --- -1.9.3 - diff --git a/SOURCES/bind-9.9-dist-native-pkcs11.patch b/SOURCES/bind-9.9-dist-native-pkcs11.patch deleted file mode 100644 index 36c0ea4..0000000 --- a/SOURCES/bind-9.9-dist-native-pkcs11.patch +++ /dev/null @@ -1,740 +0,0 @@ -diff --git a/bin/Makefile.in b/bin/Makefile.in -index 87ca5b2..187ec23 100644 ---- a/bin/Makefile.in -+++ b/bin/Makefile.in -@@ -19,7 +19,7 @@ srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ - --SUBDIRS = named rndc dig dnssec tools tests nsupdate \ -+SUBDIRS = named named-pkcs11 rndc dig dnssec dnssec-pkcs11 tools tests nsupdate \ - check confgen @PYTHON_TOOLS@ @PKCS11_TOOLS@ - TARGETS = - -diff --git a/bin/dnssec-pkcs11/Makefile.in b/bin/dnssec-pkcs11/Makefile.in -index 64e1846..7846662 100644 ---- a/bin/dnssec-pkcs11/Makefile.in -+++ b/bin/dnssec-pkcs11/Makefile.in -@@ -23,18 +23,18 @@ top_srcdir = @top_srcdir@ - - @BIND9_MAKE_INCLUDES@ - --CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} -+CINCLUDES = ${DNS_PKCS11_INCLUDES} ${ISC_PKCS11_INCLUDES} - - CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \ -- @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\" -+ @CRYPTO_PK11@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\" - CWARNINGS = - --DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ --ISCLIBS = ../../lib/isc/libisc.@A@ --ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ -+DNSLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ @DNS_CRYPTO_PK11_LIBS@ -+ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ -+ISCNOSYMLIBS = ../../lib/isc-pkcs11/libisc-pkcs11-nosymtbl.@A@ - --DNSDEPLIBS = ../../lib/dns/libdns.@A@ --ISCDEPLIBS = ../../lib/isc/libisc.@A@ -+DNSDEPLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ -+ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ - - DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} - -@@ -43,10 +43,10 @@ LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ - NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@ - - # Alphabetically --TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \ -- dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \ -- dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ \ -- dnssec-verify@EXEEXT@ dnssec-importkey@EXEEXT@ -+TARGETS = dnssec-keygen-pkcs11@EXEEXT@ dnssec-signzone-pkcs11@EXEEXT@ \ -+ dnssec-keyfromlabel-pkcs11@EXEEXT@ dnssec-dsfromkey-pkcs11@EXEEXT@ \ -+ dnssec-revoke-pkcs11@EXEEXT@ dnssec-settime-pkcs11@EXEEXT@ \ -+ dnssec-verify-pkcs11@EXEEXT@ dnssec-importkey-pkcs11@EXEEXT@ - - OBJS = dnssectool.@O@ - -@@ -67,15 +67,15 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} - - @BIND9_MAKE_RULES@ - --dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS} -+dnssec-dsfromkey-pkcs11@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS} - export BASEOBJS="dnssec-dsfromkey.@O@ ${OBJS}"; \ - ${FINALBUILDCMD} - --dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS} -+dnssec-keyfromlabel-pkcs11@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS} - export BASEOBJS="dnssec-keyfromlabel.@O@ ${OBJS}"; \ - ${FINALBUILDCMD} - --dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS} -+dnssec-keygen-pkcs11@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS} - export BASEOBJS="dnssec-keygen.@O@ ${OBJS}"; \ - ${FINALBUILDCMD} - -@@ -83,7 +83,7 @@ dnssec-signzone.@O@: dnssec-signzone.c - ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ - -c ${srcdir}/dnssec-signzone.c - --dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS} -+dnssec-signzone-pkcs11@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS} - export BASEOBJS="dnssec-signzone.@O@ ${OBJS}"; \ - ${FINALBUILDCMD} - -@@ -91,19 +91,19 @@ dnssec-verify.@O@: dnssec-verify.c - ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \ - -c ${srcdir}/dnssec-verify.c - --dnssec-verify@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS} -+dnssec-verify-pkcs11@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS} - export BASEOBJS="dnssec-verify.@O@ ${OBJS}"; \ - ${FINALBUILDCMD} - --dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS} -+dnssec-revoke-pkcs11@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-revoke.@O@ ${OBJS} ${LIBS} - --dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS} -+dnssec-settime-pkcs11@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-settime.@O@ ${OBJS} ${LIBS} - --dnssec-importkey@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS} -+dnssec-importkey-pkcs11@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - dnssec-importkey.@O@ ${OBJS} ${LIBS} - -@@ -114,11 +114,9 @@ docclean manclean maintainer-clean:: - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} -- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 - - install:: ${TARGETS} installdirs - for t in ${TARGETS}; do ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} $$t ${DESTDIR}${sbindir}; done -- for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done - - clean distclean:: - rm -f ${TARGETS} -diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in -index 64e1846..cfb5628 100644 ---- a/bin/dnssec/Makefile.in -+++ b/bin/dnssec/Makefile.in -@@ -25,7 +25,7 @@ top_srcdir = @top_srcdir@ - - CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} - --CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \ -+CDEFINES = -DVERSION=\"${VERSION}\" \ - @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\" - CWARNINGS = - -diff --git a/bin/named-pkcs11/Makefile.in b/bin/named-pkcs11/Makefile.in -index 8b9e87a..5b7d939 100644 ---- a/bin/named-pkcs11/Makefile.in -+++ b/bin/named-pkcs11/Makefile.in -@@ -45,26 +45,26 @@ DLZDRIVER_INCLUDES = @DLZ_DRIVER_INCLUDES@ - DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@ - - CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ -- ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \ -- ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ -+ ${LWRES_INCLUDES} ${DNS_PKCS11_INCLUDES} ${BIND9_INCLUDES} \ -+ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_PKCS11_INCLUDES} \ - ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ - --CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@ -+CDEFINES = @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO_PK11@ - - CWARNINGS = - --DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ -+DNSLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ @DNS_CRYPTO_LIBS@ - ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ - ISCCCLIBS = ../../lib/isccc/libisccc.@A@ --ISCLIBS = ../../lib/isc/libisc.@A@ -+ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ - ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ - LWRESLIBS = ../../lib/lwres/liblwres.@A@ - BIND9LIBS = ../../lib/bind9/libbind9.@A@ - --DNSDEPLIBS = ../../lib/dns/libdns.@A@ -+DNSDEPLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ - ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ - ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ --ISCDEPLIBS = ../../lib/isc/libisc.@A@ -+ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ - LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ - BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ - -@@ -73,15 +73,15 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \ - - LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ - ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \ -- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ -+ @LIBS@ - - NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \ - ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \ -- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@ -+ @LIBS@ - - SUBDIRS = unix - --TARGETS = named@EXEEXT@ lwresd@EXEEXT@ -+TARGETS = named-pkcs11@EXEEXT@ - - GEOIPLINKOBJS = geoip.@O@ - -@@ -92,8 +92,7 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ - tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ - zoneconf.@O@ \ - lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \ -- lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \ -- ${DLZDRIVER_OBJS} ${DBDRIVER_OBJS} -+ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ - - UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ - -@@ -108,8 +107,7 @@ SRCS = builtin.c client.c config.c control.c \ - tkeyconf.c tsigconf.c update.c xfrout.c \ - zoneconf.c \ - lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ -- lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \ -- ${DLZDRIVER_SRCS} ${DBDRIVER_SRCS} -+ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c - - MANPAGES = named.8 lwresd.8 named.conf.5 - -@@ -145,7 +143,7 @@ config.@O@: config.c bind.keys.h - -DNS_SYSCONFDIR=\"${sysconfdir}\" \ - -c ${srcdir}/config.c - --named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS} -+named-pkcs11@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS} - export MAKE_SYMTABLE="yes"; \ - export BASEOBJS="${OBJS} ${UOBJS}"; \ - ${FINALBUILDCMD} -@@ -176,15 +174,9 @@ statschannel.@O@: bind9.xsl.h bind9.ver3.xsl.h - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} -- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5 -- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 -- --install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir} -- (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@) -- ${INSTALL_DATA} ${srcdir}/named.8 ${DESTDIR}${mandir}/man8 -- ${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8 -- ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5 -+ -+install:: named-pkcs11@EXEEXT@ installdirs -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-pkcs11@EXEEXT@ ${DESTDIR}${sbindir} - - @DLZ_DRIVER_RULES@ - -diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in -index 8b9e87a..5ba3f56 100644 ---- a/bin/named/Makefile.in -+++ b/bin/named/Makefile.in -@@ -49,7 +49,7 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ - ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ - ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ - --CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@ -+CDEFINES = @CONTRIB_DLZ@ @CRYPTO@ - - CWARNINGS = - -diff --git a/bin/pkcs11/Makefile.in b/bin/pkcs11/Makefile.in -index 15d3fb5..32cc753 100644 ---- a/bin/pkcs11/Makefile.in -+++ b/bin/pkcs11/Makefile.in -@@ -20,13 +20,13 @@ top_srcdir = @top_srcdir@ - - @BIND9_MAKE_INCLUDES@ - --CINCLUDES = ${ISC_INCLUDES} -+CINCLUDES = ${ISC_PKCS11_INCLUDES} - - CDEFINES = - --ISCLIBS = ../../lib/isc/libisc.@A@ -+ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ - --ISCDEPLIBS = ../../lib/isc/libisc.@A@ -+ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ - - DEPLIBS = ${ISCDEPLIBS} - -diff --git a/configure.in b/configure.in -index 5c79d6d..6c08de9 100644 ---- a/configure.in -+++ b/configure.in -@@ -659,10 +659,10 @@ AC_ARG_WITH(pkcs11, - openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw" - if test "$use_openssl" = "auto" - then -- if test "$want_native_pkcs11" = "yes" -- then -- use_openssl="native_pkcs11" -- else -+# if test "$want_native_pkcs11" = "yes" -+# then -+# use_openssl="native_pkcs11" -+# else - for d in $openssldirs - do - if test -f $d/include/openssl/opensslv.h -@@ -671,7 +671,7 @@ then - break - fi - done -- fi -+# fi - fi - OPENSSL_ECDSA="" - OPENSSL_GOST="" -@@ -730,11 +730,11 @@ case "$use_openssl" in - If you don't want OpenSSL, use --without-openssl]) - ;; - *) -- if test "$want_native_pkcs11" = "yes" -- then -- AC_MSG_RESULT() -- AC_MSG_ERROR([OpenSSL and native PKCS11 cannot be used together.]) -- fi -+# if test "$want_native_pkcs11" = "yes" -+# then -+# AC_MSG_RESULT() -+# AC_MSG_ERROR([OpenSSL and native PKCS11 cannot be used together.]) -+# fi - if test "$use_openssl" = "yes" - then - # User did not specify a path - guess it -@@ -1014,6 +1014,7 @@ AC_SUBST(OPENSSL_ECDSA) - AC_SUBST(OPENSSL_GOST) - - DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS" -+DNS_CRYPTO_PK11_LIBS="$DNS_CRYPTO_LIBS" - - # - # Use OpenSSL for hash functions -@@ -1195,7 +1196,7 @@ case "$use_pkcs11" in - esac - AC_SUBST(PKCS11_PROVIDER) - -- -+CRYPTO_PK11="" - PKCS11_ECDSA="" - PKCS11_GOST="" - AC_MSG_CHECKING(for native PKCS11) -@@ -1203,7 +1204,7 @@ AC_MSG_CHECKING(for native PKCS11) - case "$want_native_pkcs11" in - yes) - AC_MSG_RESULT(using native PKCS11 crypto) -- CRYPTO="-DPKCS11CRYPTO" -+ CRYPTO_PK11="-DPKCS11CRYPTO" - PKCS11LINKOBJS='${PKCS11LINKOBJS}' - PKCS11LINKSRCS='${PKCS11LINKSRCS}' - PKCS11_TEST=pkcs11 -@@ -1240,6 +1241,7 @@ esac - AC_SUBST(PKCS11LINKOBJS) - AC_SUBST(PKCS11LINKSRCS) - AC_SUBST(CRYPTO) -+AC_SUBST(CRYPTO_PK11) - AC_SUBST(PKCS11_ECDSA) - AC_SUBST(PKCS11_GOST) - AC_SUBST(PKCS11_TEST) -@@ -1531,12 +1533,13 @@ AC_SUBST(USE_GSSAPI) - AC_SUBST(DST_GSSAPI_INC) - AC_SUBST(DNS_GSSAPI_LIBS) - DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS" -- -+DNS_CRYPTO_PK11_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_PK11_LIBS" - # - # Applications linking with libdns also need to link with these libraries. - # - - AC_SUBST(DNS_CRYPTO_LIBS) -+AC_SUBST(DNS_CRYPTO_PK11_LIBS) - - # - # was --with-randomdev specified? -@@ -4014,7 +4017,10 @@ AC_CONFIG_FILES([ - bin/confgen/unix/Makefile - bin/dig/Makefile - bin/dnssec/Makefile -+ bin/dnssec-pkcs11/Makefile - bin/named/Makefile -+ bin/named-pkcs11/Makefile -+ bin/named-pkcs11/unix/Makefile - bin/named/unix/Makefile - bin/nsupdate/Makefile - bin/pkcs11/Makefile -@@ -4097,11 +4103,19 @@ AC_CONFIG_FILES([ - lib/dns/include/dns/Makefile - lib/dns/include/dst/Makefile - lib/dns/tests/Makefile -+ lib/dns-pkcs11/Makefile -+ lib/dns-pkcs11/include/Makefile -+ lib/dns-pkcs11/include/dns/Makefile -+ lib/dns-pkcs11/include/dst/Makefile - lib/export/Makefile - lib/export/dns/Makefile - lib/export/dns/include/Makefile - lib/export/dns/include/dns/Makefile - lib/export/dns/include/dst/Makefile -+ lib/export/dns-pkcs11/Makefile -+ lib/export/dns-pkcs11/include/Makefile -+ lib/export/dns-pkcs11/include/dns/Makefile -+ lib/export/dns-pkcs11/include/dst/Makefile - lib/export/irs/Makefile - lib/export/irs/include/Makefile - lib/export/irs/include/irs/Makefile -@@ -4115,6 +4129,16 @@ AC_CONFIG_FILES([ - lib/export/isc/unix/Makefile - lib/export/isc/unix/include/Makefile - lib/export/isc/unix/include/isc/Makefile -+ lib/export/isc-pkcs11/$thread_dir/Makefile -+ lib/export/isc-pkcs11/$thread_dir/include/Makefile -+ lib/export/isc-pkcs11/$thread_dir/include/isc/Makefile -+ lib/export/isc-pkcs11/Makefile -+ lib/export/isc-pkcs11/include/Makefile -+ lib/export/isc-pkcs11/include/isc/Makefile -+ lib/export/isc-pkcs11/nls/Makefile -+ lib/export/isc-pkcs11/unix/Makefile -+ lib/export/isc-pkcs11/unix/include/Makefile -+ lib/export/isc-pkcs11/unix/include/isc/Makefile - lib/export/isccfg/Makefile - lib/export/isccfg/include/Makefile - lib/export/isccfg/include/isccfg/Makefile -@@ -4143,6 +4167,24 @@ AC_CONFIG_FILES([ - lib/isc/unix/include/Makefile - lib/isc/unix/include/isc/Makefile - lib/isc/unix/include/pkcs11/Makefile -+ lib/isc-pkcs11/$arch/Makefile -+ lib/isc-pkcs11/$arch/include/Makefile -+ lib/isc-pkcs11/$arch/include/isc/Makefile -+ lib/isc-pkcs11/$thread_dir/Makefile -+ lib/isc-pkcs11/$thread_dir/include/Makefile -+ lib/isc-pkcs11/$thread_dir/include/isc/Makefile -+ lib/isc-pkcs11/Makefile -+ lib/isc-pkcs11/include/Makefile -+ lib/isc-pkcs11/include/isc/Makefile -+ lib/isc-pkcs11/include/isc/platform.h -+ lib/isc-pkcs11/include/pk11/Makefile -+ lib/isc-pkcs11/include/pkcs11/Makefile -+ lib/isc-pkcs11/tests/Makefile -+ lib/isc-pkcs11/nls/Makefile -+ lib/isc-pkcs11/unix/Makefile -+ lib/isc-pkcs11/unix/include/Makefile -+ lib/isc-pkcs11/unix/include/isc/Makefile -+ lib/isc-pkcs11/unix/include/pkcs11/Makefile - lib/isccc/Makefile - lib/isccc/include/Makefile - lib/isccc/include/isccc/Makefile -diff --git a/lib/Makefile.in b/lib/Makefile.in -index 8dc1d38..8e48d5e 100644 ---- a/lib/Makefile.in -+++ b/lib/Makefile.in -@@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@ - # Attempt to disable parallel processing. - .NOTPARALLEL: - .NO_PARALLEL: --SUBDIRS = isc isccc dns isccfg bind9 lwres tests -+SUBDIRS = isc isccc dns isccfg bind9 lwres tests isc-pkcs11 dns-pkcs11 - TARGETS = - - @BIND9_MAKE_RULES@ -diff --git a/lib/dns-pkcs11/Makefile.in b/lib/dns-pkcs11/Makefile.in -index ae316c5..1a79768 100644 ---- a/lib/dns-pkcs11/Makefile.in -+++ b/lib/dns-pkcs11/Makefile.in -@@ -27,16 +27,16 @@ top_srcdir = @top_srcdir@ - - USE_ISC_SPNEGO = @USE_ISC_SPNEGO@ - --CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} \ -+CINCLUDES = -I. -I${top_srcdir}/lib/dns-pkcs11 -Iinclude ${DNS_PKCS11_INCLUDES} ${ISC_PKCS11_INCLUDES} \ - @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ - --CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@ ${USE_ISC_SPNEGO} -+CDEFINES = -DUSE_MD5 @CRYPTO_PK11@ @USE_GSSAPI@ ${USE_ISC_SPNEGO} - - CWARNINGS = - --ISCLIBS = ../../lib/isc/libisc.@A@ -+ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ - --ISCDEPLIBS = ../../lib/isc/libisc.@A@ -+ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@ - - LIBS = @LIBS@ - -@@ -131,24 +131,24 @@ version.@O@: version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - --libdns.@SA@: ${OBJS} -+libdns-pkcs11.@SA@: ${OBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} - ${RANLIB} $@ - --libdns.la: ${OBJS} -+libdns-pkcs11.la: ${OBJS} - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns.la -rpath ${libdir} \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-pkcs11.la -rpath ${libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} - --timestamp: libdns.@A@ -+timestamp: libdns-pkcs11.@A@ - touch timestamp - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns.@A@ ${DESTDIR}${libdir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns-pkcs11.@A@ ${DESTDIR}${libdir} - - clean distclean:: - rm -f libdns.@A@ timestamp -@@ -181,7 +181,7 @@ code.h: gen - ./gen -s ${srcdir} > code.h - - gen: gen.c -- ${BUILD_CC} ${BUILD_CFLAGS} -I${top_srcdir}/lib/isc/include \ -+ ${BUILD_CC} ${BUILD_CFLAGS} -I${top_srcdir}/lib/isc-pkcs11/include \ - ${BUILD_CPPFLAGS} ${BUILD_LDFLAGS} -o $@ ${srcdir}/gen.c ${BUILD_LIBS} - - rbtdb64.@O@: rbtdb.c -diff --git a/lib/export/Makefile.in b/lib/export/Makefile.in -index 1fd7216..a8a1342 100644 ---- a/lib/export/Makefile.in -+++ b/lib/export/Makefile.in -@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@ - # Attempt to disable parallel processing. - .NOTPARALLEL: - .NO_PARALLEL: --SUBDIRS = isc dns isccfg irs samples -+SUBDIRS = isc dns isccfg irs samples isc-pkcs11 dns-pkcs11 - TARGETS = - - @BIND9_MAKE_RULES@ -diff --git a/lib/export/dns-pkcs11/Makefile.in b/lib/export/dns-pkcs11/Makefile.in -index 887acb9..0f8abd3 100644 ---- a/lib/export/dns-pkcs11/Makefile.in -+++ b/lib/export/dns-pkcs11/Makefile.in -@@ -15,7 +15,7 @@ - # $Id$ - - top_srcdir = @top_srcdir@ --srcdir = @top_srcdir@/lib/dns -+srcdir = @top_srcdir@/lib/dns-pkcs11 - export_srcdir = @top_srcdir@/lib/export - - # Attempt to disable parallel processing. -@@ -28,16 +28,16 @@ export_srcdir = @top_srcdir@/lib/export - - @BIND9_MAKE_INCLUDES@ - --CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} -I${export_srcdir}/isc/include \ -- ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ -+CINCLUDES = -I. -I${top_srcdir}/lib/dns-pkcs11 -Iinclude ${DNS_PKCS11_INCLUDES} -I${export_srcdir}/isc-pkcs11/include \ -+ ${ISC_PKCS11_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ - --CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@ -+CDEFINES = -DUSE_MD5 @CRYPTO_PK11@ @USE_GSSAPI@ - - CWARNINGS = - --ISCLIBS = ../isc/libisc-export.@A@ -+ISCLIBS = ../isc-pkcs11/libisc-pkcs11-export.@A@ - --ISCDEPLIBS = ../isc/libisc-export.@A@ -+ISCDEPLIBS = ../isc-pkcs11/libisc-pkcs11-export.@A@ - - LIBS = @LIBS@ - -@@ -118,29 +118,29 @@ version.@O@: ${srcdir}/version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - --libdns-export.@SA@: ${OBJS} -+libdns-pkcs11-export.@SA@: ${OBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} - ${RANLIB} $@ - --libdns-export.la: ${OBJS} -+libdns-pkcs11-export.la: ${OBJS} - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-export.la \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-pkcs11-export.la \ - -rpath ${export_libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ -- ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} -+ ${OBJS} ${ISCLIBS} @DNS_CRYPTO_PK11_LIBS@ ${LIBS} - --timestamp: libdns-export.@A@ -+timestamp: libdns-pkcs11-export.@A@ - touch timestamp - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns-export.@A@ \ -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns-pkcs11-export.@A@ \ - ${DESTDIR}${export_libdir}/ - - clean distclean:: -- rm -f libdns-export.@A@ timestamp -+ rm -f libdns-pkcs11-export.@A@ timestamp - rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h - rm -f include/dns/rdatastruct.h - -diff --git a/lib/export/isc-pkcs11/Makefile.in b/lib/export/isc-pkcs11/Makefile.in -index 4f4a9f7..f8224e7 100644 ---- a/lib/export/isc-pkcs11/Makefile.in -+++ b/lib/export/isc-pkcs11/Makefile.in -@@ -15,7 +15,7 @@ - # $Id: Makefile.in,v 1.8 2010/06/09 23:50:58 tbox Exp $ - - top_srcdir = @top_srcdir@ --srcdir = @top_srcdir@/lib/isc -+srcdir = @top_srcdir@/lib/isc-pkcs11 - export_srcdir = @top_srcdir@/lib/export - - @BIND9_VERSION@ -@@ -25,9 +25,9 @@ export_srcdir = @top_srcdir@/lib/export - CINCLUDES = -I${srcdir}/unix/include \ - -I${srcdir}/@ISC_THREAD_DIR@/include \ - -I${srcdir}/@ISC_ARCH_DIR@/include \ -- -I${export_srcdir}/isc/include -I${srcdir}/include \ -+ -I${export_srcdir}/isc-pkcs11/include -I${srcdir}/include \ - @ISC_OPENSSL_INC@ --CDEFINES = @CRYPTO@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \ -+CDEFINES = @CRYPTO_PK11@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \ - -DUSE_SOCKETIMPREGISTER -DUSE_TASKIMPREGISTER \ - -DUSE_TIMERIMPREGISTER - CWARNINGS = -@@ -119,26 +119,26 @@ version.@O@: ${srcdir}/version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - --libisc-export.@SA@: ${OBJS} -+libisc-pkcs11-export.@SA@: ${OBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} - ${RANLIB} $@ - --libisc-export.la: ${OBJS} -+libisc-pkcs11-export.la: ${OBJS} - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-export.la \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-pkcs11-export.la \ - -rpath ${export_libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${LIBS} - --timestamp: libisc-export.@A@ -+timestamp: libisc-pkcs11-export.@A@ - touch timestamp - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisc-export.@A@ \ -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisc-pkcs11-export.@A@ \ - ${DESTDIR}${export_libdir} - - clean distclean:: -- rm -f libisc-export.@A@ libisc-export.la timestamp -+ rm -f libisc-pkcs11-export.@A@ libisc-pkcs11-export.la timestamp -diff --git a/lib/isc-pkcs11/Makefile.in b/lib/isc-pkcs11/Makefile.in -index df62ec9..d9f0107 100644 ---- a/lib/isc-pkcs11/Makefile.in -+++ b/lib/isc-pkcs11/Makefile.in -@@ -31,8 +31,8 @@ CINCLUDES = -I${srcdir}/unix/include \ - -I${srcdir}/@ISC_THREAD_DIR@/include \ - -I${srcdir}/@ISC_ARCH_DIR@/include \ - -I./include \ -- -I${srcdir}/include @ISC_OPENSSL_INC@ ${DNS_INCLUDES} --CDEFINES = @CRYPTO@ -DPK11_LIB_LOCATION=\"${PROVIDER}\" -+ -I${srcdir}/include ${DNS_PKCS11_INCLUDES} -+CDEFINES = @CRYPTO_PK11@ -DPK11_LIB_LOCATION=\"${PROVIDER}\" - CWARNINGS = - - # Alphabetically -@@ -110,35 +110,35 @@ version.@O@: version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - --libisc.@SA@: ${OBJS} ${SYMTBLOBJS} -+libisc-pkcs11.@SA@: ${OBJS} ${SYMTBLOBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} ${SYMTBLOBJS} - ${RANLIB} $@ - --libisc-nosymtbl.@SA@: ${OBJS} -+libisc-pkcs11-nosymtbl.@SA@: ${OBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} - ${RANLIB} $@ - --libisc.la: ${OBJS} ${SYMTBLOBJS} -+libisc-pkcs11.la: ${OBJS} ${SYMTBLOBJS} - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la -rpath ${libdir} \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-pkcs11.la -rpath ${libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${SYMTBLOBJS} ${LIBS} - --libisc-nosymtbl.la: ${OBJS} -+libisc-pkcs11-nosymtbl.la: ${OBJS} - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-nosymtbl.la -rpath ${libdir} \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-pkcs11-nosymtbl.la -rpath ${libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${LIBS} - --timestamp: libisc.@A@ libisc-nosymtbl.@A@ -+timestamp: libisc-pkcs11.@A@ libisc-pkcs11-nosymtbl.@A@ - touch timestamp - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisc.@A@ ${DESTDIR}${libdir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisc-pkcs11.@A@ ${DESTDIR}${libdir} - - clean distclean:: -- rm -f libisc.@A@ libisc-nosymtbl.@A@ libisc.la \ -- libisc-nosymtbl.la timestamp -+ rm -f libisc-pkcs11.@A@ libisc-pkcs11-nosymtbl.@A@ libisc-pkcs11.la \ -+ libisc-pkcs11-nosymtbl.la timestamp -diff --git a/make/includes.in b/make/includes.in -index f2f1b3f..639477c 100644 ---- a/make/includes.in -+++ b/make/includes.in -@@ -46,3 +46,13 @@ BIND9_INCLUDES = @BIND9_BIND9_BUILDINCLUDE@ \ - - TEST_INCLUDES = \ - -I${top_srcdir}/lib/tests/include -+ -+ISC_PKCS11_INCLUDES = @BIND9_ISC_BUILDINCLUDE@ \ -+ -I${top_srcdir}/lib/isc-pkcs11 \ -+ -I${top_srcdir}/lib/isc-pkcs11/include \ -+ -I${top_srcdir}/lib/isc-pkcs11/unix/include \ -+ -I${top_srcdir}/lib/isc-pkcs11/@ISC_THREAD_DIR@/include \ -+ -I${top_srcdir}/lib/isc-pkcs11/@ISC_ARCH_DIR@/include -+ -+DNS_PKCS11_INCLUDES = @BIND9_DNS_BUILDINCLUDE@ \ -+ -I${top_srcdir}/lib/dns-pkcs11/include diff --git a/SOURCES/bind-9.9-native-pkcs11.patch b/SOURCES/bind-9.9-native-pkcs11.patch deleted file mode 100644 index c8024b3..0000000 --- a/SOURCES/bind-9.9-native-pkcs11.patch +++ /dev/null @@ -1,25320 +0,0 @@ -From e9ef042fc45d2004c99dd7642d5032fd5832b270 Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Thu, 21 May 2015 10:52:03 +0200 -Subject: [PATCH] native PKCS#11 - -Signed-off-by: Tomas Hozza ---- - acconfig.h | 7 +- - bin/check/Makefile.in | 3 +- - bin/dig/Makefile.in | 13 +- - bin/dig/dighost.c | 11 +- - bin/dnssec/Makefile.in | 3 +- - bin/dnssec/dnssec-dsfromkey.c | 9 +- - bin/dnssec/dnssec-importkey.c | 93 +- - bin/dnssec/dnssec-importkey.docbook | 58 +- - bin/dnssec/dnssec-keyfromlabel.c | 31 +- - bin/dnssec/dnssec-keyfromlabel.docbook | 43 +- - bin/dnssec/dnssec-keygen.c | 21 +- - bin/dnssec/dnssec-keygen.docbook | 13 +- - bin/dnssec/dnssec-revoke.c | 14 +- - bin/dnssec/dnssec-revoke.docbook | 11 +- - bin/dnssec/dnssec-settime.c | 14 +- - bin/dnssec/dnssec-settime.docbook | 11 +- - bin/dnssec/dnssec-signzone.c | 14 +- - bin/dnssec/dnssec-signzone.docbook | 15 +- - bin/dnssec/dnssec-verify.c | 14 +- - bin/dnssec/dnssec-verify.docbook | 17 + - bin/dnssec/dnssectool.c | 2 +- - bin/named/Makefile.in | 2 +- - bin/named/include/named/globals.h | 4 +- - bin/named/main.c | 6 + - bin/named/named.docbook | 16 +- - bin/named/server.c | 9 +- - bin/nsupdate/Makefile.in | 6 +- - bin/pkcs11/Makefile.in | 67 +- - bin/pkcs11/pkcs11-destroy.8 | 10 +- - bin/pkcs11/pkcs11-destroy.c | 153 +- - bin/pkcs11/pkcs11-destroy.docbook | 19 +- - bin/pkcs11/pkcs11-destroy.html | 22 +- - bin/pkcs11/pkcs11-keygen.8 | 69 +- - bin/pkcs11/pkcs11-keygen.c | 687 +++++++-- - bin/pkcs11/pkcs11-keygen.docbook | 115 +- - bin/pkcs11/pkcs11-keygen.html | 90 +- - bin/pkcs11/pkcs11-list.c | 118 +- - bin/pkcs11/pkcs11-tokens.8 | 51 + - bin/pkcs11/pkcs11-tokens.c | 106 ++ - bin/pkcs11/pkcs11-tokens.docbook | 86 ++ - bin/pkcs11/pkcs11-tokens.html | 58 + - bin/rndc/Makefile.in | 3 +- - bin/tests/Makefile.in | 76 +- - bin/tests/dst/dst_test.c | 7 +- - bin/tests/dst/t_dst.c | 14 +- - bin/tests/pkcs11/Makefile.in | 49 + - bin/tests/pkcs11/benchmarks/Makefile.in | 79 + - bin/tests/pkcs11/benchmarks/create.c | 260 ++++ - bin/tests/pkcs11/benchmarks/find.c | 227 +++ - bin/tests/pkcs11/benchmarks/genrsa.c | 295 ++++ - bin/tests/pkcs11/benchmarks/login.c | 249 ++++ - bin/tests/pkcs11/benchmarks/privrsa.c | 360 +++++ - bin/tests/pkcs11/benchmarks/pubrsa.c | 281 ++++ - bin/tests/pkcs11/benchmarks/random.c | 192 +++ - bin/tests/pkcs11/benchmarks/session.c | 213 +++ - bin/tests/pkcs11/benchmarks/sha1.c | 214 +++ - bin/tests/pkcs11/benchmarks/sign.c | 368 +++++ - bin/tests/pkcs11/benchmarks/verify.c | 292 ++++ - bin/tests/pkcs11/pkcs11-hmacmd5.c | 332 +++++ - bin/tests/pkcs11/pkcs11-md5sum.c | 235 +++ - bin/tests/system/autosign/prereq.sh | 3 +- - bin/tests/system/cleanpkcs11.sh | 6 +- - bin/tests/system/conf.sh.in | 8 +- - bin/tests/system/dnssec/prereq.sh | 3 +- - bin/tests/system/ecdsa/prereq.sh.in | 15 +- - bin/tests/system/gost/prereq.sh.in | 15 +- - bin/tests/system/inline/clean.sh | 2 +- - bin/tests/system/metadata/prereq.sh | 3 +- - bin/tests/system/pending/prereq.sh | 23 +- - bin/tests/system/pkcs11/clean.sh | 5 +- - bin/tests/system/pkcs11/ns1/named.conf | 10 +- - bin/tests/system/pkcs11/setup.sh | 64 +- - bin/tests/system/pkcs11/tests.sh | 72 +- - bin/tests/system/pkcs11ssl/clean.sh | 20 + - bin/tests/system/pkcs11ssl/ns1/example.db.in | 29 + - bin/tests/system/pkcs11ssl/ns1/named.conf | 52 + - bin/tests/system/pkcs11ssl/prereq.sh | 34 + - bin/tests/system/pkcs11ssl/setup.sh | 46 + - bin/tests/system/pkcs11ssl/tests.sh | 71 + - bin/tests/system/pkcs11ssl/usepkcs11 | 1 + - bin/tests/system/rsabigexponent/Makefile.in | 2 +- - bin/tests/system/rsabigexponent/bigkey.c | 18 +- - bin/tests/system/rsabigexponent/prereq.sh | 3 +- - bin/tests/system/smartsign/prereq.sh | 3 +- - bin/tests/system/tkey/keycreate.c | 1 + - bin/tests/system/tkey/prereq.sh | 3 +- - config.h.in | 19 +- - configure.in | 383 ++++- - doc/arm/pkcs11.xml | 694 +++++---- - lib/dns/Makefile.in | 16 +- - lib/dns/dnssec.c | 12 +- - lib/dns/ds.c | 44 +- - lib/dns/dst_api.c | 73 +- - lib/dns/dst_gost.h | 57 + - lib/dns/dst_internal.h | 28 +- - lib/dns/dst_parse.c | 36 +- - lib/dns/dst_parse.h | 6 +- - lib/dns/dst_pkcs11.h | 43 + - lib/dns/dst_result.c | 3 +- - lib/dns/gssapi_link.c | 1 + - lib/dns/hmac_link.c | 47 +- - lib/dns/include/dst/dst.h | 10 + - lib/dns/include/dst/result.h | 3 +- - lib/dns/openssldh_link.c | 7 + - lib/dns/openssldsa_link.c | 36 +- - lib/dns/opensslecdsa_link.c | 73 +- - lib/dns/opensslgost_link.c | 180 ++- - lib/dns/opensslrsa_link.c | 35 +- - lib/dns/pkcs11.c | 50 + - lib/dns/pkcs11dh_link.c | 1140 +++++++++++++++ - lib/dns/pkcs11dsa_link.c | 1130 +++++++++++++++ - lib/dns/pkcs11ecdsa_link.c | 1189 ++++++++++++++++ - lib/dns/pkcs11gost_link.c | 949 +++++++++++++ - lib/dns/pkcs11rsa_link.c | 1583 +++++++++++++++++++++ - lib/dns/rdata/generic/dlv_32769.c | 9 + - lib/dns/rdata/generic/ds_43.c | 10 + - lib/dns/tests/Makefile.in | 14 +- - lib/dns/tests/gost_test.c | 232 +++ - lib/dns/tkey.c | 10 +- - lib/dns/tsig.c | 14 +- - lib/export/dns/Makefile.in | 4 +- - lib/export/isc/Makefile.in | 5 +- - lib/export/isc/unix/Makefile.in | 4 + - lib/isc/Makefile.in | 14 +- - lib/isc/entropy.c | 8 + - lib/isc/hmacmd5.c | 166 +++ - lib/isc/hmacsha.c | 375 +++++ - lib/isc/include/Makefile.in | 2 +- - lib/isc/include/isc/hmacmd5.h | 5 + - lib/isc/include/isc/hmacsha.h | 9 + - lib/isc/include/isc/md5.h | 5 + - lib/isc/include/isc/resultclass.h | 2 +- - lib/isc/include/isc/sha1.h | 5 + - lib/isc/include/isc/sha2.h | 6 + - lib/isc/include/pk11/Makefile.in | 38 + - lib/isc/include/pk11/constants.h | 107 ++ - lib/isc/include/pk11/internal.h | 46 + - lib/isc/include/pk11/pk11.h | 295 ++++ - lib/isc/include/pk11/result.h | 56 + - lib/isc/include/pkcs11/Makefile.in | 40 + - lib/isc/include/pkcs11/pkcs11.h | 299 ++++ - lib/isc/include/pkcs11/pkcs11f.h | 912 ++++++++++++ - lib/isc/include/pkcs11/pkcs11t.h | 1977 ++++++++++++++++++++++++++ - lib/isc/md5.c | 50 + - lib/isc/pk11.c | 1327 +++++++++++++++++ - lib/isc/pk11_result.c | 85 ++ - lib/isc/sha1.c | 50 +- - lib/isc/sha2.c | 279 ++++ - lib/isc/unix/Makefile.in | 4 +- - lib/isc/unix/include/Makefile.in | 2 +- - lib/isc/unix/include/pkcs11/Makefile.in | 33 + - lib/isc/unix/include/pkcs11/cryptoki.h | 66 + - lib/isc/unix/pk11_api.c | 673 +++++++++ - 153 files changed, 20271 insertions(+), 1183 deletions(-) - create mode 100644 bin/pkcs11/pkcs11-tokens.8 - create mode 100644 bin/pkcs11/pkcs11-tokens.c - create mode 100644 bin/pkcs11/pkcs11-tokens.docbook - create mode 100644 bin/pkcs11/pkcs11-tokens.html - create mode 100644 bin/tests/pkcs11/Makefile.in - create mode 100644 bin/tests/pkcs11/benchmarks/Makefile.in - create mode 100644 bin/tests/pkcs11/benchmarks/create.c - create mode 100644 bin/tests/pkcs11/benchmarks/find.c - create mode 100644 bin/tests/pkcs11/benchmarks/genrsa.c - create mode 100644 bin/tests/pkcs11/benchmarks/login.c - create mode 100644 bin/tests/pkcs11/benchmarks/privrsa.c - create mode 100644 bin/tests/pkcs11/benchmarks/pubrsa.c - create mode 100644 bin/tests/pkcs11/benchmarks/random.c - create mode 100644 bin/tests/pkcs11/benchmarks/session.c - create mode 100644 bin/tests/pkcs11/benchmarks/sha1.c - create mode 100644 bin/tests/pkcs11/benchmarks/sign.c - create mode 100644 bin/tests/pkcs11/benchmarks/verify.c - create mode 100644 bin/tests/pkcs11/pkcs11-hmacmd5.c - create mode 100644 bin/tests/pkcs11/pkcs11-md5sum.c - create mode 100644 bin/tests/system/pkcs11ssl/clean.sh - create mode 100644 bin/tests/system/pkcs11ssl/ns1/example.db.in - create mode 100644 bin/tests/system/pkcs11ssl/ns1/named.conf - create mode 100644 bin/tests/system/pkcs11ssl/prereq.sh - create mode 100644 bin/tests/system/pkcs11ssl/setup.sh - create mode 100644 bin/tests/system/pkcs11ssl/tests.sh - create mode 100644 bin/tests/system/pkcs11ssl/usepkcs11 - create mode 100644 lib/dns/dst_gost.h - create mode 100644 lib/dns/dst_pkcs11.h - create mode 100644 lib/dns/pkcs11.c - create mode 100644 lib/dns/pkcs11dh_link.c - create mode 100644 lib/dns/pkcs11dsa_link.c - create mode 100644 lib/dns/pkcs11ecdsa_link.c - create mode 100644 lib/dns/pkcs11gost_link.c - create mode 100644 lib/dns/pkcs11rsa_link.c - create mode 100644 lib/dns/tests/gost_test.c - create mode 100644 lib/isc/include/pk11/Makefile.in - create mode 100644 lib/isc/include/pk11/constants.h - create mode 100644 lib/isc/include/pk11/internal.h - create mode 100644 lib/isc/include/pk11/pk11.h - create mode 100644 lib/isc/include/pk11/result.h - create mode 100644 lib/isc/include/pkcs11/Makefile.in - create mode 100644 lib/isc/include/pkcs11/pkcs11.h - create mode 100644 lib/isc/include/pkcs11/pkcs11f.h - create mode 100644 lib/isc/include/pkcs11/pkcs11t.h - create mode 100644 lib/isc/pk11.c - create mode 100644 lib/isc/pk11_result.c - create mode 100644 lib/isc/unix/include/pkcs11/Makefile.in - create mode 100644 lib/isc/unix/include/pkcs11/cryptoki.h - create mode 100644 lib/isc/unix/pk11_api.c - -diff --git a/acconfig.h b/acconfig.h -index 3d412d9..c8e832a 100644 ---- a/acconfig.h -+++ b/acconfig.h -@@ -132,14 +132,11 @@ int sigwait(const unsigned int *set, int *sig); - /** define if you have strerror in the C library. */ - #undef HAVE_STRERROR - --/** Define if you are running under Compaq TruCluster. */ --#undef HAVE_TRUCLUSTER -- - /* Define if OpenSSL includes DSA support */ - #undef HAVE_OPENSSL_DSA - --/* Define if OpenSSL includes ECDSA support */ --#undef HAVE_OPENSSL_ECDSA -+/* Define if you have getpassphrase in the C library. */ -+#undef HAVE_GETPASSPHRASE - - /* Define to the length type used by the socket API (socklen_t, size_t, int). */ - #undef ISC_SOCKADDR_LEN_T -diff --git a/bin/check/Makefile.in b/bin/check/Makefile.in -index c191605..d585480 100644 ---- a/bin/check/Makefile.in -+++ b/bin/check/Makefile.in -@@ -75,7 +75,8 @@ named-checkconf@EXEEXT@: named-checkconf.@O@ check-tool.@O@ ${ISCDEPLIBS} \ - export LIBS0="${BIND9LIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \ - ${FINALBUILDCMD} - --named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} -+named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ \ -+ ${ISCDEPLIBS} ${DNSDEPLIBS} - export BASEOBJS="named-checkzone.@O@ check-tool.@O@"; \ - export LIBS0="${ISCCFGLIBS} ${DNSLIBS}"; \ - ${FINALBUILDCMD} -diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in -index 3864e06..43dd061 100644 ---- a/bin/dig/Makefile.in -+++ b/bin/dig/Makefile.in -@@ -28,7 +28,7 @@ READLINE_LIB = @READLINE_LIB@ - CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${BIND9_INCLUDES} \ - ${ISC_INCLUDES} ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} - --CDEFINES = -DVERSION=\"${VERSION}\" -+CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@ - CWARNINGS = - - ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ -@@ -44,13 +44,13 @@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ - ISCDEPLIBS = ../../lib/isc/libisc.@A@ - LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ - --DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} \ -- ${LWRESDEPLIBS} -+DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} \ -+ ${ISCCFGDEPLIBS} ${LWRESDEPLIBS} - --LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ -+LIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ - ${ISCLIBS} @IDNLIBS@ @LIBS@ -lidn - --NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ -+NOSYMLIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ - ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ -lidn - - SUBDIRS = -@@ -75,14 +75,17 @@ EXT_CFLAGS = -DWITH_LIBIDN - - dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - export BASEOBJS="dig.@O@ dighost.@O@ ${UOBJS}"; \ -+ export LIBS0="${DNSLIBS}"; \ - ${FINALBUILDCMD} - - host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - export BASEOBJS="host.@O@ dighost.@O@ ${UOBJS}"; \ -+ export LIBS0="${DNSLIBS}"; \ - ${FINALBUILDCMD} - - nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} - export BASEOBJS="nslookup.@O@ dighost.@O@ ${READLINE_LIB} ${UOBJS}"; \ -+ export LIBS0="${DNSLIBS}"; \ - ${FINALBUILDCMD} - - doc man:: ${MANOBJS} -diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c -index e2bb110..5c03d95 100644 ---- a/bin/dig/dighost.c -+++ b/bin/dig/dighost.c -@@ -105,6 +105,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #if ! defined(NS_INADDRSZ) - #define NS_INADDRSZ 4 - #endif -@@ -1347,6 +1351,11 @@ setup_libs(void) { - - debug("setup_libs()"); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif -+ dns_result_register(); -+ - result = isc_net_probeipv4(); - if (result == ISC_R_SUCCESS) - have_ipv4 = ISC_TRUE; -@@ -1403,8 +1412,6 @@ setup_libs(void) { - - result = isc_mutex_init(&lookup_lock); - check_result(result, "isc_mutex_init"); -- -- dns_result_register(); - } - - /*% -diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in -index ecb0fae..64e1846 100644 ---- a/bin/dnssec/Makefile.in -+++ b/bin/dnssec/Makefile.in -@@ -25,7 +25,8 @@ top_srcdir = @top_srcdir@ - - CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} - --CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ -+CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \ -+ @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\" - CWARNINGS = - - DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ -diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c -index bfedae8..df616ac 100644 ---- a/bin/dnssec/dnssec-dsfromkey.c -+++ b/bin/dnssec/dnssec-dsfromkey.c -@@ -49,6 +49,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #include "dnssectool.h" - - #ifndef PATH_MAX -@@ -370,6 +374,9 @@ main(int argc, char **argv) { - if (result != ISC_R_SUCCESS) - fatal("out of memory"); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - dns_result_register(); - - isc_commandline_errprint = ISC_FALSE; -@@ -448,7 +455,7 @@ main(int argc, char **argv) { - else if (strcasecmp(algname, "SHA256") == 0 || - strcasecmp(algname, "SHA-256") == 0) - dtype = DNS_DSDIGEST_SHA256; --#ifdef HAVE_OPENSSL_GOST -+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) - else if (strcasecmp(algname, "GOST") == 0) - dtype = DNS_DSDIGEST_GOST; - #endif -diff --git a/bin/dnssec/dnssec-importkey.c b/bin/dnssec/dnssec-importkey.c -index 00f9200..73166c4 100644 ---- a/bin/dnssec/dnssec-importkey.c -+++ b/bin/dnssec/dnssec-importkey.c -@@ -47,6 +47,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #include "dnssectool.h" - - #ifndef PATH_MAX -@@ -61,7 +65,9 @@ static dns_fixedname_t fixed; - static dns_name_t *name = NULL; - static isc_mem_t *mctx = NULL; - static isc_boolean_t setpub = ISC_FALSE, setdel = ISC_FALSE; -+static isc_boolean_t setttl = ISC_FALSE; - static isc_stdtime_t pub = 0, del = 0; -+static dns_ttl_t ttl = 0; - - static isc_result_t - initname(char *setname) { -@@ -190,9 +196,10 @@ static void - emit(const char *dir, dns_rdata_t *rdata) { - isc_result_t result; - char keystr[DST_KEY_FORMATSIZE]; -- char newname[1024]; -+ char pubname[1024]; -+ char priname[1024]; - isc_buffer_t buf; -- dst_key_t *key = NULL; -+ dst_key_t *key = NULL, *tmp = NULL; - - isc_buffer_init(&buf, rdata->data, rdata->length); - isc_buffer_add(&buf, rdata->length); -@@ -201,18 +208,36 @@ emit(const char *dir, dns_rdata_t *rdata) { - fatal("dst_key_fromdns: %s", isc_result_totext(result)); - } - -- dst_key_setexternal(key, ISC_TRUE); -- if (setpub) -- dst_key_settime(key, DST_TIME_PUBLISH, pub); -- if (setdel) -- dst_key_settime(key, DST_TIME_DELETE, del); -- -- isc_buffer_init(&buf, newname, sizeof(newname)); -+ isc_buffer_init(&buf, pubname, sizeof(pubname)); - result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf); - if (result != ISC_R_SUCCESS) { - fatal("Failed to build public key filename: %s", - isc_result_totext(result)); - } -+ isc_buffer_init(&buf, priname, sizeof(priname)); -+ result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); -+ if (result != ISC_R_SUCCESS) { -+ fatal("Failed to build private key filename: %s", -+ isc_result_totext(result)); -+ } -+ -+ result = dst_key_fromfile(dst_key_name(key), dst_key_id(key), -+ dst_key_alg(key), -+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, -+ dir, mctx, &tmp); -+ if (result == ISC_R_SUCCESS) { -+ if (dst_key_isprivate(tmp) && !dst_key_isexternal(tmp)) -+ fatal("Private key already exists in %s", priname); -+ dst_key_free(&tmp); -+ } -+ -+ dst_key_setexternal(key, ISC_TRUE); -+ if (setpub) -+ dst_key_settime(key, DST_TIME_PUBLISH, pub); -+ if (setdel) -+ dst_key_settime(key, DST_TIME_DELETE, del); -+ if (setttl) -+ dst_key_setttl(key, ttl); - - result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, - dir); -@@ -221,8 +246,7 @@ emit(const char *dir, dns_rdata_t *rdata) { - fatal("Failed to write key %s: %s", keystr, - isc_result_totext(result)); - } -- -- printf("%s\n", newname); -+ printf("%s\n", pubname); - - isc_buffer_clear(&buf); - result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf); -@@ -230,7 +254,7 @@ emit(const char *dir, dns_rdata_t *rdata) { - fatal("Failed to build private key filename: %s", - isc_result_totext(result)); - } -- printf("%s\n", newname); -+ printf("%s\n", priname); - dst_key_free(&key); - } - -@@ -240,13 +264,21 @@ usage(void) ISC_PLATFORM_NORETURN_POST; - static void - usage(void) { - fprintf(stderr, "Usage:\n"); -- fprintf(stderr, " %s options [-K dir] file\n\n", program); -+ fprintf(stderr, " %s options [-K dir] keyfile\n\n", program); -+ fprintf(stderr, " %s options -f file [keyname]\n\n", program); - fprintf(stderr, "Version: %s\n", VERSION); - fprintf(stderr, "Options:\n"); -- fprintf(stderr, " -v \n"); -+ fprintf(stderr, " -f file: read key from zone file\n"); - fprintf(stderr, " -K : directory in which to store " -- "the keyset files\n"); -- fprintf(stderr, " -f file: read keyset from zone file\n"); -+ "the key files\n"); -+ fprintf(stderr, " -L ttl: set default key TTL\n"); -+ fprintf(stderr, " -v \n"); -+ fprintf(stderr, " -h: print usage and exit\n"); -+ fprintf(stderr, "Timing options:\n"); -+ fprintf(stderr, " -P date/[+-]offset/none: set/unset key " -+ "publication date\n"); -+ fprintf(stderr, " -D date/[+-]offset/none: set/unset key " -+ "deletion date\n"); - - exit (-1); - } -@@ -274,15 +306,19 @@ main(int argc, char **argv) { - if (result != ISC_R_SUCCESS) - fatal("out of memory"); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - dns_result_register(); - - isc_commandline_errprint = ISC_FALSE; - -- while ((ch = isc_commandline_parse(argc, argv, "D:f:hK:P:v:")) != -1) { -+#define CMDLINE_FLAGS "D:f:hK:L:P:v:" -+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { - switch (ch) { -- case 'D': -- if (setdel) -- fatal("-D specified more than once"); -+ case 'D': -+ if (setdel) -+ fatal("-D specified more than once"); - - setdel = ISC_TRUE; - del = strtotime(isc_commandline_argument, now, now); -@@ -292,9 +328,16 @@ main(int argc, char **argv) { - if (strlen(dir) == 0U) - fatal("directory must be non-empty string"); - break; -- case 'P': -- if (setpub) -- fatal("-P specified more than once"); -+ case 'L': -+ if (strcmp(isc_commandline_argument, "none") == 0) -+ ttl = 0; -+ else -+ ttl = strtottl(isc_commandline_argument); -+ setttl = ISC_TRUE; -+ break; -+ case 'P': -+ if (setpub) -+ fatal("-P specified more than once"); - - setpub = ISC_TRUE; - pub = strtotime(isc_commandline_argument, now, now); -@@ -346,8 +389,8 @@ main(int argc, char **argv) { - dns_rdataset_init(&rdataset); - - if (filename != NULL) { -- if (argc < isc_commandline_index + 1 && filename != NULL) { -- /* using zone name as the zone file name */ -+ if (argc < isc_commandline_index + 1) { -+ /* using filename as zone name */ - namestr = filename; - } else - namestr = argv[isc_commandline_index]; -diff --git a/bin/dnssec/dnssec-importkey.docbook b/bin/dnssec/dnssec-importkey.docbook -index b8d160c..853db30 100644 ---- a/bin/dnssec/dnssec-importkey.docbook -+++ b/bin/dnssec/dnssec-importkey.docbook -@@ -44,22 +44,45 @@ - - - dnssec-importkey -- - -+ - - - - -- -+ -+ -+ -+ dnssec-importkey -+ -+ -+ -+ -+ -+ -+ -+ - - - - - DESCRIPTION - dnssec-importkey -- read a DNSKEY record and generated a .key/.private key pair. -- Publication () and deletions () -- times can be set for the key. -+ reads a public DNSKEY record and generates a pair of -+ .key/.private files. The DNSKEY record may be read from an -+ existing .key file, in which case a corresponding .private file -+ will be generated, or it may be read from any other file or -+ from the standard input, in which case both .key and .private -+ files will be generated. -+ -+ -+ The newly-created .private file does not -+ contain private key data, and cannot be used for signing. -+ However, having a .private file makes it possible to set -+ publication () and deletion -+ () times for the key, which means the -+ public key can be added to and removed from the DNSKEY RRset -+ on schedule even if the true private key is stored offline. - - - -@@ -70,9 +93,16 @@ - - -f filename - -- -- Filename to read the key from. -- -+ -+ Zone file mode: instead of a public keyfile name, the argument -+ is the DNS domain name of a zone master file, which can be read -+ from . If the domain name is the same as -+ , then it may be omitted. -+ -+ -+ If is set to "-", then -+ the zone data is read from the standard input. -+ - - - -@@ -93,7 +123,7 @@ - into a DNSKEY RR. If the key is imported into a zone, - this is the TTL that will be used for it, unless there was - already a DNSKEY RRset in place, in which case the existing TTL -- would take precedence. importkey the default TTL to -+ would take precedence. Setting the default TTL to - 0 or none removes it. -
- -@@ -160,6 +190,16 @@ - - - -+ FILES -+ -+ A keyfile can be designed by the key identification -+ Knnnn.+aaa+iiiii or the full file name -+ Knnnn.+aaa+iiiii.key as generated by -+ dnssec-keygen8. -+ -+ -+ -+ - SEE ALSO - - dnssec-keygen8 -diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c -index 3ad00d7..cc212e1 100644 ---- a/bin/dnssec/dnssec-keyfromlabel.c -+++ b/bin/dnssec/dnssec-keyfromlabel.c -@@ -43,6 +43,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #include "dnssectool.h" - - #define MAX_RSA 4096 /* should be long enough... */ -@@ -76,10 +80,15 @@ usage(void) { - "NSEC3RSASHA1 if using -3)\n"); - fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); - fprintf(stderr, " -c class (default: IN)\n"); --#ifdef USE_PKCS11 -- fprintf(stderr, " -E enginename (default: pkcs11)\n"); -+ fprintf(stderr, " -E :\n"); -+#if defined(PKCS11CRYPTO) -+ fprintf(stderr, " path to PKCS#11 provider library " -+ "(default is %s)\n", PK11_LIB_LOCATION); -+#elif defined(USE_PKCS11) -+ fprintf(stderr, " name of an OpenSSL engine to use " -+ "(default is \"pkcs11\")\n"); - #else -- fprintf(stderr, " -E enginename\n"); -+ fprintf(stderr, " name of an OpenSSL engine to use\n"); - #endif - fprintf(stderr, " -f keyflag: KSK | REVOKE\n"); - fprintf(stderr, " -K directory: directory in which to place " -@@ -116,7 +125,7 @@ main(int argc, char **argv) { - char *nametype = NULL, *type = NULL; - const char *directory = NULL; - #ifdef USE_PKCS11 -- const char *engine = "pkcs11"; -+ const char *engine = PKCS11_ENGINE; - #else - const char *engine = NULL; - #endif -@@ -161,6 +170,9 @@ main(int argc, char **argv) { - - RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - dns_result_register(); - - isc_commandline_errprint = ISC_FALSE; -@@ -334,16 +346,15 @@ main(int argc, char **argv) { - if (argc > isc_commandline_index + 1) - fatal("extraneous arguments"); - -- if (strchr(label, ':') == NULL && -- engine != NULL && strlen(engine) != 0U) { -+ if (strchr(label, ':') == NULL) { - char *l; - int len; - -- len = strlen(label) + strlen(engine) + 2; -+ len = strlen(label) + 8; - l = isc_mem_allocate(mctx, len); - if (l == NULL) - fatal("cannot allocate memory"); -- snprintf(l, len, "%s:%s", engine, label); -+ snprintf(l, len, "pkcs11:%s", label); - isc_mem_free(mctx, label); - label = l; - } -@@ -460,7 +471,7 @@ main(int argc, char **argv) { - - /* associate the key */ - ret = dst_key_fromlabel(name, alg, flags, protocol, -- rdclass, engine, label, NULL, mctx, &key); -+ rdclass, "pkcs11", label, NULL, mctx, &key); - isc_entropy_stopcallbacksources(ectx); - - if (ret != ISC_R_SUCCESS) { -@@ -468,7 +479,7 @@ main(int argc, char **argv) { - char algstr[DNS_SECALG_FORMATSIZE]; - dns_name_format(name, namestr, sizeof(namestr)); - dns_secalg_format(alg, algstr, sizeof(algstr)); -- fatal("failed to get key %s/%s: %s\n", -+ fatal("failed to get key %s/%s: %s", - namestr, algstr, isc_result_totext(ret)); - /* NOTREACHED */ - exit(-1); -diff --git a/bin/dnssec/dnssec-keyfromlabel.docbook b/bin/dnssec/dnssec-keyfromlabel.docbook -index 0dd3c0e..c48a100 100644 ---- a/bin/dnssec/dnssec-keyfromlabel.docbook -+++ b/bin/dnssec/dnssec-keyfromlabel.docbook -@@ -133,8 +133,15 @@ - -E engine - - -- Specifies the name of the crypto hardware (OpenSSL engine). -- When compiled with PKCS#11 support it defaults to "pkcs11". -+ Specifies the cryptographic hardware to use. -+ -+ -+ When BIND is built with OpenSSL PKCS#11 support, this defaults -+ to the string "pkcs11", which identifies an OpenSSL engine -+ that can drive a cryptographic accelerator or hardware service -+ module. When BIND is built with native PKCS#11 cryptography -+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11 -+ provider library specified via "--with-pkcs11". - - - -@@ -143,9 +150,32 @@ - -l label - - -- Specifies the label of the key pair in the crypto hardware. -- The label may be preceded by an optional OpenSSL engine name, -- separated by a colon, as in "pkcs11:keylabel". -+ Specifies the label for a key pair in the crypto hardware. -+ -+ -+ When BIND 9 is built with OpenSSL-based -+ PKCS#11 support, the label is an arbitrary string that -+ identifies a particular key. It may be preceded by an -+ optional OpenSSL engine name, followed by a colon, as in -+ "pkcs11:keylabel". -+ -+ -+ When BIND 9 is built with native PKCS#11 -+ support, the label is a PKCS#11 URI string in the format -+ "pkcs11:=value;=value;..." -+ Keywords include "token", which identifies the HSM; "object", which -+ identifies the key; and "pin-source", which identifies a file from -+ which the HSM's PIN code can be obtained. The label will be -+ stored in the on-disk "private" file. -+ -+ -+ If the label contains a -+ field, tools using the generated -+ key files will be able to use the HSM for signing and other -+ operations without any need for an operator to manually enter -+ a PIN. Note: Making the HSM's PIN accessible in this manner -+ may reduce the security advantage of using an HSM; be sure -+ this is what you want to do before making use of this feature. - - - -@@ -429,7 +459,8 @@ - dnssec-signzone8 - , - BIND 9 Administrator Reference Manual, -- RFC 4034. -+ RFC 4034, -+ The PKCS#11 URI Scheme (draft-pechanec-pkcs11uri-13). - - - -diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c -index 7061829..97b96ee 100644 ---- a/bin/dnssec/dnssec-keygen.c -+++ b/bin/dnssec/dnssec-keygen.c -@@ -58,6 +58,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #include "dnssectool.h" - - #define MAX_RSA 4096 /* should be long enough... */ -@@ -119,10 +123,15 @@ usage(void) { - fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n"); - fprintf(stderr, " -c : (default: IN)\n"); - fprintf(stderr, " -d (0 => max, default)\n"); --#ifdef USE_PKCS11 -- fprintf(stderr, " -E (default \"pkcs11\")\n"); -+ fprintf(stderr, " -E :\n"); -+#if defined(PKCS11CRYPTO) -+ fprintf(stderr, " path to PKCS#11 provider library " -+ "(default is %s)\n", PK11_LIB_LOCATION); -+#elif defined(USE_PKCS11) -+ fprintf(stderr, " name of an OpenSSL engine to use " -+ "(default is \"pkcs11\")\n"); - #else -- fprintf(stderr, " -E \n"); -+ fprintf(stderr, " name of an OpenSSL engine to use\n"); - #endif - fprintf(stderr, " -f : KSK | REVOKE\n"); - fprintf(stderr, " -g : use specified generator " -@@ -134,7 +143,6 @@ usage(void) { - "records with (default: 0)\n"); - fprintf(stderr, " -T : DNSKEY | KEY (default: DNSKEY; " - "use KEY for SIG(0))\n"); -- fprintf(stderr, " ECCGOST:\tignored\n"); - fprintf(stderr, " -t : " - "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " - "(default: AUTHCONF)\n"); -@@ -223,7 +231,7 @@ main(int argc, char **argv) { - isc_log_t *log = NULL; - isc_entropy_t *ectx = NULL; - #ifdef USE_PKCS11 -- const char *engine = "pkcs11"; -+ const char *engine = PKCS11_ENGINE; - #else - const char *engine = NULL; - #endif -@@ -250,6 +258,9 @@ main(int argc, char **argv) { - if (argc == 1) - usage(); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - dns_result_register(); - - isc_commandline_errprint = ISC_FALSE; -diff --git a/bin/dnssec/dnssec-keygen.docbook b/bin/dnssec/dnssec-keygen.docbook -index bc50c02..4c693eb 100644 ---- a/bin/dnssec/dnssec-keygen.docbook -+++ b/bin/dnssec/dnssec-keygen.docbook -@@ -224,10 +224,15 @@ - -E engine - - -- Uses a crypto hardware (OpenSSL engine) for random number -- and, when supported, key generation. When compiled with PKCS#11 -- support it defaults to pkcs11; the empty name resets it to -- no engine. -+ Specifies the cryptographic hardware to use, when applicable. -+ -+ -+ When BIND is built with OpenSSL PKCS#11 support, this defaults -+ to the string "pkcs11", which identifies an OpenSSL engine -+ that can drive a cryptographic accelerator or hardware service -+ module. When BIND is built with native PKCS#11 cryptography -+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11 -+ provider library specified via "--with-pkcs11". - - - -diff --git a/bin/dnssec/dnssec-revoke.c b/bin/dnssec/dnssec-revoke.c -index 7b11581..7b5aaee 100644 ---- a/bin/dnssec/dnssec-revoke.c -+++ b/bin/dnssec/dnssec-revoke.c -@@ -38,6 +38,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #include "dnssectool.h" - - const char *program = "dnssec-revoke"; -@@ -53,7 +57,10 @@ usage(void) { - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s [options] keyfile\n\n", program); - fprintf(stderr, "Version: %s\n", VERSION); --#ifdef USE_PKCS11 -+#if defined(PKCS11CRYPTO) -+ fprintf(stderr, " -E engine: specify PKCS#11 provider " -+ "(default: %s)\n", PK11_LIB_LOCATION); -+#elif defined(USE_PKCS11) - fprintf(stderr, " -E engine: specify OpenSSL engine " - "(default \"pkcs11\")\n"); - #else -@@ -76,7 +83,7 @@ int - main(int argc, char **argv) { - isc_result_t result; - #ifdef USE_PKCS11 -- const char *engine = "pkcs11"; -+ const char *engine = PKCS11_ENGINE; - #else - const char *engine = NULL; - #endif -@@ -100,6 +107,9 @@ main(int argc, char **argv) { - if (result != ISC_R_SUCCESS) - fatal("Out of memory"); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - dns_result_register(); - - isc_commandline_errprint = ISC_FALSE; -diff --git a/bin/dnssec/dnssec-revoke.docbook b/bin/dnssec/dnssec-revoke.docbook -index 4062f5e..0c1dd4e 100644 ---- a/bin/dnssec/dnssec-revoke.docbook -+++ b/bin/dnssec/dnssec-revoke.docbook -@@ -109,8 +109,15 @@ - -E engine - - -- Use the given OpenSSL engine. When compiled with PKCS#11 support -- it defaults to pkcs11; the empty name resets it to no engine. -+ Specifies the cryptographic hardware to use, when applicable. -+ -+ -+ When BIND is built with OpenSSL PKCS#11 support, this defaults -+ to the string "pkcs11", which identifies an OpenSSL engine -+ that can drive a cryptographic accelerator or hardware service -+ module. When BIND is built with native PKCS#11 cryptography -+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11 -+ provider library specified via "--with-pkcs11". - - - -diff --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c -index 108d803..c71cac7 100644 ---- a/bin/dnssec/dnssec-settime.c -+++ b/bin/dnssec/dnssec-settime.c -@@ -41,6 +41,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #include "dnssectool.h" - - const char *program = "dnssec-settime"; -@@ -57,7 +61,10 @@ usage(void) { - fprintf(stderr, " %s [options] keyfile\n\n", program); - fprintf(stderr, "Version: %s\n", VERSION); - fprintf(stderr, "General options:\n"); --#ifdef USE_PKCS11 -+#if defined(PKCS11CRYPTO) -+ fprintf(stderr, " -E engine: specify PKCS#11 provider " -+ "(default: %s)\n", PK11_LIB_LOCATION); -+#elif defined(USE_PKCS11) - fprintf(stderr, " -E engine: specify OpenSSL engine " - "(default \"pkcs11\")\n"); - #else -@@ -119,7 +126,7 @@ int - main(int argc, char **argv) { - isc_result_t result; - #ifdef USE_PKCS11 -- const char *engine = "pkcs11"; -+ const char *engine = PKCS11_ENGINE; - #else - const char *engine = NULL; - #endif -@@ -165,6 +172,9 @@ main(int argc, char **argv) { - - setup_logging(verbose, mctx, &log); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - dns_result_register(); - - isc_commandline_errprint = ISC_FALSE; -diff --git a/bin/dnssec/dnssec-settime.docbook b/bin/dnssec/dnssec-settime.docbook -index bc6870b..3540bf2 100644 ---- a/bin/dnssec/dnssec-settime.docbook -+++ b/bin/dnssec/dnssec-settime.docbook -@@ -153,8 +153,15 @@ - -E engine - - -- Use the given OpenSSL engine. When compiled with PKCS#11 support -- it defaults to pkcs11; the empty name resets it to no engine. -+ Specifies the cryptographic hardware to use, when applicable. -+ -+ -+ When BIND is built with OpenSSL PKCS#11 support, this defaults -+ to the string "pkcs11", which identifies an OpenSSL engine -+ that can drive a cryptographic accelerator or hardware service -+ module. When BIND is built with native PKCS#11 cryptography -+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11 -+ provider library specified via "--with-pkcs11". - - - -diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c -index 83456a7..128c753 100644 ---- a/bin/dnssec/dnssec-signzone.c -+++ b/bin/dnssec/dnssec-signzone.c -@@ -86,6 +86,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #include "dnssectool.h" - - #ifndef PATH_MAX -@@ -2938,7 +2942,10 @@ usage(void) { - fprintf(stderr, "verify generated signatures\n"); - fprintf(stderr, "\t-c class (IN)\n"); - fprintf(stderr, "\t-E engine:\n"); --#ifdef USE_PKCS11 -+#if defined(PKCS11CRYPTO) -+ fprintf(stderr, "\t\tpath to PKCS#11 provider library " -+ "(default is %s)\n", PK11_LIB_LOCATION); -+#elif defined(USE_PKCS11) - fprintf(stderr, "\t\tname of an OpenSSL engine to use " - "(default is \"pkcs11\")\n"); - #else -@@ -3033,7 +3040,7 @@ main(int argc, char *argv[]) { - isc_log_t *log = NULL; - isc_boolean_t pseudorandom = ISC_FALSE; - #ifdef USE_PKCS11 -- const char *engine = "pkcs11"; -+ const char *engine = PKCS11_ENGINE; - #else - const char *engine = NULL; - #endif -@@ -3085,6 +3092,9 @@ main(int argc, char *argv[]) { - if (result != ISC_R_SUCCESS) - fatal("out of memory"); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - dns_result_register(); - - isc_commandline_errprint = ISC_FALSE; -diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook -index e427fc1..c46f43c 100644 ---- a/bin/dnssec/dnssec-signzone.docbook -+++ b/bin/dnssec/dnssec-signzone.docbook -@@ -176,10 +176,17 @@ - -E engine - - -- Uses a crypto hardware (OpenSSL engine) for the crypto operations -- it supports, for instance signing with private keys from -- a secure key store. When compiled with PKCS#11 support -- it defaults to pkcs11; the empty name resets it to no engine. -+ When applicable, specifies the hardware to use for -+ cryptographic operations, such as a secure key store used -+ for signing. -+ -+ -+ When BIND is built with OpenSSL PKCS#11 support, this defaults -+ to the string "pkcs11", which identifies an OpenSSL engine -+ that can drive a cryptographic accelerator or hardware service -+ module. When BIND is built with native PKCS#11 cryptography -+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11 -+ provider library specified via "--with-pkcs11". - - - -diff --git a/bin/dnssec/dnssec-verify.c b/bin/dnssec/dnssec-verify.c -index 682896c..817e380 100644 ---- a/bin/dnssec/dnssec-verify.c -+++ b/bin/dnssec/dnssec-verify.c -@@ -69,6 +69,10 @@ - - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #include "dnssectool.h" - - const char *program = "dnssec-verify"; -@@ -137,7 +141,10 @@ usage(void) { - fprintf(stderr, "\t\tfile format of input zonefile (text)\n"); - fprintf(stderr, "\t-c class (IN)\n"); - fprintf(stderr, "\t-E engine:\n"); --#ifdef USE_PKCS11 -+#if defined(PKCS11CRYPTO) -+ fprintf(stderr, "\t\tpath to PKCS#11 provider library " -+ "(default is %s)\n", PK11_LIB_LOCATION); -+#elif defined(USE_PKCS11) - fprintf(stderr, "\t\tname of an OpenSSL engine to use " - "(default is \"pkcs11\")\n"); - #else -@@ -156,7 +163,7 @@ main(int argc, char *argv[]) { - isc_result_t result; - isc_log_t *log = NULL; - #ifdef USE_PKCS11 -- const char *engine = "pkcs11"; -+ const char *engine = PKCS11_ENGINE; - #else - const char *engine = NULL; - #endif -@@ -195,6 +202,9 @@ main(int argc, char *argv[]) { - if (result != ISC_R_SUCCESS) - fatal("out of memory"); - -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - dns_result_register(); - - isc_commandline_errprint = ISC_FALSE; -diff --git a/bin/dnssec/dnssec-verify.docbook b/bin/dnssec/dnssec-verify.docbook -index 0835df1..875f3ed 100644 ---- a/bin/dnssec/dnssec-verify.docbook -+++ b/bin/dnssec/dnssec-verify.docbook -@@ -78,6 +78,23 @@ - - - -+ -E engine -+ -+ -+ Specifies the cryptographic hardware to use, when applicable. -+ -+ -+ When BIND is built with OpenSSL PKCS#11 support, this defaults -+ to the string "pkcs11", which identifies an OpenSSL engine -+ that can drive a cryptographic accelerator or hardware service -+ module. When BIND is built with native PKCS#11 cryptography -+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11 -+ provider library specified via "--with-pkcs11". -+ -+ -+ -+ -+ - -I input-format - - -diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c -index 5f5f7d8..c68ae69 100644 ---- a/bin/dnssec/dnssectool.c -+++ b/bin/dnssec/dnssectool.c -@@ -319,7 +319,7 @@ strtotime(const char *str, isc_int64_t now, isc_int64_t base) { - isc_result_t result; - const char *orig = str; - char *endp; -- int n; -+ size_t n; - - if ((str[0] == '0' || str[0] == '-') && str[1] == '\0') - return ((isc_stdtime_t) 0); -diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in -index 68c42a8..cd65777 100644 ---- a/bin/named/Makefile.in -+++ b/bin/named/Makefile.in -@@ -51,7 +51,7 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \ - ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ - ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@ - --CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @USE_OPENSSL@ -+CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@ - - CWARNINGS = - -diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h -index cbc14d8..aad462d 100644 ---- a/bin/named/include/named/globals.h -+++ b/bin/named/include/named/globals.h -@@ -146,8 +146,8 @@ EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR - - EXTERN const char * ns_g_username INIT(NULL); - --#ifdef USE_PKCS11 --EXTERN const char * ns_g_engine INIT("pkcs11"); -+#if defined(USE_PKCS11) -+EXTERN const char * ns_g_engine INIT(PKCS11_ENGINE); - #else - EXTERN const char * ns_g_engine INIT(NULL); - #endif -diff --git a/bin/named/main.c b/bin/named/main.c -index 15905ef..a00687f 100644 ---- a/bin/named/main.c -+++ b/bin/named/main.c -@@ -51,6 +51,9 @@ - #include - - #include -+#ifdef PKCS11CRYPTO -+#include -+#endif - - #include - -@@ -1081,6 +1084,9 @@ main(int argc, char *argv[]) { - dns_result_register(); - dst_result_register(); - isccc_result_register(); -+#ifdef PKCS11CRYPTO -+ pk11_result_register(); -+#endif - - parse_command_line(argc, argv); - -diff --git a/bin/named/named.docbook b/bin/named/named.docbook -index 1f08e19..8f46aac 100644 ---- a/bin/named/named.docbook -+++ b/bin/named/named.docbook -@@ -153,11 +153,17 @@ - -E engine-name - - -- Use a crypto hardware (OpenSSL engine) for the crypto operations -- it supports, for instance re-signing with private keys from -- a secure key store. When compiled with PKCS#11 support -- engine-name -- defaults to pkcs11, the empty name resets it to no engine. -+ When applicable, specifies the hardware to use for -+ cryptographic operations, such as a secure key store used -+ for signing. -+ -+ -+ When BIND is built with OpenSSL PKCS#11 support, this defaults -+ to the string "pkcs11", which identifies an OpenSSL engine -+ that can drive a cryptographic accelerator or hardware service -+ module. When BIND is built with native PKCS#11 cryptography -+ (--enable-native-pkcs11), it defaults to the path of the PKCS#11 -+ provider library specified via "--with-pkcs11". - - - -diff --git a/bin/named/server.c b/bin/named/server.c -index 56df6bf..227c646 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -6215,6 +6215,11 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { - server->in_roothints = NULL; - server->blackholeacl = NULL; - -+ /* Must be first. */ -+ CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy, -+ ns_g_engine, ISC_ENTROPY_GOODONLY), -+ "initializing DST"); -+ - CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, - &server->in_roothints), - "setting up root hints"); -@@ -6231,10 +6236,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { - ISC_R_NOMEMORY : ISC_R_SUCCESS, - "allocating reload event"); - -- CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy, -- ns_g_engine, ISC_ENTROPY_GOODONLY), -- "initializing DST"); -- - server->tkeyctx = NULL; - CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy, - &server->tkeyctx), -diff --git a/bin/nsupdate/Makefile.in b/bin/nsupdate/Makefile.in -index 09e6c14..e258ffc 100644 ---- a/bin/nsupdate/Makefile.in -+++ b/bin/nsupdate/Makefile.in -@@ -46,9 +46,11 @@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ - - DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} - --LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ -+LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ -+ ${ISCLIBS} @LIBS@ - --NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@ -+NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \ -+ ${ISCNOSYMLIBS} @LIBS@ - - SUBDIRS = - -diff --git a/bin/pkcs11/Makefile.in b/bin/pkcs11/Makefile.in -index 407d977..15d3fb5 100644 ---- a/bin/pkcs11/Makefile.in -+++ b/bin/pkcs11/Makefile.in -@@ -20,38 +20,51 @@ top_srcdir = @top_srcdir@ - - @BIND9_MAKE_INCLUDES@ - --PROVIDER = @PKCS11_PROVIDER@ -+CINCLUDES = ${ISC_INCLUDES} - --CINCLUDES = -I${srcdir}/include -I${srcdir}/unix -+CDEFINES = - --CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\" -+ISCLIBS = ../../lib/isc/libisc.@A@ -+ -+ISCDEPLIBS = ../../lib/isc/libisc.@A@ -+ -+DEPLIBS = ${ISCDEPLIBS} - - # if FORCE_STATIC_PROVIDER: LIBS = ${PROVIDER} --LIBS = -ldl -+LIBS = ${ISCLIBS} @LIBS@ - --SUBDIRS = -+SUBDIRS = benchmarks - --TARGETS = pkcs11-keygen@EXEEXT@ pkcs11-list@EXEEXT@ \ -- pkcs11-destroy@EXEEXT@ --SRCS = pkcs11-keygen.c pkcs11-list.c pkcs11-destroy.c -+TARGETS = pkcs11-list@EXEEXT@ pkcs11-destroy@EXEEXT@ \ -+ pkcs11-keygen@EXEEXT@ pkcs11-tokens@EXEEXT@ -+SRCS = pkcs11-list.c pkcs11-destroy.c \ -+ pkcs11-keygen.c pkcs11-tokens.c -+OBJS = pkcs11-list.@O@ pkcs11-destroy.@O@ \ -+ pkcs11-keygen.@O@ pkcs11-tokens.@O@ - --MANPAGES = pkcs11-keygen.8 pkcs11-list.8 pkcs11-destroy.8 --HTMLPAGES = pkcs11-keygen.html pkcs11-list.html pkcs11-destroy.html -+MANPAGES = pkcs11-list.8 pkcs11-destroy.8 \ -+ pkcs11-keygen.8 pkcs11-tokens.8 -+HTMLPAGES = pkcs11-list.html pkcs11-destroy.html \ -+ pkcs11-keygen.html pkcs11-tokens.html - MANOBJS = ${MANPAGES} ${HTMLPAGES} - - @BIND9_MAKE_RULES@ - --pkcs11-keygen@EXEEXT@: @srcdir@/pkcs11-keygen.c -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -- -o $@ @srcdir@/pkcs11-keygen.c ${LIBS} -- --pkcs11-list@EXEEXT@: @srcdir@/pkcs11-list.c -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -- -o $@ @srcdir@/pkcs11-list.c ${LIBS} -- --pkcs11-destroy@EXEEXT@: @srcdir@/pkcs11-destroy.c -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -- -o $@ @srcdir@/pkcs11-destroy.c ${LIBS} -+pkcs11-list@EXEEXT@: @srcdir@/pkcs11-list.@O@ ${DEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@ @srcdir@/pkcs11-list.@O@ ${LIBS} -+ -+pkcs11-destroy@EXEEXT@: @srcdir@/pkcs11-destroy.@O@ ${DEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@ @srcdir@/pkcs11-destroy.@O@ ${LIBS} -+ -+pkcs11-keygen@EXEEXT@: @srcdir@/pkcs11-keygen.@O@ ${DEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@ @srcdir@/pkcs11-keygen.@O@ ${LIBS} -+ -+pkcs11-tokens@EXEEXT@: @srcdir@/pkcs11-tokens.@O@ ${DEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@ @srcdir@/pkcs11-tokens.@O@ ${LIBS} - - doc man:: ${MANOBJS} - -@@ -63,12 +76,14 @@ installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8 - - install:: ${TARGETS} installdirs -- ${INSTALL_PROGRAM} pkcs11-keygen@EXEEXT@ ${DESTDIR}${sbindir} -- ${INSTALL_PROGRAM} pkcs11-list@EXEEXT@ ${DESTDIR}${sbindir} -- ${INSTALL_PROGRAM} pkcs11-destroy@EXEEXT@ ${DESTDIR}${sbindir} -- ${INSTALL_DATA} ${srcdir}/pkcs11-keygen.8 ${DESTDIR}${mandir}/man8 -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-list@EXEEXT@ ${DESTDIR}${sbindir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-destroy@EXEEXT@ ${DESTDIR}${sbindir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-keygen@EXEEXT@ ${DESTDIR}${sbindir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-tokens@EXEEXT@ ${DESTDIR}${sbindir} - ${INSTALL_DATA} ${srcdir}/pkcs11-list.8 ${DESTDIR}${mandir}/man8 - ${INSTALL_DATA} ${srcdir}/pkcs11-destroy.8 ${DESTDIR}${mandir}/man8 -+ ${INSTALL_DATA} ${srcdir}/pkcs11-keygen.8 ${DESTDIR}${mandir}/man8 -+ ${INSTALL_DATA} ${srcdir}/pkcs11-tokens.8 ${DESTDIR}${mandir}/man8 - - clean distclean:: -- rm -f ${TARGETS} -+ rm -f ${OBJS} ${TARGETS} -diff --git a/bin/pkcs11/pkcs11-destroy.8 b/bin/pkcs11/pkcs11-destroy.8 -index aff35b3..25323ca 100644 ---- a/bin/pkcs11/pkcs11-destroy.8 -+++ b/bin/pkcs11/pkcs11-destroy.8 -@@ -32,7 +32,7 @@ - pkcs11\-destroy \- destroy PKCS#11 objects - .SH "SYNOPSIS" - .HP 15 --\fBpkcs11\-destroy\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {\-i\ \fIID\fR | \-l\ \fIlabel\fR} [\fB\-p\ \fR\fB\fIPIN\fR\fR] -+\fBpkcs11\-destroy\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {\-i\ \fIID\fR | \-l\ \fIlabel\fR} [\fB\-p\ \fR\fB\fIPIN\fR\fR] [\fB\-w\ \fR\fB\fIseconds\fR\fR] - .SH "DESCRIPTION" - .PP - \fBpkcs11\-destroy\fR -@@ -41,7 +41,7 @@ destroys keys stored in a PKCS#11 device, identified by their - or - \fBlabel\fR. - .PP --Matching keys are displayed before being destroyed. There is a five second delay to allow the user to interrupt the process before the destruction takes place. -+Matching keys are displayed before being destroyed. By default, there is a five second delay to allow the user to interrupt the process before the destruction takes place. - .SH "ARGUMENTS" - .PP - \-m \fImodule\fR -@@ -70,6 +70,12 @@ Specify the PIN for the device. If no PIN is provided on the command line, - \fBpkcs11\-destroy\fR - will prompt for it. - .RE -+.PP -+\-w \fIseconds\fR -+.RS 4 -+Specify how long to pause before carrying out key destruction. The default is five seconds. If set to -+0, destruction will be immediate. -+.RE - .SH "SEE ALSO" - .PP - \fBpkcs11\-list\fR(3), -diff --git a/bin/pkcs11/pkcs11-destroy.c b/bin/pkcs11/pkcs11-destroy.c -index 0f46a89..2905395 100644 ---- a/bin/pkcs11/pkcs11-destroy.c -+++ b/bin/pkcs11/pkcs11-destroy.c -@@ -40,7 +40,10 @@ - - /* $Id: pkcs11-destroy.c,v 1.8 2010/01/13 21:19:52 fdupont Exp $ */ - --/* pkcs11-destroy [-m module] [-s $slot] [-i $id | -l $label] [-p $pin] */ -+/* -+ * pkcs11-destroy [-m module] [-s $slot] [-i $id | -l $label] -+ * [-p $pin] [ -w $wait ] -+ */ - - /*! \file */ - -@@ -52,74 +55,70 @@ - #include - #include - #include --#include "cryptoki.h" - --#ifdef WIN32 --#define sleep(x) Sleep(x) --#include "win32.c" --#else --#ifndef FORCE_STATIC_PROVIDER --#include "unix.c" --#endif --#endif -+#include -+#include -+#include -+ -+#include -+#include - - #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) - #define getpassphrase(x) getpass(x) - #endif - - int --main(int argc, char *argv[]) --{ -+main(int argc, char *argv[]) { -+ isc_result_t result; - CK_RV rv; - CK_SLOT_ID slot = 0; - CK_SESSION_HANDLE hSession; -- CK_UTF8CHAR *pin = NULL; - CK_BYTE attr_id[2]; - CK_OBJECT_HANDLE akey[50]; -+ pk11_context_t pctx; -+ char *lib_name = NULL; - char *label = NULL; -+ char *pin = NULL; - int error = 0; -- unsigned int id = 0, i = 0; -+ unsigned int id = 0, i = 0, wait = 5; - int c, errflg = 0; - CK_ULONG ulObjectCount; - CK_ATTRIBUTE search_template[] = { - {CKA_ID, &attr_id, sizeof(attr_id)} - }; -- char *pk11_provider; - unsigned int j, len; -- extern char *optarg; -- extern int optopt; -- -- pk11_provider = getenv("PKCS11_PROVIDER"); -- if (pk11_provider != NULL) -- pk11_libname = pk11_provider; - -- while ((c = getopt(argc, argv, ":m:s:i:l:p:")) != -1) { -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:i:l:p:w:")) != -1) { - switch (c) { - case 'm': -- pk11_libname = optarg; -+ lib_name = isc_commandline_argument; - break; - case 's': -- slot = atoi(optarg); -+ slot = atoi(isc_commandline_argument); - break; - case 'i': -- id = atoi(optarg); -+ id = atoi(isc_commandline_argument); - id &= 0xffff; - break; - case 'l': -- label = optarg; -+ label = isc_commandline_argument; - break; - case 'p': -- pin = (CK_UTF8CHAR *)optarg; -+ pin = isc_commandline_argument; -+ break; -+ case 'w': -+ wait = atoi(isc_commandline_argument); - break; - case ':': - fprintf(stderr, - "Option -%c requires an operand\n", -- optopt); -+ isc_commandline_option); - errflg++; - break; - case '?': - default: -- fprintf(stderr, "Unrecognised option: -%c\n", optopt); -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); - errflg++; - } - } -@@ -127,56 +126,49 @@ main(int argc, char *argv[]) - if (errflg || (id && (label != NULL))) { - fprintf(stderr, "Usage:\n"); - fprintf(stderr, "\tpkcs11-destroy [-m module] [-s slot] " -- "[-i id | -l label] [-p pin]\n"); -+ "[-i id | -l label] [-p pin] [-w waittime]\n"); - exit(1); - } - - if (id) { -- printf("id %i\n", id); - attr_id[0] = (id >> 8) & 0xff; - attr_id[1] = id & 0xff; - } else if (label) { -- printf("label %s\n", label); - search_template[0].type = CKA_LABEL; - search_template[0].pValue = label; - search_template[0].ulValueLen = strlen(label); - } - -- /* Initialize the CRYPTOKI library */ -- rv = C_Initialize(NULL_PTR); -- if (rv != CKR_OK) { -- if (rv == 0xfe) -- fprintf(stderr, -- "Can't load or link module \"%s\"\n", -- pk11_libname); -- else -- fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv); -- exit(1); -- } -+ pk11_result_register(); - -- /* Open a session on the slot found */ -- rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION, -- NULL_PTR, NULL_PTR, &hSession); -- if (rv != CKR_OK) { -- fprintf(stderr, "C_OpenSession: Error = 0x%.8lX\n", rv); -- error = 1; -- goto exit_program; -- } -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); - - if (pin == NULL) -- pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: "); -+ pin = getpassphrase("Enter Pin: "); - - /* Login to the Token (Keystore) */ -- rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin)); -- memset(pin, 0, strlen((char *)pin)); -- if (rv != CKR_OK) { -- fprintf(stderr, "C_Login: Error = 0x%.8lX\n", rv); -- error = 1; -- goto exit_session; -+ result = pk11_get_session(&pctx, OP_ANY, ISC_FALSE, ISC_TRUE, -+ ISC_TRUE, (const char *) pin, slot); -+ if (result == PK11_R_NORANDOMSERVICE || -+ result == PK11_R_NODIGESTSERVICE || -+ result == PK11_R_NOAESSERVICE) { -+ fprintf(stderr, "Warning: %s\n", isc_result_totext(result)); -+ fprintf(stderr, "This HSM will not work with BIND 9 " -+ "using native PKCS#11.\n"); -+ } else if (result != ISC_R_SUCCESS) { -+ fprintf(stderr, "Unrecoverable error initializing " -+ "PKCS#11: %s\n", isc_result_totext(result)); -+ exit(1); - } - -- rv = C_FindObjectsInit(hSession, search_template, -- ((id != 0) || (label != NULL)) ? 1 : 0); -+ memset(pin, 0, strlen(pin)); -+ -+ hSession = pctx.session; -+ -+ rv = pkcs_C_FindObjectsInit(hSession, search_template, -+ ((id != 0) || (label != NULL)) ? 1 : 0); - - if (rv != CKR_OK) { - fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv); -@@ -184,13 +176,19 @@ main(int argc, char *argv[]) - goto exit_session; - } - -- rv = C_FindObjects(hSession, akey, 50, &ulObjectCount); -+ rv = pkcs_C_FindObjects(hSession, akey, 50, &ulObjectCount); - if (rv != CKR_OK) { - fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv); - error = 1; - goto exit_search; - } - -+ if (ulObjectCount == 0) { -+ printf("No matching key objects found.\n"); -+ goto exit_search; -+ } else -+ printf("Key object%s found:\n", ulObjectCount > 1 ? "s" : ""); -+ - for (i = 0; i < ulObjectCount; i++) { - CK_OBJECT_CLASS oclass = 0; - CK_BYTE labelbuf[64 + 1]; -@@ -204,7 +202,8 @@ main(int argc, char *argv[]) - memset(labelbuf, 0, sizeof(labelbuf)); - memset(idbuf, 0, sizeof(idbuf)); - -- rv = C_GetAttributeValue(hSession, akey[i], attr_template, 3); -+ rv = pkcs_C_GetAttributeValue(hSession, akey[i], -+ attr_template, 3); - if (rv != CKR_OK) { - fprintf(stderr, - "C_GetAttributeValue[%u]: rv = 0x%.8lX\n", -@@ -213,7 +212,7 @@ main(int argc, char *argv[]) - goto exit_search; - } - len = attr_template[2].ulValueLen; -- printf("object[%u]: class %lu label '%s' id[%lu] ", -+ printf(" object[%u]: class %lu, label '%s', id[%lu] ", - i, oclass, labelbuf, attr_template[2].ulValueLen); - if (len > 4) - len = 4; -@@ -227,32 +226,40 @@ main(int argc, char *argv[]) - printf("\n"); - } - -- /* give a chance to kill this */ -- printf("sleeping 5 seconds...\n"); -- sleep(5); -+ if (wait != 0) { -+ printf("WARNING: This action is irreversible! " -+ "Destroying key objects in %d seconds\n ", wait); -+ for (i = 0; i < wait; i++) { -+ printf("."); -+ fflush(stdout); -+ sleep(1); -+ } -+ printf("\n"); -+ } - - for (i = 0; i < ulObjectCount; i++) { -- rv = C_DestroyObject(hSession, akey[i]); -+ rv = pkcs_C_DestroyObject(hSession, akey[i]); - if (rv != CKR_OK) { - fprintf(stderr, -- "C_DestroyObject[%u]: rv = 0x%.8lX\n", -+ "C_DestroyObject[%u] failed: rv = 0x%.8lX\n", - i, rv); - error = 1; - } - } - -+ if (error == 0) -+ printf("Destruction complete.\n"); -+ - exit_search: -- rv = C_FindObjectsFinal(hSession); -+ rv = pkcs_C_FindObjectsFinal(hSession); - if (rv != CKR_OK) { - fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv); - error = 1; - } - - exit_session: -- (void)C_CloseSession(hSession); -- -- exit_program: -- (void)C_Finalize(NULL_PTR); -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); - - exit(error); - } -diff --git a/bin/pkcs11/pkcs11-destroy.docbook b/bin/pkcs11/pkcs11-destroy.docbook -index b4c2048..45c0208 100644 ---- a/bin/pkcs11/pkcs11-destroy.docbook -+++ b/bin/pkcs11/pkcs11-destroy.docbook -@@ -37,6 +37,7 @@ - - - 2009 -+ 2014 - Internet Systems Consortium, Inc. ("ISC") - - -@@ -51,6 +52,7 @@ - -l label - - -+ - - - -@@ -62,9 +64,9 @@ - . - - -- Matching keys are displayed before being destroyed. There is a -- five second delay to allow the user to interrupt the process -- before the destruction takes place. -+ Matching keys are displayed before being destroyed. By default, -+ there is a five second delay to allow the user to interrupt the -+ process before the destruction takes place. - - - -@@ -119,6 +121,17 @@ - - - -+ -+ -+ -w seconds -+ -+ -+ Specify how long to pause before carrying out key destruction. -+ The default is five seconds. If set to 0, -+ destruction will be immediate. -+ -+ -+ - - - -diff --git a/bin/pkcs11/pkcs11-destroy.html b/bin/pkcs11/pkcs11-destroy.html -index afc6e36..899b3e9 100644 ---- a/bin/pkcs11/pkcs11-destroy.html -+++ b/bin/pkcs11/pkcs11-destroy.html -@@ -29,23 +29,23 @@ - -
-

Synopsis

--

pkcs11-destroy [-m module] [-s slot] { -i ID | -l label } [-p PIN]

-+

pkcs11-destroy [-m module] [-s slot] { -i ID | -l label } [-p PIN] [-w seconds]

-
-
--

DESCRIPTION

-+

DESCRIPTION

-

- pkcs11-destroy destroys keys stored in a - PKCS#11 device, identified by their ID or - label. -

-

-- Matching keys are displayed before being destroyed. There is a -- five second delay to allow the user to interrupt the process -- before the destruction takes place. -+ Matching keys are displayed before being destroyed. By default, -+ there is a five second delay to allow the user to interrupt the -+ process before the destruction takes place. -

-
-
--

ARGUMENTS

-+

ARGUMENTS

-
-
-m module
-

-@@ -71,17 +71,23 @@ - Specify the PIN for the device. If no PIN is provided on the - command line, pkcs11-destroy will prompt for it. -

-+
-w seconds
-+

-+ Specify how long to pause before carrying out key destruction. -+ The default is five seconds. If set to 0, -+ destruction will be immediate. -+

-
-
-
--

SEE ALSO

-+

SEE ALSO

-

- pkcs11-list(3), - pkcs11-keygen(3) -

-
-
--

AUTHOR

-+

AUTHOR

-

Internet Systems Consortium -

-
-diff --git a/bin/pkcs11/pkcs11-keygen.8 b/bin/pkcs11/pkcs11-keygen.8 -index 568e862..53de464 100644 ---- a/bin/pkcs11/pkcs11-keygen.8 -+++ b/bin/pkcs11/pkcs11-keygen.8 -@@ -23,80 +23,91 @@ - .\" Manual: BIND9 - .\" Source: BIND9 - .\" --.TH "PKCS11\-KEYGEN" "8" "Sep 18, 2009" "BIND9" "BIND9" -+.TH "PKCS11\-ECGEN" "8" "Feb 30, 2012" "BIND9" "BIND9" - .\" disable hyphenation - .nh - .\" disable justification (adjust text to left margin only) - .ad l - .SH "NAME" --pkcs11\-keygen \- generate RSA keys on a PKCS#11 device -+pkcs11\-keygen \- generate keys on a PKCS#11 device - .SH "SYNOPSIS" - .HP 14 --\fBpkcs11\-keygen\fR [\fB\-P\fR] [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] [\fB\-e\fR] {\-b\ \fIkeysize\fR} {\-l\ \fIlabel\fR} [\fB\-i\ \fR\fB\fIid\fR\fR] [\fB\-p\ \fR\fB\fIPIN\fR\fR] -+\fBpkcs11\-keygen\fR {\-a\ \fIalgorithm\fR} [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-e\fR] [\fB\-i\ \fR\fB\fIid\fR\fR] [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-P\fR] [\fB\-p\ \fR\fB\fIPIN\fR\fR] [\fB\-q\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {label} - .SH "DESCRIPTION" - .PP - \fBpkcs11\-keygen\fR --causes a PKCS#11 device to generate a new RSA key pair with the specified -+causes a PKCS#11 device to generate a new key pair with the given - \fBlabel\fR --and with -+(which must be unique) and with - \fBkeysize\fR --bits of modulus. -+bits of prime. - .SH "ARGUMENTS" - .PP --\-P --.RS 4 --Set the new private key to be non\-sensitive and extractable. The allows the private key data to be read from the PKCS#11 device. The default is for private keys to be sensitive and non\-extractable. --.RE --.PP --\-m \fImodule\fR -+\-a \fIalgorithm\fR - .RS 4 --Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device. -+Specify the key algorithm class: Supported classes are RSA, DSA, DH, and ECC. In addition to these strings, the -+\fBalgorithm\fR -+can be specified as a DNSSEC signing algorithm that will be used with this key; for example, NSEC3RSASHA1 maps to RSA, and ECDSAP256SHA256 maps to ECC. The default class is "RSA". - .RE - .PP --\-s \fIslot\fR -+\-b \fIkeysize\fR - .RS 4 --Open the session with the given PKCS#11 slot. The default is slot 0. -+Create the key pair with -+\fBkeysize\fR -+bits of prime. For ECC keys, the only valid values are 256 and 384, and the default is 256. - .RE - .PP - \-e - .RS 4 --Use a large exponent. -+For RSA keys only, use a large exponent. - .RE - .PP --\-b \fIkeysize\fR -+\-i \fIid\fR - .RS 4 --Create the key pair with --\fBkeysize\fR --bits of modulus. -+Create key objects with id. The id is either an unsigned short 2 byte or an unsigned long 4 byte number. - .RE - .PP --\-l \fIlabel\fR -+\-m \fImodule\fR - .RS 4 --Create key objects with the given label. This name must be unique. -+Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device. - .RE - .PP --\-i \fIid\fR -+\-P - .RS 4 --Create key objects with id. The id is either an unsigned short 2 byte or an unsigned long 4 byte number. -+Set the new private key to be non\-sensitive and extractable. The allows the private key data to be read from the PKCS#11 device. The default is for private keys to be sensitive and non\-extractable. - .RE - .PP - \-p \fIPIN\fR - .RS 4 - Specify the PIN for the device. If no PIN is provided on the command line, --\fBpkcs11\-keygen\fR -+\fBpkcs11\-ecgen\fR - will prompt for it. - .RE -+.PP -+\-e -+.RS 4 -+Quiet mode: suppress unnecessary output. -+.RE -+.PP -+\-S -+.RS 4 -+For Diffie\-Hellman (DH) keys only, use a special prime of 768, 1024 or 1536 bit size and base (aka generator) 2. If not specified, bit size will default to 1024. -+.RE -+.PP -+\-s \fIslot\fR -+.RS 4 -+Open the session with the given PKCS#11 slot. The default is slot 0. -+.RE - .SH "SEE ALSO" - .PP -+\fBpkcs11\-rsagen\fR(3), -+\fBpkcs11\-dsagen\fR(3), - \fBpkcs11\-list\fR(3), - \fBpkcs11\-destroy\fR(3), - \fBdnssec\-keyfromlabel\fR(3), --.SH "CAVEAT" --.PP --Some PKCS#11 providers crash with big public exponent. - .SH "AUTHOR" - .PP - Internet Systems Consortium - .SH "COPYRIGHT" --Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC") -+Copyright \(co 2012 Internet Systems Consortium, Inc. ("ISC") - .br -diff --git a/bin/pkcs11/pkcs11-keygen.c b/bin/pkcs11/pkcs11-keygen.c -index 1ffb343..cc91776 100644 ---- a/bin/pkcs11/pkcs11-keygen.c -+++ b/bin/pkcs11/pkcs11-keygen.c -@@ -40,18 +40,19 @@ - - /* $Id: pkcs11-keygen.c,v 1.9 2009/10/26 23:36:53 each Exp $ */ - --/* pkcs11-keygen - pkcs11 rsa key generator --* --* create RSASHA1 key in the keystore of an SCA6000 --* The calculation of key tag is left to the script --* that converts the key into a DNSKEY RR and inserts --* it into a zone file. --* --* usage: --* pkcs11-keygen [-P] [-m module] [-s slot] [-e] -b keysize --* -l label [-i id] [-p pin] --* --*/ -+/* pkcs11-keygen - PKCS#11 key generator -+ * -+ * Create a key in the keystore of an HSM -+ * -+ * The calculation of key tag is left to the script -+ * that converts the key into a DNSKEY RR and inserts -+ * it into a zone file. -+ * -+ * usage: -+ * pkcs11-keygen [-P] [-m module] [-s slot] [-e] [-b keysize] -+ * [-i id] [-p pin] -l label -+ * -+ */ - - /*! \file */ - -@@ -63,15 +64,16 @@ - #include - #include - #include --#include "cryptoki.h" - --#ifdef WIN32 --#include "win32.c" --#else --#ifndef FORCE_STATIC_PROVIDER --#include "unix.c" --#endif --#endif -+#include -+#include -+#include -+ -+#include -+#include -+#define WANT_DH_PRIMES -+#define WANT_ECC_CURVES -+#include - - #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) - #define getpassphrase(x) getpass(x) -@@ -81,188 +83,478 @@ - static CK_BBOOL truevalue = TRUE; - static CK_BBOOL falsevalue = FALSE; - -+/* Key class: RSA, ECC, DSA, DH, or unknown */ -+typedef enum { -+ key_unknown, -+ key_rsa, -+ key_dsa, -+ key_dh, -+ key_ecc -+} key_class_t; -+ -+/* -+ * Private key template: usable for most key classes without -+ * modificaton; override CKA_SIGN with CKA_DERIVE for DH -+ */ -+#define PRIVATE_LABEL 0 -+#define PRIVATE_SIGN 1 -+#define PRIVATE_DERIVE 1 -+#define PRIVATE_TOKEN 2 -+#define PRIVATE_PRIVATE 3 -+#define PRIVATE_SENSITIVE 4 -+#define PRIVATE_EXTRACTABLE 5 -+#define PRIVATE_ID 6 -+#define PRIVATE_ATTRS 7 -+static CK_ATTRIBUTE private_template[] = { -+ {CKA_LABEL, NULL_PTR, 0}, -+ {CKA_SIGN, &truevalue, sizeof(truevalue)}, -+ {CKA_TOKEN, &truevalue, sizeof(truevalue)}, -+ {CKA_PRIVATE, &truevalue, sizeof(truevalue)}, -+ {CKA_SENSITIVE, &truevalue, sizeof(truevalue)}, -+ {CKA_EXTRACTABLE, &falsevalue, sizeof(falsevalue)}, -+ {CKA_ID, NULL_PTR, 0} -+}; -+ -+/* -+ * Public key template for RSA keys -+ */ -+#define RSA_LABEL 0 -+#define RSA_VERIFY 1 -+#define RSA_TOKEN 2 -+#define RSA_PRIVATE 3 -+#define RSA_MODULUS_BITS 4 -+#define RSA_PUBLIC_EXPONENT 5 -+#define RSA_ID 6 -+#define RSA_ATTRS 7 -+static CK_ATTRIBUTE rsa_template[] = { -+ {CKA_LABEL, NULL_PTR, 0}, -+ {CKA_VERIFY, &truevalue, sizeof(truevalue)}, -+ {CKA_TOKEN, &truevalue, sizeof(truevalue)}, -+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, -+ {CKA_MODULUS_BITS, NULL_PTR, 0}, -+ {CKA_PUBLIC_EXPONENT, NULL_PTR, 0}, -+ {CKA_ID, NULL_PTR, 0} -+}; -+ -+/* -+ * Public key template for ECC keys -+ */ -+#define ECC_LABEL 0 -+#define ECC_VERIFY 1 -+#define ECC_TOKEN 2 -+#define ECC_PRIVATE 3 -+#define ECC_PARAMS 4 -+#define ECC_ID 5 -+#define ECC_ATTRS 6 -+static CK_ATTRIBUTE ecc_template[] = { -+ {CKA_LABEL, NULL_PTR, 0}, -+ {CKA_VERIFY, &truevalue, sizeof(truevalue)}, -+ {CKA_TOKEN, &truevalue, sizeof(truevalue)}, -+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, -+ {CKA_EC_PARAMS, NULL_PTR, 0}, -+ {CKA_ID, NULL_PTR, 0} -+}; -+ -+/* -+ * Public key template for DSA keys -+ */ -+#define DSA_LABEL 0 -+#define DSA_VERIFY 1 -+#define DSA_TOKEN 2 -+#define DSA_PRIVATE 3 -+#define DSA_PRIME 4 -+#define DSA_SUBPRIME 5 -+#define DSA_BASE 6 -+#define DSA_ID 7 -+#define DSA_ATTRS 8 -+static CK_ATTRIBUTE dsa_template[] = { -+ {CKA_LABEL, NULL_PTR, 0}, -+ {CKA_VERIFY, &truevalue, sizeof(truevalue)}, -+ {CKA_TOKEN, &truevalue, sizeof(truevalue)}, -+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, -+ {CKA_PRIME, NULL_PTR, 0}, -+ {CKA_SUBPRIME, NULL_PTR, 0}, -+ {CKA_BASE, NULL_PTR, 0}, -+ {CKA_ID, NULL_PTR, 0} -+}; -+#define DSA_PARAM_PRIME 0 -+#define DSA_PARAM_SUBPRIME 1 -+#define DSA_PARAM_BASE 2 -+#define DSA_PARAM_ATTRS 3 -+static CK_ATTRIBUTE dsa_param_template[] = { -+ {CKA_PRIME, NULL_PTR, 0}, -+ {CKA_SUBPRIME, NULL_PTR, 0}, -+ {CKA_BASE, NULL_PTR, 0}, -+}; -+#define DSA_DOMAIN_PRIMEBITS 0 -+#define DSA_DOMAIN_PRIVATE 1 -+#define DSA_DOMAIN_ATTRS 2 -+static CK_ATTRIBUTE dsa_domain_template[] = { -+ {CKA_PRIME_BITS, NULL_PTR, 0}, -+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, -+}; -+ -+/* -+ * Public key template for DH keys -+ */ -+#define DH_LABEL 0 -+#define DH_VERIFY 1 -+#define DH_TOKEN 2 -+#define DH_PRIVATE 3 -+#define DH_PRIME 4 -+#define DH_BASE 5 -+#define DH_ID 6 -+#define DH_ATTRS 7 -+static CK_ATTRIBUTE dh_template[] = { -+ {CKA_LABEL, NULL_PTR, 0}, -+ {CKA_VERIFY, &truevalue, sizeof(truevalue)}, -+ {CKA_TOKEN, &truevalue, sizeof(truevalue)}, -+ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)}, -+ {CKA_PRIME, NULL_PTR, 0}, -+ {CKA_BASE, NULL_PTR, 0}, -+ {CKA_ID, NULL_PTR, 0} -+}; -+#define DH_PARAM_PRIME 0 -+#define DH_PARAM_BASE 1 -+#define DH_PARAM_ATTRS 2 -+static CK_ATTRIBUTE dh_param_template[] = { -+ {CKA_PRIME, NULL_PTR, 0}, -+ {CKA_BASE, NULL_PTR, 0}, -+}; -+#define DH_DOMAIN_PRIMEBITS 0 -+#define DH_DOMAIN_ATTRS 1 -+static CK_ATTRIBUTE dh_domain_template[] = { -+ {CKA_PRIME_BITS, NULL_PTR, 0}, -+}; -+ -+/* -+ * Convert from text to key class. Accepts the names of DNSSEC -+ * signing algorithms, so e.g., ECDSAP256SHA256 maps to ECC and -+ * NSEC3RSASHA1 maps to RSA. -+ */ -+static key_class_t -+keyclass_fromtext(const char *name) { -+ if (name == NULL) -+ return (key_unknown); -+ -+ if (strncasecmp(name, "rsa", 3) == 0 || -+ strncasecmp(name, "nsec3rsa", 8) == 0) -+ return (key_rsa); -+ else if (strncasecmp(name, "dsa", 3) == 0 || -+ strncasecmp(name, "nsec3dsa", 8) == 0) -+ return (key_dsa); -+ else if (strcasecmp(name, "dh") == 0) -+ return (key_dh); -+ else if (strncasecmp(name, "ecc", 3) == 0 || -+ strncasecmp(name, "ecdsa", 5) == 0) -+ return (key_ecc); -+ else -+ return (key_unknown); -+} -+ -+static void -+usage() { -+ fprintf(stderr, -+ "Usage:\n" -+ "\tpkcs11-keygen -a algorithm -b keysize -l label\n" -+ "\t [-P] [-m module] " -+ "[-s slot] [-e] [-S] [-i id] [-p PIN]\n"); -+ exit(2); -+} -+ - int --main(int argc, char *argv[]) --{ -+main(int argc, char *argv[]) { -+ isc_result_t result; - CK_RV rv; - CK_SLOT_ID slot = 0; -- CK_MECHANISM genmech; -+ CK_MECHANISM mech, dpmech; - CK_SESSION_HANDLE hSession; -- CK_UTF8CHAR *pin = NULL; -- CK_ULONG modulusbits = 0; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ CK_ULONG bits = 0; - CK_CHAR *label = NULL; -- CK_OBJECT_HANDLE privatekey, publickey; -- CK_BYTE public_exponent[5]; -- CK_ULONG expsize = 3; -+ CK_OBJECT_HANDLE privatekey, publickey, domainparams; -+ CK_BYTE exponent[5]; -+ CK_ULONG expsize = 0; -+ pk11_context_t pctx; - int error = 0; - int c, errflg = 0; -- int hide = 1; -- int idlen = 0; -+ int hide = 1, special = 0, quiet = 0; -+ int idlen = 0, id_offset = 0; -+ unsigned int i; - unsigned long id = 0; - CK_BYTE idbuf[4]; - CK_ULONG ulObjectCount; -- /* Set search template */ - CK_ATTRIBUTE search_template[] = { - {CKA_LABEL, NULL_PTR, 0} - }; -- CK_ATTRIBUTE publickey_template[] = { -- {CKA_LABEL, NULL_PTR, 0}, -- {CKA_VERIFY, &truevalue, sizeof(truevalue)}, -- {CKA_TOKEN, &truevalue, sizeof(truevalue)}, -- {CKA_MODULUS_BITS, &modulusbits, sizeof(modulusbits)}, -- {CKA_PUBLIC_EXPONENT, &public_exponent, expsize}, -- {CKA_ID, &idbuf, idlen} -- }; -- CK_ULONG publickey_attrcnt = 6; -- CK_ATTRIBUTE privatekey_template[] = { -- {CKA_LABEL, NULL_PTR, 0}, -- {CKA_SIGN, &truevalue, sizeof(truevalue)}, -- {CKA_TOKEN, &truevalue, sizeof(truevalue)}, -- {CKA_PRIVATE, &truevalue, sizeof(truevalue)}, -- {CKA_SENSITIVE, &truevalue, sizeof(truevalue)}, -- {CKA_EXTRACTABLE, &falsevalue, sizeof(falsevalue)}, -- {CKA_ID, &idbuf, idlen} -- }; -- CK_ULONG privatekey_attrcnt = 7; -- char *pk11_provider; -- extern char *optarg; -- extern int optopt; - -- pk11_provider = getenv("PKCS11_PROVIDER"); -- if (pk11_provider != NULL) -- pk11_libname = pk11_provider; -+ CK_ATTRIBUTE *public_template = NULL; -+ CK_ATTRIBUTE *domain_template = NULL; -+ CK_ATTRIBUTE *param_template = NULL; -+ CK_ULONG public_attrcnt = 0, private_attrcnt = PRIVATE_ATTRS; -+ CK_ULONG domain_attrcnt = 0, param_attrcnt = 0; -+ key_class_t keyclass = key_rsa; -+ pk11_optype_t op_type = OP_ANY; - -- while ((c = getopt(argc, argv, ":Pm:s:b:ei:l:p:")) != -1) { -+#define OPTIONS ":a:b:ei:l:m:Pp:qSs:" -+ while ((c = isc_commandline_parse(argc, argv, OPTIONS)) != -1) { - switch (c) { -+ case 'a': -+ keyclass = keyclass_fromtext(isc_commandline_argument); -+ break; - case 'P': - hide = 0; - break; - case 'm': -- pk11_libname = optarg; -+ lib_name = isc_commandline_argument; - break; - case 's': -- slot = atoi(optarg); -+ slot = atoi(isc_commandline_argument); - break; - case 'e': - expsize = 5; - break; - case 'b': -- modulusbits = atoi(optarg); -+ bits = atoi(isc_commandline_argument); - break; - case 'l': -- label = (CK_CHAR *)optarg; -+ /* -l option is retained for backward compatibility * */ -+ label = (CK_CHAR *)isc_commandline_argument; - break; - case 'i': -- id = strtoul(optarg, NULL, 0); -+ id = strtoul(isc_commandline_argument, NULL, 0); - idlen = 4; - break; - case 'p': -- pin = (CK_UTF8CHAR *)optarg; -+ pin = isc_commandline_argument; -+ break; -+ case 'q': -+ quiet = 1; -+ break; -+ case 'S': -+ special = 1; - break; - case ':': - fprintf(stderr, - "Option -%c requires an operand\n", -- optopt); -+ isc_commandline_option); - errflg++; - break; - case '?': - default: -- fprintf(stderr, "Unrecognised option: -%c\n", optopt); -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); - errflg++; - } - } - -- if (errflg || !modulusbits || (label == NULL)) { -- fprintf(stderr, "Usage:\n"); -- fprintf(stderr, "\tpkcs11-keygen -b keysize -l label\n"); -- fprintf(stderr, "\t [-P] [-m module] " -- "[-s slot] [-e] [-i id] [-p PIN]\n"); -+ if (label == NULL && isc_commandline_index < argc) -+ label = (CK_CHAR *)argv[isc_commandline_index]; -+ -+ if (errflg || (label == NULL)) -+ usage(); -+ -+ if (expsize != 0 && keyclass != key_rsa) { -+ fprintf(stderr, "The -e option is only compatible " -+ "with RSA key generation\n"); - exit(2); - } -+ -+ if (special != 0 && keyclass != key_dh) { -+ fprintf(stderr, "The -S option is only compatible " -+ "with Diffie-Hellman key generation\n"); -+ exit(2); -+ } -+ -+ switch (keyclass) { -+ case key_rsa: -+ op_type = OP_RSA; -+ if (expsize == 0) -+ expsize = 3; -+ if (bits == 0) -+ usage(); -+ -+ mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; -+ mech.pParameter = NULL; -+ mech.ulParameterLen = 0; -+ -+ public_template = rsa_template; -+ public_attrcnt = RSA_ATTRS; -+ id_offset = RSA_ID; -+ -+ /* Set public exponent to F4 or F5 */ -+ exponent[0] = 0x01; -+ exponent[1] = 0x00; -+ if (expsize == 3) -+ exponent[2] = 0x01; -+ else { -+ exponent[2] = 0x00; -+ exponent[3] = 0x00; -+ exponent[4] = 0x01; -+ } -+ -+ public_template[RSA_MODULUS_BITS].pValue = &bits; -+ public_template[RSA_MODULUS_BITS].ulValueLen = sizeof(bits); -+ public_template[RSA_PUBLIC_EXPONENT].pValue = &exponent; -+ public_template[RSA_PUBLIC_EXPONENT].ulValueLen = expsize; -+ break; -+ case key_ecc: -+ op_type = OP_EC; -+ if (bits == 0) -+ bits = 256; -+ else if (bits != 256 && bits != 384) { -+ fprintf(stderr, "ECC keys only support bit sizes of " -+ "256 and 384\n"); -+ exit(2); -+ } -+ -+ mech.mechanism = CKM_EC_KEY_PAIR_GEN; -+ mech.pParameter = NULL; -+ mech.ulParameterLen = 0; -+ -+ public_template = ecc_template; -+ public_attrcnt = ECC_ATTRS; -+ id_offset = ECC_ID; -+ -+ if (bits == 256) { -+ public_template[4].pValue = pk11_ecc_prime256v1; -+ public_template[4].ulValueLen = -+ sizeof(pk11_ecc_prime256v1); -+ } else { -+ public_template[4].pValue = pk11_ecc_secp384r1; -+ public_template[4].ulValueLen = -+ sizeof(pk11_ecc_secp384r1); -+ } -+ -+ break; -+ case key_dsa: -+ op_type = OP_DSA; -+ if (bits == 0) -+ usage(); -+ -+ dpmech.mechanism = CKM_DSA_PARAMETER_GEN; -+ dpmech.pParameter = NULL; -+ dpmech.ulParameterLen = 0; -+ mech.mechanism = CKM_DSA_KEY_PAIR_GEN; -+ mech.pParameter = NULL; -+ mech.ulParameterLen = 0; -+ -+ public_template = dsa_template; -+ public_attrcnt = DSA_ATTRS; -+ id_offset = DSA_ID; -+ -+ domain_template = dsa_domain_template; -+ domain_attrcnt = DSA_DOMAIN_ATTRS; -+ param_template = dsa_param_template; -+ param_attrcnt = DSA_PARAM_ATTRS; -+ -+ domain_template[DSA_DOMAIN_PRIMEBITS].pValue = &bits; -+ domain_template[DSA_DOMAIN_PRIMEBITS].ulValueLen = sizeof(bits); -+ break; -+ case key_dh: -+ op_type = OP_DH; -+ if (special && bits == 0) -+ bits = 1024; -+ else if (special && -+ bits != 768 && bits != 1024 && bits != 1536) -+ { -+ fprintf(stderr, "When using the special prime (-S) " -+ "option, only key sizes of\n" -+ "768, 1024 or 1536 are supported.\n"); -+ exit(2); -+ } else if (bits == 0) -+ usage(); -+ -+ dpmech.mechanism = CKM_DH_PKCS_PARAMETER_GEN; -+ dpmech.pParameter = NULL; -+ dpmech.ulParameterLen = 0; -+ mech.mechanism = CKM_DH_PKCS_KEY_PAIR_GEN; -+ mech.pParameter = NULL; -+ mech.ulParameterLen = 0; -+ -+ /* Override CKA_SIGN attribute */ -+ private_template[PRIVATE_DERIVE].type = CKA_DERIVE; -+ -+ public_template = dh_template; -+ public_attrcnt = DH_ATTRS; -+ id_offset = DH_ID; -+ -+ domain_template = dh_domain_template; -+ domain_attrcnt = DH_DOMAIN_ATTRS; -+ param_template = dh_param_template; -+ param_attrcnt = DH_PARAM_ATTRS; -+ -+ domain_template[DH_DOMAIN_PRIMEBITS].pValue = &bits; -+ domain_template[DH_DOMAIN_PRIMEBITS].ulValueLen = sizeof(bits); -+ break; -+ case key_unknown: -+ usage(); -+ } - - search_template[0].pValue = label; - search_template[0].ulValueLen = strlen((char *)label); -- publickey_template[0].pValue = label; -- publickey_template[0].ulValueLen = strlen((char *)label); -- privatekey_template[0].pValue = label; -- privatekey_template[0].ulValueLen = strlen((char *)label); -- -- /* Set public exponent to F4 or F5 */ -- public_exponent[0] = 0x01; -- public_exponent[1] = 0x00; -- if (expsize == 3) -- public_exponent[2] = 0x01; -- else { -- publickey_template[4].ulValueLen = expsize; -- public_exponent[2] = 0x00; -- public_exponent[3] = 0x00; -- public_exponent[4] = 0x01; -- } -- -- /* Set up mechanism for generating key pair */ -- genmech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; -- genmech.pParameter = NULL_PTR; -- genmech.ulParameterLen = 0; -+ public_template[0].pValue = label; -+ public_template[0].ulValueLen = strlen((char *)label); -+ private_template[0].pValue = label; -+ private_template[0].ulValueLen = strlen((char *)label); - - if (idlen == 0) { -- publickey_attrcnt--; -- privatekey_attrcnt--; -- } else if (id <= 0xffff) { -- idlen = 2; -- publickey_template[5].ulValueLen = idlen; -- privatekey_template[6].ulValueLen = idlen; -- idbuf[0] = (CK_BYTE)(id >> 8); -- idbuf[1] = (CK_BYTE)id; -+ public_attrcnt--; -+ private_attrcnt--; - } else { -- idbuf[0] = (CK_BYTE)(id >> 24); -- idbuf[1] = (CK_BYTE)(id >> 16); -- idbuf[2] = (CK_BYTE)(id >> 8); -- idbuf[3] = (CK_BYTE)id; -- } -- -- /* Initialize the CRYPTOKI library */ -- rv = C_Initialize(NULL_PTR); -+ if (id <= 0xffff) { -+ idlen = 2; -+ idbuf[0] = (CK_BYTE)(id >> 8); -+ idbuf[1] = (CK_BYTE)id; -+ } else { -+ idbuf[0] = (CK_BYTE)(id >> 24); -+ idbuf[1] = (CK_BYTE)(id >> 16); -+ idbuf[2] = (CK_BYTE)(id >> 8); -+ idbuf[3] = (CK_BYTE)id; -+ } - -- if (rv != CKR_OK) { -- if (rv == 0xfe) -- fprintf(stderr, -- "Can't load or link module \"%s\"\n", -- pk11_libname); -- else -- fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv); -- exit(1); -+ public_template[id_offset].pValue = idbuf; -+ public_template[id_offset].ulValueLen = idlen; -+ private_template[PRIVATE_ID].pValue = idbuf; -+ private_template[PRIVATE_ID].ulValueLen = idlen; - } - -- /* Open a session on the slot found */ -- rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION, -- NULL_PTR, NULL_PTR, &hSession); -+ pk11_result_register(); - -- if (rv != CKR_OK) { -- fprintf(stderr, "C_OpenSession: Error = 0x%.8lX\n", rv); -- error = 1; -- goto exit_program; -- } -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); - -- /* Login to the Token (Keystore) */ - if (pin == NULL) -- pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: "); -+ pin = getpassphrase("Enter Pin: "); - -- rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin)); -- memset(pin, 0, strlen((char *)pin)); -- if (rv != CKR_OK) { -- fprintf(stderr, "C_Login: Error = 0x%.8lX\n", rv); -- error = 1; -- goto exit_session; -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE, -+ ISC_TRUE, (const char *) pin, slot); -+ if (result == PK11_R_NORANDOMSERVICE || -+ result == PK11_R_NODIGESTSERVICE || -+ result == PK11_R_NOAESSERVICE) { -+ fprintf(stderr, "Warning: %s\n", isc_result_totext(result)); -+ fprintf(stderr, "This HSM will not work with BIND 9 " -+ "using native PKCS#11.\n"); -+ } else if (result != ISC_R_SUCCESS) { -+ fprintf(stderr, "Unrecoverable error initializing " -+ "PKCS#11: %s\n", isc_result_totext(result)); -+ exit(1); - } - -+ /* Login to the Token (Keystore) */ -+ memset(pin, 0, strlen(pin)); -+ hSession = pctx.session; -+ - /* check if a key with the same id already exists */ -- rv = C_FindObjectsInit(hSession, search_template, 1); -+ rv = pkcs_C_FindObjectsInit(hSession, search_template, 1); - if (rv != CKR_OK) { - fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv); - error = 1; - goto exit_session; - } -- rv = C_FindObjects(hSession, &privatekey, 1, &ulObjectCount); -+ rv = pkcs_C_FindObjects(hSession, &privatekey, 1, &ulObjectCount); - if (rv != CKR_OK) { - fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv); - error = 1; -@@ -276,33 +568,140 @@ main(int argc, char *argv[]) - - /* Set attributes if the key is not to be hidden */ - if (!hide) { -- privatekey_template[4].pValue = &falsevalue; -- privatekey_template[5].pValue = &truevalue; -+ private_template[4].pValue = &falsevalue; -+ private_template[5].pValue = &truevalue; -+ } -+ -+ if (keyclass == key_rsa || keyclass == key_ecc) -+ goto generate_keys; -+ -+ /* -+ * Special setup for Diffie-Hellman keys -+ */ -+ if (special != 0) { -+ public_template[DH_BASE].pValue = pk11_dh_bn2; -+ public_template[DH_BASE].ulValueLen = sizeof(pk11_dh_bn2); -+ if (bits == 768) { -+ public_template[DH_PRIME].pValue = pk11_dh_bn768; -+ public_template[DH_PRIME].ulValueLen = -+ sizeof(pk11_dh_bn768); -+ } else if (bits == 1024) { -+ public_template[DH_PRIME].pValue = pk11_dh_bn1024; -+ public_template[DH_PRIME].ulValueLen = -+ sizeof(pk11_dh_bn1024); -+ } else { -+ public_template[DH_PRIME].pValue = pk11_dh_bn1536; -+ public_template[DH_PRIME].ulValueLen = -+ sizeof(pk11_dh_bn1536); -+ } -+ param_attrcnt = 0; -+ goto generate_keys; -+ } -+ -+ /* Generate Domain parameters */ -+ rv = pkcs_C_GenerateKey(hSession, &dpmech, domain_template, -+ domain_attrcnt, &domainparams); -+ -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_GenerateKey: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_search; -+ } -+ -+ /* Get Domain parameters */ -+ rv = pkcs_C_GetAttributeValue(hSession, domainparams, -+ param_template, param_attrcnt); -+ -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_GetAttributeValue0: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_domain; -+ } -+ -+ /* Allocate space for parameter attributes */ -+ for (i = 0; i < param_attrcnt; i++) -+ param_template[i].pValue = malloc(param_template[i].ulValueLen); -+ -+ rv = pkcs_C_GetAttributeValue(hSession, domainparams, -+ dsa_param_template, DSA_PARAM_ATTRS); -+ -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_GetAttributeValue1: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_params; -+ } -+ -+ switch (keyclass) { -+ case key_dsa: -+ public_template[DSA_PRIME].pValue = -+ param_template[DSA_PARAM_PRIME].pValue; -+ public_template[DSA_PRIME].ulValueLen = -+ param_template[DSA_PARAM_PRIME].ulValueLen; -+ public_template[DSA_SUBPRIME].pValue = -+ param_template[DSA_PARAM_SUBPRIME].pValue; -+ public_template[DSA_SUBPRIME].ulValueLen = -+ param_template[DSA_PARAM_SUBPRIME].ulValueLen; -+ public_template[DSA_BASE].pValue = -+ param_template[DSA_PARAM_BASE].pValue; -+ public_template[DSA_BASE].ulValueLen = -+ param_template[DSA_PARAM_BASE].ulValueLen; -+ break; -+ case key_dh: -+ public_template[DH_PRIME].pValue = -+ param_template[DH_PARAM_PRIME].pValue; -+ public_template[DH_PRIME].ulValueLen = -+ param_template[DH_PARAM_PRIME].ulValueLen; -+ public_template[DH_BASE].pValue = -+ param_template[DH_PARAM_BASE].pValue; -+ public_template[DH_BASE].ulValueLen = -+ param_template[DH_PARAM_BASE].ulValueLen; -+ default: -+ break; - } - -+ generate_keys: - /* Generate Key pair for signing/verifying */ -- rv = C_GenerateKeyPair(hSession, &genmech, -- publickey_template, publickey_attrcnt, -- privatekey_template, privatekey_attrcnt, -+ rv = pkcs_C_GenerateKeyPair(hSession, &mech, -+ public_template, public_attrcnt, -+ private_template, private_attrcnt, - &publickey, &privatekey); - - if (rv != CKR_OK) { - fprintf(stderr, "C_GenerateKeyPair: Error = 0x%.8lX\n", rv); - error = 1; -+ } else if (!quiet) -+ printf("Key pair generation complete.\n"); -+ -+ exit_params: -+ /* Free parameter attributes */ -+ if (keyclass == key_dsa || keyclass == key_dh) -+ for (i = 0; i < param_attrcnt; i++) -+ free(param_template[i].pValue); -+ -+ exit_domain: -+ /* Destroy domain parameters */ -+ if (keyclass == key_dsa || (keyclass == key_dh && !special)) { -+ rv = pkcs_C_DestroyObject(hSession, domainparams); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_DestroyObject: Error = 0x%.8lX\n", rv); -+ error = 1; -+ } - } -- -+ - exit_search: -- rv = C_FindObjectsFinal(hSession); -+ rv = pkcs_C_FindObjectsFinal(hSession); - if (rv != CKR_OK) { - fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv); - error = 1; - } - - exit_session: -- (void)C_CloseSession(hSession); -- -- exit_program: -- (void)C_Finalize(NULL_PTR); -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); - - exit(error); - } -diff --git a/bin/pkcs11/pkcs11-keygen.docbook b/bin/pkcs11/pkcs11-keygen.docbook -index 7c4ba08..d62ba2f 100644 ---- a/bin/pkcs11/pkcs11-keygen.docbook -+++ b/bin/pkcs11/pkcs11-keygen.docbook -@@ -18,25 +18,26 @@ - --> - - -- -+ - -- Sep 18, 2009 -+ Feb 30, 2012 - - - -- pkcs11-keygen -+ pkcs11-ecgen - 8 - BIND9 - - - - pkcs11-keygen -- generate RSA keys on a PKCS#11 device -+ generate keys on a PKCS#11 device - - - - - 2009 -+ 2014 - Internet Systems Consortium, Inc. ("ISC") - - -@@ -44,14 +45,17 @@ - - - pkcs11-keygen -- -- -- -+ -a algorithm -+ - -- -b keysize -- -l label - -+ -+ - -+ -+ -+ -+ label - - - -@@ -59,8 +63,8 @@ - DESCRIPTION - - pkcs11-keygen causes a PKCS#11 device to generate -- a new RSA key pair with the specified and -- with bits of modulus. -+ a new key pair with the given (which must be -+ unique) and with bits of prime. - - - -@@ -68,83 +72,109 @@ - ARGUMENTS - - -- -P -+ -a algorithm - - -- Set the new private key to be non-sensitive and extractable. -- The allows the private key data to be read from the PKCS#11 -- device. The default is for private keys to be sensitive and -- non-extractable. -+ Specify the key algorithm class: Supported classes are RSA, -+ DSA, DH, and ECC. In addition to these strings, the -+ can be specified as a DNSSEC -+ signing algorithm that will be used with this key; for -+ example, NSEC3RSASHA1 maps to RSA, and ECDSAP256SHA256 maps -+ to ECC. The default class is "RSA". - - - - - -- -m module -+ -b keysize - - -- Specify the PKCS#11 provider module. This must be the full -- path to a shared library object implementing the PKCS#11 API -- for the device. -+ Create the key pair with bits of -+ prime. For ECC keys, the only valid values are 256 and 384, -+ and the default is 256. - - - - - -- -s slot -+ -e - - -- Open the session with the given PKCS#11 slot. The default is -- slot 0. -+ For RSA keys only, use a large exponent. - - - - - -- -e -+ -i id - - -- Use a large exponent. -+ Create key objects with id. The id is either -+ an unsigned short 2 byte or an unsigned long 4 byte number. - - - - - -- -b keysize -+ -m module - - -- Create the key pair with bits of -- modulus. -+ Specify the PKCS#11 provider module. This must be the full -+ path to a shared library object implementing the PKCS#11 API -+ for the device. -+ -+ -+ -+ -+ -+ -P -+ -+ -+ Set the new private key to be non-sensitive and extractable. -+ The allows the private key data to be read from the PKCS#11 -+ device. The default is for private keys to be sensitive and -+ non-extractable. - - - - - -- -l label -+ -p PIN - - -- Create key objects with the given label. -- This name must be unique. -+ Specify the PIN for the device. If no PIN is provided on -+ the command line, pkcs11-ecgen will -+ prompt for it. - - - - - -- -i id -+ -q - - -- Create key objects with id. The id is either -- an unsigned short 2 byte or an unsigned long 4 byte number. -+ Quiet mode: suppress unnecessary output. -+ -+ -+ -+ -+ -+ -S -+ -+ -+ For Diffie-Hellman (DH) keys only, use a special prime of -+ 768, 1024 or 1536 bit size and base (aka generator) 2. -+ If not specified, bit size will default to 1024. - - - - - -- -p PIN -+ -s slot - - -- Specify the PIN for the device. If no PIN is provided on the -- command line, pkcs11-keygen will prompt for it. -+ Open the session with the given PKCS#11 slot. The default is -+ slot 0. - - - -@@ -155,6 +185,12 @@ - SEE ALSO - - -+ pkcs11-rsagen3 -+ , -+ -+ pkcs11-dsagen3 -+ , -+ - pkcs11-list3 - , - -@@ -167,11 +203,6 @@ - - - -- CAVEAT -- Some PKCS#11 providers crash with big public exponent. -- -- -- - AUTHOR - Internet Systems Consortium - -diff --git a/bin/pkcs11/pkcs11-keygen.html b/bin/pkcs11/pkcs11-keygen.html -index 41378fc..c7fdecf 100644 ---- a/bin/pkcs11/pkcs11-keygen.html -+++ b/bin/pkcs11/pkcs11-keygen.html -@@ -18,36 +18,53 @@ - - - --pkcs11-keygen -+pkcs11-ecgen - - -
--
-+
-
-

Name

--

pkcs11-keygen — generate RSA keys on a PKCS#11 device

-+

pkcs11-keygen — generate keys on a PKCS#11 device

-
-
-

Synopsis

--

pkcs11-keygen [-P] [-m module] [-s slot] [-e] {-b keysize} {-l label} [-i id] [-p PIN]

-+

pkcs11-keygen {-a algorithm} [-b keysize] [-e] [-i id] [-m module] [-P] [-p PIN] [-q] [-S] [-s slot] {label}

-
-
--

DESCRIPTION

-+

DESCRIPTION

-

- pkcs11-keygen causes a PKCS#11 device to generate -- a new RSA key pair with the specified label and -- with keysize bits of modulus. -+ a new key pair with the given label (which must be -+ unique) and with keysize bits of prime. -

-
-
--

ARGUMENTS

-+

ARGUMENTS

-
--
-P
-+
-a algorithm
-

-- Set the new private key to be non-sensitive and extractable. -- The allows the private key data to be read from the PKCS#11 -- device. The default is for private keys to be sensitive and -- non-extractable. -+ Specify the key algorithm class: Supported classes are RSA, -+ DSA, DH, and ECC. In addition to these strings, the -+ algorithm can be specified as a DNSSEC -+ signing algorithm that will be used with this key; for -+ example, NSEC3RSASHA1 maps to RSA, and ECDSAP256SHA256 maps -+ to ECC. The default class is "RSA". -+

-+
-b keysize
-+

-+ Create the key pair with keysize bits of -+ prime. For ECC keys, the only valid values are 256 and 384, -+ and the default is 256. -+

-+
-e
-+

-+ For RSA keys only, use a large exponent. -+

-+
-i id
-+

-+ Create key objects with id. The id is either -+ an unsigned short 2 byte or an unsigned long 4 byte number. -

-
-m module
-

-@@ -55,51 +72,48 @@ - path to a shared library object implementing the PKCS#11 API - for the device. -

--
-s slot
--

-- Open the session with the given PKCS#11 slot. The default is -- slot 0. --

--
-e
-+
-P
-

-- Use a large exponent. -+ Set the new private key to be non-sensitive and extractable. -+ The allows the private key data to be read from the PKCS#11 -+ device. The default is for private keys to be sensitive and -+ non-extractable. -

--
-b keysize
-+
-p PIN
-

-- Create the key pair with keysize bits of -- modulus. -+ Specify the PIN for the device. If no PIN is provided on -+ the command line, pkcs11-ecgen will -+ prompt for it. -

--
-l label
-+
-q
-

-- Create key objects with the given label. -- This name must be unique. -+ Quiet mode: suppress unnecessary output. -

--
-i id
-+
-S
-

-- Create key objects with id. The id is either -- an unsigned short 2 byte or an unsigned long 4 byte number. -+ For Diffie-Hellman (DH) keys only, use a special prime of -+ 768, 1024 or 1536 bit size and base (aka generator) 2. -+ If not specified, bit size will default to 1024. -

--
-p PIN
-+
-s slot
-

-- Specify the PIN for the device. If no PIN is provided on the -- command line, pkcs11-keygen will prompt for it. -+ Open the session with the given PKCS#11 slot. The default is -+ slot 0. -

-
-
-
--

SEE ALSO

-+

SEE ALSO

-

-+ pkcs11-rsagen(3), -+ pkcs11-dsagen(3), - pkcs11-list(3), - pkcs11-destroy(3), - dnssec-keyfromlabel(3), -

-
-
--

CAVEAT

--

Some PKCS#11 providers crash with big public exponent.

--
--
--

AUTHOR

-+

AUTHOR

-

Internet Systems Consortium -

-
-diff --git a/bin/pkcs11/pkcs11-list.c b/bin/pkcs11/pkcs11-list.c -index 336bf41..bc6ad28 100644 ---- a/bin/pkcs11/pkcs11-list.c -+++ b/bin/pkcs11/pkcs11-list.c -@@ -52,74 +52,68 @@ - #include - #include - #include --#include "cryptoki.h" - --#ifdef WIN32 --#include "win32.c" --#else --#ifndef FORCE_STATIC_PROVIDER --#include "unix.c" --#endif --#endif -+#include -+#include -+#include -+ -+#include -+#include - - #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) - #define getpassphrase(x) getpass(x) - #endif - - int --main(int argc, char *argv[]) --{ -+main(int argc, char *argv[]) { -+ isc_result_t result; - CK_RV rv; - CK_SLOT_ID slot = 0; - CK_SESSION_HANDLE hSession; -- CK_UTF8CHAR *pin = NULL; - CK_BYTE attr_id[2]; - CK_OBJECT_HANDLE akey[50]; -+ pk11_context_t pctx; -+ char *lib_name = NULL; - char *label = NULL; -- int error = 0, public = 0, all = 0; -+ char *pin = NULL; -+ isc_boolean_t error = ISC_FALSE, logon = ISC_TRUE, all = ISC_FALSE; - unsigned int i = 0, id = 0; - int c, errflg = 0; - CK_ULONG ulObjectCount; - CK_ATTRIBUTE search_template[] = { - {CKA_ID, &attr_id, sizeof(attr_id)} - }; -- char *pk11_provider; -- extern char *optarg; -- extern int optopt; - -- pk11_provider = getenv("PKCS11_PROVIDER"); -- if (pk11_provider != NULL) -- pk11_libname = pk11_provider; -- -- while ((c = getopt(argc, argv, ":m:s:i:l:p:P")) != -1) { -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:i:l:p:P")) != -1) { - switch (c) { - case 'P': -- public = 1; -+ logon = ISC_FALSE; - break; - case 'm': -- pk11_libname = optarg; -+ lib_name = isc_commandline_argument; - break; - case 's': -- slot = atoi(optarg); -+ slot = atoi(isc_commandline_argument); - break; - case 'i': -- id = atoi(optarg); -+ id = atoi(isc_commandline_argument); - id &= 0xffff; - break; - case 'l': -- label = optarg; -+ label = isc_commandline_argument; - break; - case 'p': -- pin = (CK_UTF8CHAR *)optarg; -+ pin = isc_commandline_argument; - break; - case ':': - fprintf(stderr, "Option -%c requires an operand\n", -- optopt); -+ isc_commandline_option); - errflg++; - break; - case '?': - default: -- fprintf(stderr, "Unrecognised option: -%c\n", optopt); -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); - errflg++; - } - } -@@ -132,7 +126,7 @@ main(int argc, char *argv[]) - } - - if (!id && (label == NULL)) -- all = 1; -+ all = ISC_TRUE; - - if (slot) - printf("slot %lu\n", slot); -@@ -148,41 +142,37 @@ main(int argc, char *argv[]) - search_template[0].ulValueLen = strlen(label); - } - -+ pk11_result_register(); -+ - /* Initialize the CRYPTOKI library */ -- rv = C_Initialize(NULL_PTR); -- if (rv != CKR_OK) { -- if (rv == 0xfe) -- fprintf(stderr, -- "Can't load or link module \"%s\"\n", -- pk11_libname); -- else -- fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv); -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (logon && pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, OP_ANY, ISC_FALSE, ISC_FALSE, -+ logon, pin, slot); -+ if (result == PK11_R_NORANDOMSERVICE || -+ result == PK11_R_NODIGESTSERVICE || -+ result == PK11_R_NOAESSERVICE) { -+ fprintf(stderr, "Warning: %s\n", isc_result_totext(result)); -+ fprintf(stderr, "This HSM will not work with BIND 9 " -+ "using native PKCS#11.\n"); -+ } else if (result != ISC_R_SUCCESS) { -+ fprintf(stderr, "Unrecoverable error initializing " -+ "PKCS#11: %s\n", isc_result_totext(result)); -+ fprintf(stderr, "Unrecoverable error initializing " -+ "PKCS#11: %s\n", isc_result_totext(result)); - exit(1); - } - -- /* Open a session on the slot found */ -- rv = C_OpenSession(slot, CKF_SERIAL_SESSION, -- NULL_PTR, NULL_PTR, &hSession); -- if (rv != CKR_OK) { -- fprintf(stderr, "C_OpenSession: Error = 0x%.8lX\n", rv); -- error = 1; -- goto exit_program; -- } -+ if (pin != NULL) -+ memset(pin, 0, strlen(pin)); - -- /* Login to the Token (Keystore) */ -- if (!public) { -- if (pin == NULL) -- pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: "); -- rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin)); -- memset(pin, 0, strlen((char *)pin)); -- if (rv != CKR_OK) { -- fprintf(stderr, "C_Login: Error = 0x%.8lX\n", rv); -- error = 1; -- goto exit_session; -- } -- } -+ hSession = pctx.session; - -- rv = C_FindObjectsInit(hSession, search_template, all ? 0 : 1); -+ rv = pkcs_C_FindObjectsInit(hSession, search_template, all ? 0 : 1); - if (rv != CKR_OK) { - fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv); - error = 1; -@@ -191,7 +181,7 @@ main(int argc, char *argv[]) - - ulObjectCount = 1; - while (ulObjectCount) { -- rv = C_FindObjects(hSession, akey, 50, &ulObjectCount); -+ rv = pkcs_C_FindObjects(hSession, akey, 50, &ulObjectCount); - if (rv != CKR_OK) { - fprintf(stderr, - "C_FindObjects: Error = 0x%.8lX\n", -@@ -215,7 +205,7 @@ main(int argc, char *argv[]) - memset(labelbuf, 0, sizeof(labelbuf)); - memset(idbuf, 0, sizeof(idbuf)); - -- rv = C_GetAttributeValue(hSession, akey[i], -+ rv = pkcs_C_GetAttributeValue(hSession, akey[i], - template, 3); - if (rv != CKR_OK) { - fprintf(stderr, -@@ -260,17 +250,15 @@ main(int argc, char *argv[]) - } - - exit_search: -- rv = C_FindObjectsFinal(hSession); -+ rv = pkcs_C_FindObjectsFinal(hSession); - if (rv != CKR_OK) { - fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv); - error = 1; - } - - exit_session: -- (void)C_CloseSession(hSession); -- -- exit_program: -- (void)C_Finalize(NULL_PTR); -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); - - exit(error); - } -diff --git a/bin/pkcs11/pkcs11-tokens.8 b/bin/pkcs11/pkcs11-tokens.8 -new file mode 100644 -index 0000000..7c2be83 ---- /dev/null -+++ b/bin/pkcs11/pkcs11-tokens.8 -@@ -0,0 +1,51 @@ -+.\" Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+.\" -+.\" Permission to use, copy, modify, and/or distribute this software for any -+.\" purpose with or without fee is hereby granted, provided that the above -+.\" copyright notice and this permission notice appear in all copies. -+.\" -+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+.\" PERFORMANCE OF THIS SOFTWARE. -+.\" -+.\" $Id$ -+.\" -+.hy 0 -+.ad l -+.\" Title: pkcs11\-tokens -+.\" Author: -+.\" Generator: DocBook XSL Stylesheets v1.71.1 -+.\" Date: August 25, 2013 -+.\" Manual: BIND9 -+.\" Source: BIND9 -+.\" -+.TH "PKCS11\-TOKENS" "8" "August 25, 2013" "BIND9" "BIND9" -+.\" disable hyphenation -+.nh -+.\" disable justification (adjust text to left margin only) -+.ad l -+.SH "NAME" -+pkcs11\-tokens \- list PKCS#11 available tokens -+.SH "SYNOPSIS" -+.HP 14 -+\fBpkcs11\-tokens\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] -+.SH "DESCRIPTION" -+.PP -+\fBpkcs11\-tokens\fR -+lists the PKCS#11 available tokens with defaults from the slot/token scan performed at application initialization. -+.SH "ARGUMENTS" -+.PP -+\-m \fImodule\fR -+.RS 4 -+Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device. -+.RE -+.SH "AUTHOR" -+.PP -+Internet Systems Consortium -+.SH "COPYRIGHT" -+Copyright \(co 2013 Internet Systems Consortium, Inc. ("ISC") -+.br -diff --git a/bin/pkcs11/pkcs11-tokens.c b/bin/pkcs11/pkcs11-tokens.c -new file mode 100644 -index 0000000..ff4e030 ---- /dev/null -+++ b/bin/pkcs11/pkcs11-tokens.c -@@ -0,0 +1,106 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+/* pkcs11-tokens [-m module] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ char *lib_name = NULL; -+ int c, errflg = 0; -+ isc_mem_t *mctx = NULL; -+ pk11_context_t pctx; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case ':': -+ fprintf(stderr, "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, "\tpkcs11-tokens [-m module]\n"); -+ exit(1); -+ } -+ -+ if (isc_mem_create(0, 0, &mctx) != ISC_R_SUCCESS) { -+ fprintf(stderr, "isc_mem_create() failed\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ result = pk11_get_session(&pctx, OP_ANY, ISC_FALSE, ISC_FALSE, -+ ISC_FALSE, NULL, 0); -+ if (result == PK11_R_NORANDOMSERVICE || -+ result == PK11_R_NODIGESTSERVICE || -+ result == PK11_R_NOAESSERVICE) { -+ fprintf(stderr, "Warning: %s\n", isc_result_totext(result)); -+ fprintf(stderr, "This HSM will not work with BIND 9 " -+ "using native PKCS#11.\n\n"); -+ } else if (result != ISC_R_SUCCESS) { -+ fprintf(stderr, "Unrecoverable error initializing " -+ "PKCS#11: %s\n", isc_result_totext(result)); -+ exit(1); -+ } -+ -+ pk11_dump_tokens(); -+ -+ if (pctx.handle != NULL) -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ isc_mem_destroy(&mctx); -+ -+ exit(0); -+} -diff --git a/bin/pkcs11/pkcs11-tokens.docbook b/bin/pkcs11/pkcs11-tokens.docbook -new file mode 100644 -index 0000000..44dc7cd ---- /dev/null -+++ b/bin/pkcs11/pkcs11-tokens.docbook -@@ -0,0 +1,86 @@ -+]> -+ -+ -+ -+ -+ -+ August 25, 2013 -+ -+ -+ -+ pkcs11-tokens -+ 8 -+ BIND9 -+ -+ -+ -+ pkcs11-tokens -+ list PKCS#11 available tokens -+ -+ -+ -+ -+ 2013 -+ Internet Systems Consortium, Inc. ("ISC") -+ -+ -+ -+ -+ -+ pkcs11-tokens -+ -+ -+ -+ -+ -+ DESCRIPTION -+ -+ pkcs11-tokens -+ lists the PKCS#11 available tokens with defaults from the slot/token -+ scan performed at application initialization. -+ -+ -+ -+ -+ ARGUMENTS -+ -+ -+ -m module -+ -+ -+ Specify the PKCS#11 provider module. This must be the full -+ path to a shared library object implementing the PKCS#11 API -+ for the device. -+ -+ -+ -+ -+ -+ -+ -+ AUTHOR -+ Internet Systems Consortium -+ -+ -+ -+ -diff --git a/bin/pkcs11/pkcs11-tokens.html b/bin/pkcs11/pkcs11-tokens.html -new file mode 100644 -index 0000000..45d7243 ---- /dev/null -+++ b/bin/pkcs11/pkcs11-tokens.html -@@ -0,0 +1,58 @@ -+ -+ -+ -+ -+ -+pkcs11-tokens -+ -+ -+
-+
-+
-+

Name

-+

pkcs11-tokens — list PKCS#11 available tokens

-+
-+
-+

Synopsis

-+

pkcs11-tokens [-m module]

-+
-+
-+

DESCRIPTION

-+

-+ pkcs11-tokens -+ lists the PKCS#11 available tokens with defaults from the slot/token -+ scan performed at application initialization. -+

-+
-+
-+

ARGUMENTS

-+
-+
-m module
-+

-+ Specify the PKCS#11 provider module. This must be the full -+ path to a shared library object implementing the PKCS#11 API -+ for the device. -+

-+
-+
-+
-+

AUTHOR

-+

Internet Systems Consortium -+

-+
-+
-+ -diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in -index f6100df..bc0657a 100644 ---- a/bin/rndc/Makefile.in -+++ b/bin/rndc/Makefile.in -@@ -45,7 +45,8 @@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ - LIBS = ${ISCLIBS} @LIBS@ - NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ - --RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} -+RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} \ -+ ${DNSDEPLIBS} ${ISCDEPLIBS} - - CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} - -diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in -index bc040a3..2020bf4 100644 ---- a/bin/tests/Makefile.in -+++ b/bin/tests/Makefile.in -@@ -42,7 +42,7 @@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ - LIBS = @LIBS@ - - SUBDIRS = atomic db dst master mem hashes names net rbt resolver \ -- sockaddr tasks timers system -+ sockaddr tasks timers system @PKCS11_TOOLS@ - - # Test programs that are built by default: - # cfg_test is needed for regenerating doc/misc/options -@@ -173,139 +173,139 @@ backtrace_test@EXEEXT@: backtrace_test_nosymtbl@EXEEXT@ - nsecify@EXEEXT@: nsecify.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsecify.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - byaddr_test@EXEEXT@: byaddr_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byaddr_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - byname_test@EXEEXT@: byname_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byname_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - lex_test@EXEEXT@: lex_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lex_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - lfsr_test@EXEEXT@: lfsr_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lfsr_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - log_test@EXEEXT@: log_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ log_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - name_test@EXEEXT@: name_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ name_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - hash_test@EXEEXT@: hash_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ hash_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - entropy_test@EXEEXT@: entropy_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - entropy2_test@EXEEXT@: entropy2_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy2_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - sock_test@EXEEXT@: sock_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sock_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - sym_test@EXEEXT@: sym_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sym_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - task_test@EXEEXT@: task_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ task_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - shutdown_test@EXEEXT@: shutdown_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ shutdown_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - timer_test@EXEEXT@: timer_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ timer_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - ratelimiter_test@EXEEXT@: ratelimiter_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ratelimiter_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - rbt_test@EXEEXT@: rbt_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rbt_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - rdata_test@EXEEXT@: rdata_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rdata_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - rwlock_test@EXEEXT@: rwlock_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rwlock_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - wire_test@EXEEXT@: wire_test.@O@ printmsg.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ wire_test.@O@ printmsg.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - master_test@EXEEXT@: master_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ master_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - db_test@EXEEXT@: db_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ db_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - compress_test@EXEEXT@: compress_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ compress_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - mempool_test@EXEEXT@: mempool_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ mempool_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - serial_test@EXEEXT@: serial_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ serial_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - zone_test@EXEEXT@: zone_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ zone_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - fsaccess_test@EXEEXT@: fsaccess_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ fsaccess_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - inter_test@EXEEXT@: inter_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ inter_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - keyboard_test@EXEEXT@: keyboard_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ keyboard_test.@O@ \ - ${ISCLIBS} ${LIBS} -- -+ - lwresconf_test@EXEEXT@: lwresconf_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwresconf_test.@O@ \ - ${LWRESLIBS} ${ISCLIBS} ${LIBS} -- -+ - lwres_test@EXEEXT@: lwres_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwres_test.@O@ \ -- ${LWRESLIBS} ${ISCLIBS} ${LIBS} -- --gxbn_test@EXEEXT@: gxbn_test.@O@ ${LWRESDEPLIBS} -+ ${LWRESLIBS} ${ISCLIBS} ${LIBS} -+ -+ gxbn_test@EXEEXT@: gxbn_test.@O@ ${LWRESDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxbn_test.@O@ \ - ${LWRESLIBS} ${ISCLIBS} ${LIBS} -- --gxba_test@EXEEXT@: gxba_test.@O@ ${LWRESDEPLIBS} -+ -+ gxba_test@EXEEXT@: gxba_test.@O@ ${LWRESDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxba_test.@O@ \ - ${LWRESLIBS} ${ISCLIBS} ${LIBS} -- -+ - sig0_test@EXEEXT@: sig0_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sig0_test.@O@ \ - ${DNSLIBS} ${ISCLIBS} ${LIBS} -- -+ - cfg_test@EXEEXT@: cfg_test.@O@ ${ISCCFGDEPLIBS} ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ cfg_test.@O@ \ - ${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS} ${LIBS} -diff --git a/bin/tests/dst/dst_test.c b/bin/tests/dst/dst_test.c -index bf305d8..240dc6f 100644 ---- a/bin/tests/dst/dst_test.c -+++ b/bin/tests/dst/dst_test.c -@@ -30,6 +30,7 @@ - #include /* Required for HP/UX (and others?) */ - - #include -+#include - #include - #include - -@@ -58,7 +59,8 @@ use(dst_key_t *key, isc_mem_t *mctx) { - isc_buffer_add(&databuf, strlen(data)); - isc_buffer_usedregion(&databuf, &datareg); - -- ret = dst_context_create(key, mctx, &ctx); -+ ret = dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_GENERAL, ISC_TRUE, &ctx); - if (ret != ISC_R_SUCCESS) { - printf("contextcreate(%d) returned: %s\n", dst_key_alg(key), - isc_result_totext(ret)); -@@ -78,7 +80,8 @@ use(dst_key_t *key, isc_mem_t *mctx) { - - isc_buffer_forward(&sigbuf, 1); - isc_buffer_remainingregion(&sigbuf, &sigreg); -- ret = dst_context_create(key, mctx, &ctx); -+ ret = dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_GENERAL, ISC_FALSE, &ctx); - if (ret != ISC_R_SUCCESS) { - printf("contextcreate(%d) returned: %s\n", dst_key_alg(key), - isc_result_totext(ret)); -diff --git a/bin/tests/dst/t_dst.c b/bin/tests/dst/t_dst.c -index e431c95..59c7835 100644 ---- a/bin/tests/dst/t_dst.c -+++ b/bin/tests/dst/t_dst.c -@@ -108,7 +108,8 @@ use(dst_key_t *key, isc_mem_t *mctx, isc_result_t exp_result, int *nfails) { - isc_buffer_add(&databuf, strlen(data)); - isc_buffer_usedregion(&databuf, &datareg); - -- ret = dst_context_create(key, mctx, &ctx); -+ ret = dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_GENERAL, ISC_TRUE, &ctx); - if (ret != exp_result) { - t_info("dst_context_create(%d) returned (%s) expected (%s)\n", - dst_key_alg(key), dst_result_totext(ret), -@@ -137,7 +138,8 @@ use(dst_key_t *key, isc_mem_t *mctx, isc_result_t exp_result, int *nfails) { - dst_context_destroy(&ctx); - - isc_buffer_remainingregion(&sigbuf, &sigreg); -- ret = dst_context_create(key, mctx, &ctx); -+ ret = dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_GENERAL, ISC_FALSE, &ctx); - if (ret != ISC_R_SUCCESS) { - t_info("dst_context_create(%d) returned (%s)\n", - dst_key_alg(key), dst_result_totext(ret)); -@@ -783,7 +785,9 @@ t2_sigchk(char *datapath, char *sigpath, char *keyname, - memset(sig, 0, sizeof(sig)); - isc_buffer_init(&sigbuf, sig, sizeof(sig)); - -- isc_result = dst_context_create(key, mctx, &ctx); -+ isc_result = dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_GENERAL, -+ ISC_TRUE, &ctx); - if (isc_result != ISC_R_SUCCESS) { - t_info("dst_context_create(%d) failed %s\n", - dst_result_totext(isc_result)); -@@ -849,7 +853,9 @@ t2_sigchk(char *datapath, char *sigpath, char *keyname, - if (strstr(expected_result, "!")) - exp_res = 1; - -- isc_result = dst_context_create(key, mctx, &ctx); -+ isc_result = dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_GENERAL, -+ ISC_FALSE, &ctx); - if (isc_result != ISC_R_SUCCESS) { - t_info("dst_context_create returned %s\n", - isc_result_totext(isc_result)); -diff --git a/bin/tests/pkcs11/Makefile.in b/bin/tests/pkcs11/Makefile.in -new file mode 100644 -index 0000000..0a6281f ---- /dev/null -+++ b/bin/tests/pkcs11/Makefile.in -@@ -0,0 +1,49 @@ -+# Copyright (C) 2009, 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_MAKE_INCLUDES@ -+ -+PROVIDER = @PKCS11_PROVIDER@ -+ -+CINCLUDES = ${ISC_INCLUDES} -+ -+CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\" -+ -+ISCLIBS = ../../../lib/isc/libisc.@A@ -+ -+LIBS = ${ISCLIBS} @LIBS@ -+ -+SUBDIRS = benchmarks -+ -+TARGETS = pkcs11-md5sum@EXEEXT@ pkcs11-hmacmd5@EXEEXT@ -+SRCS = pkcs11-md5sum.c pkcs11-hmacmd5.c -+ -+@BIND9_MAKE_RULES@ -+ -+pkcs11-md5sum@EXEEXT@: @srcdir@/pkcs11-md5sum.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@ @srcdir@/pkcs11-md5sum.c ${LIBS} -+ -+pkcs11-hmacmd5@EXEEXT@: @srcdir@/pkcs11-hmacmd5.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@ @srcdir@/pkcs11-hmacmd5.c ${LIBS} -+ -+test: -+ -+clean distclean:: -+ rm -f ${TARGETS} -diff --git a/bin/tests/pkcs11/benchmarks/Makefile.in b/bin/tests/pkcs11/benchmarks/Makefile.in -new file mode 100644 -index 0000000..cd0347c ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/Makefile.in -@@ -0,0 +1,79 @@ -+# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id$ -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_MAKE_INCLUDES@ -+ -+PROVIDER = @PKCS11_PROVIDER@ -+ -+CINCLUDES = ${ISC_INCLUDES} -+ -+CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\" -+ -+ISCLIBS = ../../../../lib/isc/libisc.@A@ -+ -+LIBS = ${ISCLIBS} @LIBS@ -+ -+SUBDIRS = -+ -+TARGETS = session@EXEEXT@ login@EXEEXT@ random@EXEEXT@ \ -+ sha1@EXEEXT@ create@EXEEXT@ find@EXEEXT@ \ -+ pubrsa@EXEEXT@ privrsa@EXEEXT@ genrsa@EXEEXT@ \ -+ sign@EXEEXT@ verify@EXEEXT@ -+ -+SRCS = session.c login.c random.c sha1.c create.c find.c \ -+ pubrsa.c privrsa.c genrsa.c sign.c verify.c -+ -+@BIND9_MAKE_RULES@ -+ -+session@EXEEXT@: @srcdir@/session.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/session.c ${LIBS} -+ -+login@EXEEXT@: @srcdir@/login.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/login.c ${LIBS} -+ -+random@EXEEXT@: @srcdir@/random.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/random.c ${LIBS} -+ -+sha1@EXEEXT@: @srcdir@/sha1.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/sha1.c ${LIBS} -+ -+create@EXEEXT@: @srcdir@/create.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/create.c ${LIBS} -+ -+find@EXEEXT@: @srcdir@/find.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/find.c ${LIBS} -+ -+pubrsa@EXEEXT@: @srcdir@/pubrsa.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/pubrsa.c ${LIBS} -+ -+privrsa@EXEEXT@: @srcdir@/privrsa.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/privrsa.c ${LIBS} -+ -+genrsa@EXEEXT@: @srcdir@/genrsa.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/genrsa.c ${LIBS} -+ -+sign@EXEEXT@: @srcdir@/sign.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/sign.c ${LIBS} -+ -+verify@EXEEXT@: @srcdir@/verify.c -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/verify.c ${LIBS} -+ -+clean distclean:: -+ rm -f ${TARGETS} -diff --git a/bin/tests/pkcs11/benchmarks/create.c b/bin/tests/pkcs11/benchmarks/create.c -new file mode 100644 -index 0000000..d0d8c77 ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/create.c -@@ -0,0 +1,260 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* create [-m module] [-s $slot] [-p pin] [-t] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+CK_BYTE buf[1024]; -+char label[16]; -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_OBJECT_HANDLE *hKey; -+ CK_OBJECT_CLASS kClass = CKO_DATA; -+ CK_ULONG len = sizeof(buf); -+ CK_ATTRIBUTE kTemplate[] = -+ { -+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) }, -+ { CKA_VALUE, buf, (CK_ULONG) sizeof(buf) } -+ }; -+ pk11_context_t pctx; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ int ontoken = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 't': -+ ontoken = 1; -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tcreate [-m module] [-s slot] [-t] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Allocate hanles */ -+ hKey = (CK_SESSION_HANDLE *) -+ malloc(count * sizeof(CK_SESSION_HANDLE)); -+ if (hKey == NULL) { -+ perror("malloc"); -+ exit(1); -+ } -+ for (i = 0; i < count; i++) -+ hKey[i] = CK_INVALID_HANDLE; -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, OP_ANY, ISC_TRUE, ISC_TRUE, -+ ISC_TRUE, (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NODIGESTSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ /* Randomize the buffer */ -+ rv = pkcs_C_GenerateRandom(hSession, buf, len); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv); -+ goto exit_objects; -+ } -+ -+ if (ontoken) -+ kTemplate[1].pValue = &truevalue; -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_objects; -+ } -+ -+ for (i = 0; i < count; i++) { -+ (void) snprintf(label, sizeof(label), "obj%u", i); -+ kTemplate[3].ulValueLen = strlen(label); -+ rv = pkcs_C_CreateObject(hSession, kTemplate, 5, &hKey[i]); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_CreateObject[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ if (i == 0) -+ goto exit_objects; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_objects; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u created objects in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g created objects/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_objects: -+ for (i = 0; i < count; i++) { -+ /* Destroy objects */ -+ if (hKey[i] == CK_INVALID_HANDLE) -+ continue; -+ rv = pkcs_C_DestroyObject(hSession, hKey[i]); -+ if ((rv != CKR_OK) && !errflg) { -+ fprintf(stderr, -+ "C_DestroyObject[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ errflg = 1; -+ } -+ } -+ -+ free(hKey); -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/find.c b/bin/tests/pkcs11/benchmarks/find.c -new file mode 100644 -index 0000000..e22b17e ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/find.c -@@ -0,0 +1,227 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* find [-m module] [-s $slot] [-p pin] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+CK_BYTE label[] = "foo??bar!!"; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_ATTRIBUTE sTemplate[] = -+ { -+ { CKA_LABEL, label, (CK_ULONG) sizeof(label) }, -+ }; -+ CK_OBJECT_HANDLE sKey = CK_INVALID_HANDLE; -+ CK_ULONG found = 0; -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_RSA; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:n:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tfind [-m module] [-s slot] [-p pin] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_FALSE, -+ ISC_TRUE, (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NODIGESTSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_objects; -+ } -+ -+ for (i = 0; !error && (i < count); i++) { -+ rv = pkcs_C_FindObjectsInit(hSession, sTemplate, 1); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_FindObjectsInit[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ break; -+ } -+ -+ rv = pkcs_C_FindObjects(hSession, &sKey, 1, &found); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_FindObjects[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ /* no break here! */ -+ } -+ -+ rv = pkcs_C_FindObjectsFinal(hSession); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_FindObjectsFinal[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_objects; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u object searches in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g object searches/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_objects: -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/genrsa.c b/bin/tests/pkcs11/benchmarks/genrsa.c -new file mode 100644 -index 0000000..e9d3c2a ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/genrsa.c -@@ -0,0 +1,295 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* genrsa [-m module] [-s $slot] [-p pin] [-t] [-b bits] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 }; -+ CK_OBJECT_HANDLE *pubKey; -+ CK_OBJECT_HANDLE *privKey; -+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; -+ CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE kType = CKK_RSA; -+ CK_ULONG bits = 1024; -+ CK_BYTE exponent[] = { 0x01, 0x00, 0x01 }; -+ CK_ATTRIBUTE pubTemplate[] = -+ { -+ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, -+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_MODULUS_BITS, &bits, (CK_ULONG) sizeof(bits) }, -+ { CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) } -+ }; -+ CK_ATTRIBUTE privTemplate[] = -+ { -+ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, -+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ }; -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_RSA; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ int ontoken = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tb:n:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case 't': -+ ontoken = 1; -+ break; -+ case 'b': -+ bits = (CK_ULONG)atoi(isc_commandline_argument); -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tgenrsa [-m module] [-s slot] [-p pin] " -+ "[-t] [-b bits] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Allocate hanles */ -+ pubKey = (CK_SESSION_HANDLE *) -+ malloc(count * sizeof(CK_SESSION_HANDLE)); -+ if (pubKey == NULL) { -+ perror("malloc"); -+ exit(1); -+ } -+ privKey = (CK_SESSION_HANDLE *) -+ malloc(count * sizeof(CK_SESSION_HANDLE)); -+ if (privKey == NULL) { -+ free(pubKey); -+ perror("malloc"); -+ exit(1); -+ } -+ for (i = 0; i < count; i++) { -+ pubKey[i] = CK_INVALID_HANDLE; -+ privKey[i] = CK_INVALID_HANDLE; -+ } -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE, -+ ISC_TRUE, (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NODIGESTSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ if (ontoken) { -+ pubTemplate[2].pValue = &truevalue; -+ privTemplate[2].pValue = &truevalue; -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_keys; -+ } -+ -+ for (i = 0; i < count; i++) { -+ rv = pkcs_C_GenerateKeyPair(hSession, &mech, -+ pubTemplate, 7, -+ privTemplate, 5, -+ &pubKey[i], &privKey[i]); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_GenerateKeyPair[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ if (i == 0) -+ goto exit_keys; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_keys; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u generated RSA in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g generated RSA/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_keys: -+ for (i = 0; i < count; i++) { -+ /* Destroy keys */ -+ if (pubKey[i] == CK_INVALID_HANDLE) -+ goto destroy_priv; -+ rv = pkcs_C_DestroyObject(hSession, pubKey[i]); -+ if ((rv != CKR_OK) && !errflg) { -+ fprintf(stderr, -+ "C_DestroyObject[pub%u]: Error = 0x%.8lX\n", -+ i, rv); -+ errflg = 1; -+ } -+ destroy_priv: -+ if (privKey[i] == CK_INVALID_HANDLE) -+ continue; -+ rv = pkcs_C_DestroyObject(hSession, privKey[i]); -+ if ((rv != CKR_OK) && !errflg) { -+ fprintf(stderr, -+ "C_DestroyObject[priv%u]: Error = 0x%.8lX\n", -+ i, rv); -+ errflg = 1; -+ } -+ } -+ -+ free(pubKey); -+ free(privKey); -+ -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/login.c b/bin/tests/pkcs11/benchmarks/login.c -new file mode 100644 -index 0000000..fe597fa ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/login.c -@@ -0,0 +1,249 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* login [-m module] [-s $slot] [-p pin] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+int -+main(int argc, char *argv[]) { -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE *hSession; -+ CK_UTF8CHAR *pin = NULL; -+ char *lib_name = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ unsigned int count = 1000; -+ unsigned int i, j; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:n:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'p': -+ pin = (CK_UTF8CHAR *)isc_commandline_argument; -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tlogin [-m module] [-s slot] [-p pin] [-n count]\n"); -+ exit(1); -+ } -+ -+ /* allocate sessions */ -+ hSession = (CK_SESSION_HANDLE *) -+ malloc(count * sizeof(CK_SESSION_HANDLE)); -+ if (hSession == NULL) { -+ perror("malloc"); -+ exit(1); -+ } -+ for (i = 0; i < count; i++) -+ hSession[i] = CK_INVALID_HANDLE; -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (pin == NULL) -+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: "); -+ -+ rv = pkcs_C_Initialize(NULL_PTR); -+ if (rv != CKR_OK) { -+ if (rv == 0xfe) -+ fprintf(stderr, -+ "Can't load or link module \"%s\"\n", -+ pk11_get_lib_name()); -+ else -+ fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv); -+ free(hSession); -+ exit(1); -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_program; -+ } -+ -+ /* loop */ -+ for (i = 0; i < count; i++) { -+ /* Open sessions */ -+ rv = pkcs_C_OpenSession(slot, CKF_SERIAL_SESSION, -+ NULL_PTR, NULL_PTR, &hSession[i]); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_OpenSession[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ if (i == 0) -+ goto exit_program; -+ break; -+ } -+ -+ /* Logon */ -+ rv = pkcs_C_Login(hSession[i], CKU_USER, -+ pin, strlen((char *)pin)); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_Login[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ if (i == 0) -+ goto exit_program; -+ break; -+ } -+ -+ /* Logoff */ -+ rv = pkcs_C_Logout(hSession[i]); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_Logout[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ if (i == 0) -+ goto exit_program; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_program; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u logins in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g logins/s\n", -+ i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ for (j = 0; j < i; j++) { -+ if (hSession[j] == CK_INVALID_HANDLE) -+ continue; -+ /* Close sessions */ -+ rv = pkcs_C_CloseSession(hSession[j]); -+ if ((rv != CKR_OK) && !errflg) { -+ fprintf(stderr, -+ "C_CloseSession[%u]: Error = 0x%.8lX\n", -+ j, rv); -+ errflg = 1; -+ } -+ } -+ -+ exit_program: -+ free(hSession); -+ -+ rv = pkcs_C_Finalize(NULL_PTR); -+ if (rv != CKR_OK) -+ fprintf(stderr, "C_Finalize: Error = 0x%.8lX\n", rv); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/privrsa.c b/bin/tests/pkcs11/benchmarks/privrsa.c -new file mode 100644 -index 0000000..c50d8d2 ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/privrsa.c -@@ -0,0 +1,360 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* privrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+CK_BYTE modulus[] = { -+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99, -+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b, -+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90, -+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f, -+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96, -+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5, -+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b, -+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd, -+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08, -+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79, -+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45, -+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7, -+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd, -+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d, -+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f, -+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34, -+ 0xbf -+}; -+CK_BYTE pubexp[] = { 0x01, 0x00, 0x01 }; -+CK_BYTE privexp[] = { -+ 0x00, 0xae, 0x02, 0xf1, 0x47, 0xa8, 0x07, 0x02, -+ 0xb8, 0xf1, 0xd6, 0x92, 0x03, 0xee, 0x50, 0x33, -+ 0xab, 0x67, 0x9e, 0x3b, 0xb1, 0x57, 0xc7, 0x3e, -+ 0xc4, 0x86, 0x46, 0x61, 0xf1, 0xf8, 0xb6, 0x63, -+ 0x9f, 0x91, 0xe6, 0x3f, 0x44, 0xb8, 0x77, 0x1b, -+ 0xbe, 0x4c, 0x3c, 0xb8, 0x9f, 0xf7, 0x45, 0x7d, -+ 0xbf, 0x4f, 0xef, 0x3b, 0xcc, 0xda, 0x1a, 0x4e, -+ 0x34, 0xa8, 0x40, 0xea, 0x51, 0x72, 0x8a, 0xea, -+ 0x47, 0x06, 0x04, 0xd0, 0x62, 0x31, 0xa0, 0x6c, -+ 0x09, 0x60, 0xf9, 0xc7, 0x95, 0x88, 0x4a, 0xd7, -+ 0x19, 0xce, 0x89, 0x08, 0x87, 0x14, 0xef, 0xcc, -+ 0x0a, 0xef, 0x72, 0xb9, 0x21, 0xf5, 0xf0, 0xcd, -+ 0x6d, 0xe5, 0xfa, 0x15, 0x7f, 0xae, 0x33, 0x9f, -+ 0x26, 0xac, 0x2e, 0x52, 0x02, 0x07, 0xfb, 0x1d, -+ 0x4b, 0xec, 0x9a, 0x6b, 0x3b, 0x26, 0x1f, 0x52, -+ 0xfc, 0x47, 0xf8, 0x66, 0x33, 0xfa, 0x50, 0x6c, -+ 0x41 -+}; -+CK_BYTE prime1[] = { -+ 0x00, 0xe8, 0x98, 0xeb, 0xa1, 0xf0, 0xce, 0xde, -+ 0xc2, 0x74, 0x01, 0x18, 0x2b, 0xd3, 0x8f, 0x58, -+ 0xcd, 0xe9, 0x8e, 0x97, 0xbe, 0xfe, 0xe8, 0x6f, -+ 0xd6, 0x0c, 0x0a, 0x47, 0xf8, 0x56, 0x84, 0x36, -+ 0x15, 0xe6, 0x75, 0x1c, 0x69, 0x48, 0x8b, 0xf5, -+ 0x0f, 0x84, 0xd2, 0x60, 0x8b, 0xa2, 0x2a, 0xa1, -+ 0xeb, 0xed, 0xbe, 0x2d, 0xe9, 0x41, 0x0b, 0xed, -+ 0x17, 0x7c, 0xd3, 0xa6, 0x35, 0x6e, 0xa6, 0xd8, -+ 0x21 -+}; -+CK_BYTE prime2[] = { -+ 0x00, 0xca, 0x15, 0x6a, 0x43, 0x5e, 0x83, 0xc9, -+ 0x09, 0xeb, 0x14, 0x1e, 0x46, 0x46, 0x97, 0xfa, -+ 0xfa, 0x3c, 0x61, 0x7e, 0xc1, 0xf8, 0x8c, 0x5e, -+ 0xcb, 0xbf, 0xe4, 0xb9, 0x78, 0x7f, 0x4f, 0xab, -+ 0x82, 0x15, 0x53, 0xaa, 0x04, 0xee, 0x11, 0x21, -+ 0x2e, 0x23, 0x08, 0xa0, 0x14, 0x6d, 0x3a, 0x88, -+ 0xe6, 0xf8, 0xbe, 0x61, 0x38, 0x99, 0xca, 0x36, -+ 0x0d, 0x3e, 0x42, 0x0f, 0x63, 0x4d, 0x73, 0xf0, -+ 0xdf -+}; -+CK_BYTE exp_1[] = { -+ 0x66, 0x2d, 0xb7, 0x65, 0xbe, 0x99, 0xc2, 0x35, -+ 0xfe, 0x2b, 0xf4, 0xe8, 0x5b, 0xd9, 0xdf, 0x13, -+ 0x26, 0x04, 0xe4, 0x18, 0x9d, 0x76, 0x92, 0x9a, -+ 0x9f, 0x53, 0x6c, 0xe6, 0x65, 0x6b, 0x53, 0x2f, -+ 0x2f, 0xbc, 0x46, 0xac, 0xe1, 0x97, 0xca, 0x21, -+ 0xf5, 0x21, 0x4e, 0x14, 0x49, 0x3b, 0x1d, 0x42, -+ 0xbd, 0x80, 0x0c, 0x3f, 0x29, 0xba, 0x09, 0x7f, -+ 0x85, 0xf0, 0x9c, 0x55, 0x60, 0xb4, 0x9e, 0xc1 -+}; -+CK_BYTE exp_2[] = { -+ 0x00, 0x87, 0x22, 0x74, 0xf1, 0xe2, 0x15, 0x3c, -+ 0x6d, 0xde, 0x7e, 0x90, 0x94, 0x2c, 0x06, 0xdb, -+ 0xb5, 0x54, 0x85, 0x59, 0xcf, 0x7a, 0x56, 0xdb, -+ 0xd9, 0x62, 0x54, 0x20, 0x56, 0xdc, 0xc3, 0xb9, -+ 0x0b, 0xff, 0x18, 0xf8, 0x7b, 0xdd, 0x7b, 0x24, -+ 0xf6, 0x06, 0x45, 0x71, 0x4e, 0xd7, 0x90, 0x2a, -+ 0x16, 0x52, 0x46, 0x75, 0x1a, 0xf5, 0x74, 0x8c, -+ 0x5a, 0xa4, 0xc4, 0x66, 0x27, 0xe0, 0x96, 0x64, -+ 0x7f -+}; -+CK_BYTE coeff[] = { -+ 0x00, 0xd0, 0x1f, 0xb3, 0x47, 0x40, 0x93, 0x8b, -+ 0x99, 0xd7, 0xb5, 0xc6, 0x09, 0x82, 0x65, 0x94, -+ 0x9d, 0x56, 0x0a, 0x05, 0x55, 0x7d, 0x93, 0x04, -+ 0xa4, 0x26, 0xee, 0x42, 0x86, 0xa3, 0xf1, 0xd5, -+ 0x7a, 0x42, 0x84, 0x3c, 0x21, 0x96, 0x9a, 0xd9, -+ 0x36, 0xd4, 0x62, 0x01, 0xb0, 0x8b, 0x77, 0xe5, -+ 0xcc, 0x1b, 0xd2, 0x12, 0xd2, 0x9c, 0x89, 0x67, -+ 0x0c, 0x00, 0x09, 0x56, 0x8c, 0x33, 0x57, 0xf9, -+ 0x8c -+}; -+ -+char label[16]; -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_OBJECT_HANDLE *hKey; -+ CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE kType = CKK_RSA; -+ CK_ATTRIBUTE kTemplate[] = -+ { -+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) }, -+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) }, -+ { CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG) sizeof(pubexp) }, -+ { CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG) sizeof(privexp) }, -+ { CKA_PRIME_1, prime1, (CK_ULONG) sizeof(prime1) }, -+ { CKA_PRIME_2, prime2, (CK_ULONG) sizeof(prime2) }, -+ { CKA_EXPONENT_1, exp_1, (CK_ULONG) sizeof(exp_1) }, -+ { CKA_EXPONENT_2, exp_2, (CK_ULONG) sizeof(exp_2) }, -+ { CKA_COEFFICIENT, coeff, (CK_ULONG) sizeof(coeff) } -+ }; -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_RSA; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ int ontoken = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case 't': -+ ontoken = 1; -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tprivrsa [-m module] [-s slot] [-p pin] " -+ "[-t] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Allocate hanles */ -+ hKey = (CK_SESSION_HANDLE *) -+ malloc(count * sizeof(CK_SESSION_HANDLE)); -+ if (hKey == NULL) { -+ perror("malloc"); -+ exit(1); -+ } -+ for (i = 0; i < count; i++) -+ hKey[i] = CK_INVALID_HANDLE; -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE, -+ ISC_TRUE, (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NODIGESTSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ free(hKey); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ if (ontoken) -+ kTemplate[2].pValue = &truevalue; -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_objects; -+ } -+ -+ for (i = 0; i < count; i++) { -+ (void) snprintf(label, sizeof(label), "obj%u", i); -+ kTemplate[4].ulValueLen = strlen(label); -+ rv = pkcs_C_CreateObject(hSession, kTemplate, 14, &hKey[i]); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_CreateObject[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ if (i == 0) -+ goto exit_objects; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_objects; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u private RSA keys in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g private RSA keys/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_objects: -+ for (i = 0; i < count; i++) { -+ /* Destroy objects */ -+ if (hKey[i] == CK_INVALID_HANDLE) -+ continue; -+ rv = pkcs_C_DestroyObject(hSession, hKey[i]); -+ if ((rv != CKR_OK) && !errflg) { -+ fprintf(stderr, -+ "C_DestroyObject[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ errflg = 1; -+ } -+ } -+ -+ free(hKey); -+ -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/pubrsa.c b/bin/tests/pkcs11/benchmarks/pubrsa.c -new file mode 100644 -index 0000000..b27a999 ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/pubrsa.c -@@ -0,0 +1,281 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* pubrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+CK_BYTE modulus[] = { -+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99, -+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b, -+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90, -+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f, -+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96, -+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5, -+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b, -+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd, -+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08, -+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79, -+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45, -+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7, -+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd, -+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d, -+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f, -+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34, -+ 0xbf -+}; -+CK_BYTE exponent[] = { 0x01, 0x00, 0x01 }; -+ -+char label[16]; -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_OBJECT_HANDLE *hKey; -+ CK_OBJECT_CLASS kClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE kType = CKK_RSA; -+ CK_ATTRIBUTE kTemplate[] = -+ { -+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) }, -+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) }, -+ { CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) } -+ }; -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_RSA; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ int ontoken = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case 't': -+ ontoken = 1; -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tpubrsa [-m module] [-s slot] [-p pin] " -+ "[-t] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Allocate hanles */ -+ hKey = (CK_SESSION_HANDLE *) -+ malloc(count * sizeof(CK_SESSION_HANDLE)); -+ if (hKey == NULL) { -+ perror("malloc"); -+ exit(1); -+ } -+ for (i = 0; i < count; i++) -+ hKey[i] = CK_INVALID_HANDLE; -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE, -+ ISC_TRUE, (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NODIGESTSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ free(hKey); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ if (ontoken) -+ kTemplate[2].pValue = &truevalue; -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_objects; -+ } -+ -+ for (i = 0; i < count; i++) { -+ (void) snprintf(label, sizeof(label), "obj%u", i); -+ kTemplate[4].ulValueLen = strlen(label); -+ rv = pkcs_C_CreateObject(hSession, kTemplate, 8, &hKey[i]); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_CreateObject[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ if (i == 0) -+ goto exit_objects; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_objects; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u public RSA keys in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g public RSA keys/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_objects: -+ for (i = 0; i < count; i++) { -+ /* Destroy objects */ -+ if (hKey[i] == CK_INVALID_HANDLE) -+ continue; -+ rv = pkcs_C_DestroyObject(hSession, hKey[i]); -+ if ((rv != CKR_OK) && !errflg) { -+ fprintf(stderr, -+ "C_DestroyObject[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ errflg = 1; -+ } -+ } -+ -+ free(hKey); -+ -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/random.c b/bin/tests/pkcs11/benchmarks/random.c -new file mode 100644 -index 0000000..10d6db0 ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/random.c -@@ -0,0 +1,192 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* random [-m module] [-s $slot] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+CK_BYTE buf[1024]; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_ULONG len = sizeof(buf); -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_RAND; -+ char *lib_name = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\trandom [-m module] [-s slot] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_FALSE, -+ ISC_FALSE, NULL, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NODIGESTSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ hSession = pctx.session; -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_session; -+ } -+ -+ for (i = 0; i < count; i++) { -+ /* Get random bytes */ -+ rv = pkcs_C_GenerateRandom(hSession, buf, len); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_GenerateRandom[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_session; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%uK random bytes in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g random bytes/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_session: -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/session.c b/bin/tests/pkcs11/benchmarks/session.c -new file mode 100644 -index 0000000..74bd63a ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/session.c -@@ -0,0 +1,213 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* session [-m module] [-s $slot] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+int -+main(int argc, char *argv[]) { -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE *hSession; -+ char *lib_name = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tsession [-m module] [-s slot] [-n count]\n"); -+ exit(1); -+ } -+ -+ /* Allocate sessions */ -+ hSession = (CK_SESSION_HANDLE *) -+ malloc(count * sizeof(CK_SESSION_HANDLE)); -+ if (hSession == NULL) { -+ perror("malloc"); -+ exit(1); -+ } -+ for (i = 0; i < count; i++) -+ hSession[i] = CK_INVALID_HANDLE; -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ rv = pkcs_C_Initialize(NULL_PTR); -+ if (rv != CKR_OK) { -+ if (rv == 0xfe) -+ fprintf(stderr, -+ "Can't load or link module \"%s\"\n", -+ pk11_get_lib_name()); -+ else -+ fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv); -+ free(hSession); -+ exit(1); -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_program; -+ } -+ -+ /* loop */ -+ for (i = 0; i < count; i++) { -+ /* Open sessions */ -+ rv = pkcs_C_OpenSession(slot, CKF_SERIAL_SESSION, -+ NULL_PTR, NULL_PTR, &hSession[i]); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_OpenSession[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ if (i == 0) -+ goto exit_program; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_program; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u sessions in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g sessions/s\n", -+ i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ for (i = 0; i < count; i++) { -+ /* Close sessions */ -+ if (hSession[i] == CK_INVALID_HANDLE) -+ continue; -+ rv = pkcs_C_CloseSession(hSession[i]); -+ if ((rv != CKR_OK) && !errflg) { -+ fprintf(stderr, -+ "C_CloseSession[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ errflg = 1; -+ } -+ } -+ -+ exit_program: -+ free(hSession); -+ -+ rv = pkcs_C_Finalize(NULL_PTR); -+ if (rv != CKR_OK) -+ fprintf(stderr, "C_Finalize: Error = 0x%.8lX\n", rv); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/sha1.c b/bin/tests/pkcs11/benchmarks/sha1.c -new file mode 100644 -index 0000000..756aadb ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/sha1.c -@@ -0,0 +1,214 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* sha1 [-m module] [-s $slot] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+CK_BYTE buf[1024]; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_MECHANISM mech = { CKM_SHA_1, NULL, 0 }; -+ CK_ULONG len = sizeof(buf); -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_DIGEST; -+ char *lib_name = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tssha1 [-m module] [-s slot] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_FALSE, -+ ISC_FALSE, NULL, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ hSession = pctx.session; -+ -+ /* Randomize the buffer */ -+ rv = pkcs_C_GenerateRandom(hSession, buf, len); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv); -+ goto exit_session; -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_session; -+ } -+ -+ /* Initialize Digest */ -+ rv = pkcs_C_DigestInit(hSession, &mech); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_DigestInit: Error = 0x%.8lX\n", rv); -+ goto exit_session; -+ } -+ -+ -+ for (i = 0; i < count; i++) { -+ /* Digest buffer */ -+ rv = pkcs_C_DigestUpdate(hSession, buf, len); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_DigestUpdate[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ break; -+ } -+ } -+ -+ /* Finalize Digest (unconditionally) */ -+ len = 20U; -+ rv = pkcs_C_DigestFinal(hSession, buf, &len); -+ if ((rv != CKR_OK) && !error) -+ fprintf(stderr, "C_DigestFinal: Error = 0x%.8lX\n", rv); -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_session; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%uK digested bytes in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g digested bytes/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_session: -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/sign.c b/bin/tests/pkcs11/benchmarks/sign.c -new file mode 100644 -index 0000000..8425ba9 ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/sign.c -@@ -0,0 +1,368 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* signrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+CK_BYTE modulus[] = { -+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99, -+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b, -+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90, -+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f, -+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96, -+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5, -+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b, -+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd, -+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08, -+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79, -+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45, -+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7, -+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd, -+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d, -+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f, -+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34, -+ 0xbf -+}; -+CK_BYTE pubexp[] = { 0x01, 0x00, 0x01 }; -+CK_BYTE privexp[] = { -+ 0x00, 0xae, 0x02, 0xf1, 0x47, 0xa8, 0x07, 0x02, -+ 0xb8, 0xf1, 0xd6, 0x92, 0x03, 0xee, 0x50, 0x33, -+ 0xab, 0x67, 0x9e, 0x3b, 0xb1, 0x57, 0xc7, 0x3e, -+ 0xc4, 0x86, 0x46, 0x61, 0xf1, 0xf8, 0xb6, 0x63, -+ 0x9f, 0x91, 0xe6, 0x3f, 0x44, 0xb8, 0x77, 0x1b, -+ 0xbe, 0x4c, 0x3c, 0xb8, 0x9f, 0xf7, 0x45, 0x7d, -+ 0xbf, 0x4f, 0xef, 0x3b, 0xcc, 0xda, 0x1a, 0x4e, -+ 0x34, 0xa8, 0x40, 0xea, 0x51, 0x72, 0x8a, 0xea, -+ 0x47, 0x06, 0x04, 0xd0, 0x62, 0x31, 0xa0, 0x6c, -+ 0x09, 0x60, 0xf9, 0xc7, 0x95, 0x88, 0x4a, 0xd7, -+ 0x19, 0xce, 0x89, 0x08, 0x87, 0x14, 0xef, 0xcc, -+ 0x0a, 0xef, 0x72, 0xb9, 0x21, 0xf5, 0xf0, 0xcd, -+ 0x6d, 0xe5, 0xfa, 0x15, 0x7f, 0xae, 0x33, 0x9f, -+ 0x26, 0xac, 0x2e, 0x52, 0x02, 0x07, 0xfb, 0x1d, -+ 0x4b, 0xec, 0x9a, 0x6b, 0x3b, 0x26, 0x1f, 0x52, -+ 0xfc, 0x47, 0xf8, 0x66, 0x33, 0xfa, 0x50, 0x6c, -+ 0x41 -+}; -+CK_BYTE prime1[] = { -+ 0x00, 0xe8, 0x98, 0xeb, 0xa1, 0xf0, 0xce, 0xde, -+ 0xc2, 0x74, 0x01, 0x18, 0x2b, 0xd3, 0x8f, 0x58, -+ 0xcd, 0xe9, 0x8e, 0x97, 0xbe, 0xfe, 0xe8, 0x6f, -+ 0xd6, 0x0c, 0x0a, 0x47, 0xf8, 0x56, 0x84, 0x36, -+ 0x15, 0xe6, 0x75, 0x1c, 0x69, 0x48, 0x8b, 0xf5, -+ 0x0f, 0x84, 0xd2, 0x60, 0x8b, 0xa2, 0x2a, 0xa1, -+ 0xeb, 0xed, 0xbe, 0x2d, 0xe9, 0x41, 0x0b, 0xed, -+ 0x17, 0x7c, 0xd3, 0xa6, 0x35, 0x6e, 0xa6, 0xd8, -+ 0x21 -+}; -+CK_BYTE prime2[] = { -+ 0x00, 0xca, 0x15, 0x6a, 0x43, 0x5e, 0x83, 0xc9, -+ 0x09, 0xeb, 0x14, 0x1e, 0x46, 0x46, 0x97, 0xfa, -+ 0xfa, 0x3c, 0x61, 0x7e, 0xc1, 0xf8, 0x8c, 0x5e, -+ 0xcb, 0xbf, 0xe4, 0xb9, 0x78, 0x7f, 0x4f, 0xab, -+ 0x82, 0x15, 0x53, 0xaa, 0x04, 0xee, 0x11, 0x21, -+ 0x2e, 0x23, 0x08, 0xa0, 0x14, 0x6d, 0x3a, 0x88, -+ 0xe6, 0xf8, 0xbe, 0x61, 0x38, 0x99, 0xca, 0x36, -+ 0x0d, 0x3e, 0x42, 0x0f, 0x63, 0x4d, 0x73, 0xf0, -+ 0xdf -+}; -+CK_BYTE exp_1[] = { -+ 0x66, 0x2d, 0xb7, 0x65, 0xbe, 0x99, 0xc2, 0x35, -+ 0xfe, 0x2b, 0xf4, 0xe8, 0x5b, 0xd9, 0xdf, 0x13, -+ 0x26, 0x04, 0xe4, 0x18, 0x9d, 0x76, 0x92, 0x9a, -+ 0x9f, 0x53, 0x6c, 0xe6, 0x65, 0x6b, 0x53, 0x2f, -+ 0x2f, 0xbc, 0x46, 0xac, 0xe1, 0x97, 0xca, 0x21, -+ 0xf5, 0x21, 0x4e, 0x14, 0x49, 0x3b, 0x1d, 0x42, -+ 0xbd, 0x80, 0x0c, 0x3f, 0x29, 0xba, 0x09, 0x7f, -+ 0x85, 0xf0, 0x9c, 0x55, 0x60, 0xb4, 0x9e, 0xc1 -+}; -+CK_BYTE exp_2[] = { -+ 0x00, 0x87, 0x22, 0x74, 0xf1, 0xe2, 0x15, 0x3c, -+ 0x6d, 0xde, 0x7e, 0x90, 0x94, 0x2c, 0x06, 0xdb, -+ 0xb5, 0x54, 0x85, 0x59, 0xcf, 0x7a, 0x56, 0xdb, -+ 0xd9, 0x62, 0x54, 0x20, 0x56, 0xdc, 0xc3, 0xb9, -+ 0x0b, 0xff, 0x18, 0xf8, 0x7b, 0xdd, 0x7b, 0x24, -+ 0xf6, 0x06, 0x45, 0x71, 0x4e, 0xd7, 0x90, 0x2a, -+ 0x16, 0x52, 0x46, 0x75, 0x1a, 0xf5, 0x74, 0x8c, -+ 0x5a, 0xa4, 0xc4, 0x66, 0x27, 0xe0, 0x96, 0x64, -+ 0x7f -+}; -+CK_BYTE coeff[] = { -+ 0x00, 0xd0, 0x1f, 0xb3, 0x47, 0x40, 0x93, 0x8b, -+ 0x99, 0xd7, 0xb5, 0xc6, 0x09, 0x82, 0x65, 0x94, -+ 0x9d, 0x56, 0x0a, 0x05, 0x55, 0x7d, 0x93, 0x04, -+ 0xa4, 0x26, 0xee, 0x42, 0x86, 0xa3, 0xf1, 0xd5, -+ 0x7a, 0x42, 0x84, 0x3c, 0x21, 0x96, 0x9a, 0xd9, -+ 0x36, 0xd4, 0x62, 0x01, 0xb0, 0x8b, 0x77, 0xe5, -+ 0xcc, 0x1b, 0xd2, 0x12, 0xd2, 0x9c, 0x89, 0x67, -+ 0x0c, 0x00, 0x09, 0x56, 0x8c, 0x33, 0x57, 0xf9, -+ 0x8c -+}; -+ -+CK_BYTE buf[1024]; -+CK_BYTE sig[128]; -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_ULONG len; -+ CK_ULONG slen; -+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE kType = CKK_RSA; -+ CK_ATTRIBUTE kTemplate[] = -+ { -+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) }, -+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) }, -+ { CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG) sizeof(pubexp) }, -+ { CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG) sizeof(privexp) }, -+ { CKA_PRIME_1, prime1, (CK_ULONG) sizeof(prime1) }, -+ { CKA_PRIME_2, prime2, (CK_ULONG) sizeof(prime2) }, -+ { CKA_EXPONENT_1, exp_1, (CK_ULONG) sizeof(exp_1) }, -+ { CKA_EXPONENT_2, exp_2, (CK_ULONG) sizeof(exp_2) }, -+ { CKA_COEFFICIENT, coeff, (CK_ULONG) sizeof(coeff) } -+ }; -+ CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 }; -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_RSA; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ int ontoken = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case 't': -+ ontoken = 1; -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tsign [-m module] [-s slot] [-p pin] " -+ "[-t] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE, -+ ISC_TRUE, (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NODIGESTSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ /* Create the private RSA key */ -+ if (ontoken) -+ kTemplate[2].pValue = &truevalue; -+ -+ rv = pkcs_C_CreateObject(hSession, kTemplate, 13, &hKey); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv); -+ goto exit_key; -+ } -+ -+ /* Randomize the buffer */ -+ len = (CK_ULONG) sizeof(buf); -+ rv = pkcs_C_GenerateRandom(hSession, buf, len); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv); -+ goto exit_key; -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_key; -+ } -+ -+ for (i = 0; i < count; i++) { -+ /* Initialize Sign */ -+ rv = pkcs_C_SignInit(hSession, &mech, hKey); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_SignInit[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ break; -+ } -+ -+ /* Perform Sign */ -+ slen = (CK_ULONG) sizeof(sig); -+ rv = pkcs_C_Sign(hSession, buf, len, sig, &slen); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_Sign[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_key; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u RSA signs in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g RSA signs/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_key: -+ if (hKey != CK_INVALID_HANDLE) { -+ rv = pkcs_C_DestroyObject(hSession, hKey); -+ if (rv != CKR_OK) -+ fprintf(stderr, -+ "C_DestroyObject: Error = 0x%.8lX\n", -+ rv); -+ } -+ -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/benchmarks/verify.c b/bin/tests/pkcs11/benchmarks/verify.c -new file mode 100644 -index 0000000..0a8f2c2 ---- /dev/null -+++ b/bin/tests/pkcs11/benchmarks/verify.c -@@ -0,0 +1,292 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* verify [-m module] [-s $slot] [-p pin] [-t] [-n count] */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#ifndef HAVE_CLOCK_GETTIME -+#ifndef CLOCK_REALTIME -+#define CLOCK_REALTIME 0 -+#endif -+ -+int -+clock_gettime(int32_t id, struct timespec *tp) -+{ -+ struct timeval tv; -+ int result; -+ -+ result = gettimeofday(&tv, NULL); -+ if (result) -+ return (result); -+ tp->tv_sec = tv.tv_sec; -+ tp->tv_nsec = (long) tv.tv_usec * 1000; -+ return (result); -+} -+#endif -+ -+CK_BYTE modulus[] = { -+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99, -+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b, -+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90, -+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f, -+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96, -+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5, -+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b, -+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd, -+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08, -+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79, -+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45, -+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7, -+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd, -+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d, -+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f, -+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34, -+ 0xbf -+}; -+CK_BYTE exponent[] = { 0x01, 0x00, 0x01 }; -+ -+CK_BYTE buf[1024]; -+CK_BYTE sig[128]; -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; -+ CK_ULONG len; -+ CK_ULONG slen; -+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS kClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE kType = CKK_RSA; -+ CK_ATTRIBUTE kTemplate[] = -+ { -+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) }, -+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) }, -+ { CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) } -+ }; -+ CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 }; -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_RSA; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ int c, errflg = 0; -+ int ontoken = 0; -+ unsigned int count = 1000; -+ unsigned int i; -+ struct timespec starttime; -+ struct timespec endtime; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case 't': -+ ontoken = 1; -+ break; -+ case 'n': -+ count = atoi(isc_commandline_argument); -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tverify [-m module] [-s slot] [-p pin] " -+ "[-t] [-n count]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE, -+ ISC_TRUE, (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NODIGESTSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ /* Create the private RSA key */ -+ if (ontoken) -+ kTemplate[2].pValue = &truevalue; -+ -+ rv = pkcs_C_CreateObject(hSession, kTemplate, 7, &hKey); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_key; -+ } -+ -+ /* Randomize the buffer */ -+ len = (CK_ULONG) sizeof(buf); -+ rv = pkcs_C_GenerateRandom(hSession, buf, len); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv); -+ goto exit_key; -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) { -+ perror("clock_gettime(start)"); -+ goto exit_key; -+ } -+ -+ for (i = 0; i < count; i++) { -+ /* Initialize Verify */ -+ rv = pkcs_C_VerifyInit(hSession, &mech, hKey); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_VerifyInit[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ break; -+ } -+ -+ /* Perform Verify */ -+ slen = (CK_ULONG) sizeof(sig); -+ rv = pkcs_C_Verify(hSession, buf, len, sig, slen); -+ if ((rv != CKR_OK) && (rv != CKR_SIGNATURE_INVALID)) { -+ fprintf(stderr, -+ "C_Verify[%u]: Error = 0x%.8lX\n", -+ i, rv); -+ error = 1; -+ break; -+ } -+ } -+ -+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) { -+ perror("clock_gettime(end)"); -+ goto exit_key; -+ } -+ -+ endtime.tv_sec -= starttime.tv_sec; -+ endtime.tv_nsec -= starttime.tv_nsec; -+ while (endtime.tv_nsec < 0) { -+ endtime.tv_sec -= 1; -+ endtime.tv_nsec += 1000000000; -+ } -+ printf("%u RSA verify in %ld.%09lds\n", i, -+ endtime.tv_sec, endtime.tv_nsec); -+ if (i > 0) -+ printf("%g RSA verify/s\n", -+ 1024 * i / ((double) endtime.tv_sec + -+ (double) endtime.tv_nsec / 1000000000.)); -+ -+ exit_key: -+ if (hKey != CK_INVALID_HANDLE) { -+ rv = pkcs_C_DestroyObject(hSession, hKey); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_DestroyObject: Error = 0x%.8lX\n", -+ rv); -+ errflg = 1; -+ } -+ } -+ -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/pkcs11-hmacmd5.c b/bin/tests/pkcs11/pkcs11-hmacmd5.c -new file mode 100644 -index 0000000..00a1df1 ---- /dev/null -+++ b/bin/tests/pkcs11/pkcs11-hmacmd5.c -@@ -0,0 +1,332 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* -+ * pkcs11-hmacmd5 -+ * -+ * Prints the MD5 HMAC of the standard input, using the PKCS#11 device. -+ * -+ * Usage: -+ * pkcs11-hmacmd5 [-m module] [-s $slot] [-n] [-p $pin] -+ * -m: PKCS#11 provider module. This must be the full -+ * path to a shared library object implementing the -+ * PKCS#11 API for a device. -+ * -s: Slot -+ * -p: PIN -+ * -n: don't log in to the PKCS#11 device -+ * -k: key name for the HMAC -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+/* Define static key template values */ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+#define BLOCKSIZE 32768 -+ -+char buffer[BLOCKSIZE + 72]; -+char digest[16]; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession; -+ CK_MECHANISM mech = { CKM_MD5_HMAC, NULL, 0 }; -+ CK_ULONG len; -+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; -+ CK_KEY_TYPE keyType = CKK_MD5_HMAC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, 0 } -+ }; -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_DIGEST; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ isc_boolean_t logon = ISC_TRUE; -+ int c, errflg = 0; -+ char *key = NULL; -+ size_t sum = 0; -+ unsigned int i; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:np:k:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'n': -+ logon = ISC_FALSE; -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case 'k': -+ key = isc_commandline_argument; -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg || (key == NULL)) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tpkcs11-hmacmd5 [-m module] [-s slot] " -+ "[-n|-p pin] -k key\n"); -+ exit(1); -+ } -+ -+ /* Decode the key */ -+ for (i = 0; i < BLOCKSIZE / 2; i++) { -+ switch (c = *key++) { -+ case 0: -+ goto key_done; -+ case '0': -+ case '1': -+ case '2': -+ case '3': -+ case '4': -+ case '5': -+ case '6': -+ case '7': -+ case '8': -+ case '9': -+ if ((i & 1) == 0) -+ buffer[i >> 1] = (c - '0') << 4; -+ else -+ buffer[i >> 1] |= c - '0'; -+ break; -+ case 'A': -+ case 'B': -+ case 'C': -+ case 'D': -+ case 'E': -+ case 'F': -+ if ((i & 1) == 0) -+ buffer[i >> 1] = (c - 'A' + 10) << 4; -+ else -+ buffer[i >> 1] |= c - 'A' + 10; -+ break; -+ case 'a': -+ case 'b': -+ case 'c': -+ case 'd': -+ case 'e': -+ case 'f': -+ if ((i & 1) == 0) -+ buffer[i >> 1] = (c - 'a' + 10) << 4; -+ else -+ buffer[i >> 1] |= c - 'a' + 10; -+ break; -+ default: -+ fprintf(stderr, "Not hexdigit '%c' in key\n", c); -+ exit(1); -+ } -+ } -+ key_done: -+ if ((i & 1) != 0) { -+ fprintf(stderr, "Even number of hexdigits in key\n"); -+ exit(1); -+ } -+ len = i >> 1; -+ keyTemplate[5].pValue = buffer; -+ keyTemplate[5].ulValueLen = (CK_ULONG) len; -+ -+ pk11_result_register(); -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (logon && pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_FALSE, logon, -+ (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ rv = pkcs_C_CreateObject(hSession, keyTemplate, (CK_ULONG) 6, &hKey); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_session; -+ } -+ if (hKey == CK_INVALID_HANDLE) { -+ fprintf(stderr, "C_CreateObject failed\n"); -+ error = 1; -+ goto exit_session; -+ } -+ -+ rv = pkcs_C_SignInit(hSession, &mech, hKey); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_SignInit: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_sign; -+ } -+ -+ for (;;) { -+ size_t n; -+ -+ for (;;) { -+ n = fread(buffer + sum, 1, BLOCKSIZE - sum, stdin); -+ sum += n; -+ if (sum == BLOCKSIZE) -+ break; -+ if (n == 0) { -+ if (ferror(stdin)) { -+ fprintf(stderr, "fread failed\n"); -+ error = 1; -+ goto exit_sign; -+ } -+ goto partial_block; -+ } -+ if (feof(stdin)) -+ goto partial_block; -+ } -+ -+ rv = pkcs_C_SignUpdate(hSession, (CK_BYTE_PTR) buffer, -+ (CK_ULONG) BLOCKSIZE); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_SignUpdate: Error = 0x%.8lX\n", -+ rv); -+ error = 1; -+ goto exit_sign; -+ } -+ } -+ -+partial_block: -+ if (sum > 0) { -+ rv = pkcs_C_SignUpdate(hSession, (CK_BYTE_PTR) buffer, -+ (CK_ULONG) sum); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_SignUpdate: Error = 0x%.8lX\n", -+ rv); -+ error = 1; -+ goto exit_sign; -+ } -+ } -+ -+ len = 16; -+ rv = pkcs_C_SignFinal(hSession, (CK_BYTE_PTR) digest, &len); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_SignFinal: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_sign; -+ } -+ if (len != 16) { -+ fprintf(stderr, "C_SignFinal: bad length = %lu\n", len); -+ error = 1; -+ } -+ -+ for (i = 0; i < 16; i++) -+ printf("%02x", digest[i] & 0xff); -+ printf("\n"); -+ -+ exit_sign: -+ rv = pkcs_C_DestroyObject(hSession, hKey); -+ if ((error == 0) && (rv != CKR_OK)) { -+ fprintf(stderr, "C_DestroyObject: Error = 0x%.8lX\n", rv); -+ error = 1; -+ } -+ -+ exit_session: -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/pkcs11/pkcs11-md5sum.c b/bin/tests/pkcs11/pkcs11-md5sum.c -new file mode 100644 -index 0000000..fd50648 ---- /dev/null -+++ b/bin/tests/pkcs11/pkcs11-md5sum.c -@@ -0,0 +1,235 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* $Id$ */ -+ -+/* -+ * pkcs11-md5sum -+ * -+ * Prints the MD5 checksum of the standard input, using the PKCS#11 device. -+ * -+ * Usage: -+ * pkcs11-md5sum [-m module] [-s $slot] [-n] [-p $pin] -+ * -m: PKCS#11 provider module. This must be the full -+ * path to a shared library object implementing the -+ * PKCS#11 API for a device. -+ * -s: Slot -+ * -p: PIN -+ * -n: don't log in to the PKCS#11 device -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun))) -+#define getpassphrase(x) getpass(x) -+#endif -+ -+#define BLOCKSIZE 32768 -+ -+char buffer[BLOCKSIZE + 72]; -+char digest[16]; -+ -+int -+main(int argc, char *argv[]) { -+ isc_result_t result; -+ CK_RV rv; -+ CK_SLOT_ID slot = 0; -+ CK_SESSION_HANDLE hSession; -+ CK_MECHANISM mech = { CKM_MD5, NULL, 0 }; -+ CK_ULONG len; -+ pk11_context_t pctx; -+ pk11_optype_t op_type = OP_DIGEST; -+ char *lib_name = NULL; -+ char *pin = NULL; -+ int error = 0; -+ isc_boolean_t logon = ISC_TRUE; -+ int c, errflg = 0; -+ size_t sum = 0; -+ unsigned int i; -+ -+ while ((c = isc_commandline_parse(argc, argv, ":m:s:np:")) != -1) { -+ switch (c) { -+ case 'm': -+ lib_name = isc_commandline_argument; -+ break; -+ case 's': -+ op_type = OP_ANY; -+ slot = atoi(isc_commandline_argument); -+ break; -+ case 'n': -+ logon = ISC_FALSE; -+ break; -+ case 'p': -+ pin = isc_commandline_argument; -+ break; -+ case ':': -+ fprintf(stderr, -+ "Option -%c requires an operand\n", -+ isc_commandline_option); -+ errflg++; -+ break; -+ case '?': -+ default: -+ fprintf(stderr, "Unrecognised option: -%c\n", -+ isc_commandline_option); -+ errflg++; -+ } -+ } -+ -+ if (errflg) { -+ fprintf(stderr, "Usage:\n"); -+ fprintf(stderr, -+ "\tpkcs11-md5sum [-m module] [-s slot] [-n|-p pin]\n"); -+ exit(1); -+ } -+ -+ pk11_result_register(); -+ -+ /* Initialize the CRYPTOKI library */ -+ if (lib_name != NULL) -+ pk11_set_lib_name(lib_name); -+ -+ if (logon && pin == NULL) -+ pin = getpassphrase("Enter Pin: "); -+ -+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_FALSE, logon, -+ (const char *) pin, slot); -+ if ((result != ISC_R_SUCCESS) && -+ (result != PK11_R_NORANDOMSERVICE) && -+ (result != PK11_R_NOAESSERVICE)) { -+ fprintf(stderr, "Error initializing PKCS#11: %s\n", -+ isc_result_totext(result)); -+ exit(1); -+ } -+ -+ if (pin != NULL) -+ memset(pin, 0, strlen((char *)pin)); -+ -+ hSession = pctx.session; -+ -+ rv = pkcs_C_DigestInit(hSession, &mech); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_DigestInit: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_session; -+ } -+ -+ for (;;) { -+ size_t n; -+ -+ for (;;) { -+ n = fread(buffer + sum, 1, BLOCKSIZE - sum, stdin); -+ sum += n; -+ if (sum == BLOCKSIZE) -+ break; -+ if (n == 0) { -+ if (ferror(stdin)) { -+ fprintf(stderr, "fread failed\n"); -+ error = 1; -+ goto exit_session; -+ } -+ goto partial_block; -+ } -+ if (feof(stdin)) -+ goto partial_block; -+ } -+ -+ rv = pkcs_C_DigestUpdate(hSession, (CK_BYTE_PTR) buffer, -+ (CK_ULONG) BLOCKSIZE); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_DigestUpdate: Error = 0x%.8lX\n", -+ rv); -+ error = 1; -+ goto exit_session; -+ } -+ } -+ -+partial_block: -+ if (sum > 0) { -+ rv = pkcs_C_DigestUpdate(hSession, (CK_BYTE_PTR) buffer, -+ (CK_ULONG) sum); -+ if (rv != CKR_OK) { -+ fprintf(stderr, -+ "C_DigestUpdate: Error = 0x%.8lX\n", -+ rv); -+ error = 1; -+ goto exit_session; -+ } -+ } -+ -+ len = 16; -+ rv = pkcs_C_DigestFinal(hSession, (CK_BYTE_PTR) digest, &len); -+ if (rv != CKR_OK) { -+ fprintf(stderr, "C_DigestFinal: Error = 0x%.8lX\n", rv); -+ error = 1; -+ goto exit_session; -+ } -+ if (len != 16) { -+ fprintf(stderr, "C_DigestFinal: bad length = %lu\n", len); -+ error = 1; -+ } -+ -+ for (i = 0; i < 16; i++) -+ printf("%02x", digest[i] & 0xff); -+ printf("\n"); -+ -+ exit_session: -+ pk11_return_session(&pctx); -+ (void) pk11_finalize(); -+ -+ exit(error); -+} -diff --git a/bin/tests/system/autosign/prereq.sh b/bin/tests/system/autosign/prereq.sh -index 34cd4a1..53807a2 100644 ---- a/bin/tests/system/autosign/prereq.sh -+++ b/bin/tests/system/autosign/prereq.sh -@@ -25,6 +25,7 @@ if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1 - then - rm -f Kfoo* - else -- echo "I:This test requires that --with-openssl was used." >&2 -+ echo "I:This test requires cryptography" >&2 -+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 - exit 1 - fi -diff --git a/bin/tests/system/cleanpkcs11.sh b/bin/tests/system/cleanpkcs11.sh -index e1cbc6f..ba541ed 100644 ---- a/bin/tests/system/cleanpkcs11.sh -+++ b/bin/tests/system/cleanpkcs11.sh -@@ -16,6 +16,10 @@ - - # $Id: cleanpkcs11.sh,v 1.3 2010/06/08 23:50:24 tbox Exp $ - -+SYSTEMTESTTOP=. -+. $SYSTEMTESTTOP/conf.sh -+ -+ - if [ ! -x ../../pkcs11/pkcs11-destroy ]; then exit 1; fi - --../../pkcs11/pkcs11-destroy -s ${SLOT:-0} -p 1234 -+$PK11DEL -w0 > /dev/null 2>&1 -diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in -index d6e902f..c40e8f1 100644 ---- a/bin/tests/system/conf.sh.in -+++ b/bin/tests/system/conf.sh.in -@@ -47,9 +47,9 @@ CHECKDS=$TOP/bin/python/dnssec-checkds - COVERAGE=$TOP/bin/python/dnssec-coverage - CHECKZONE=$TOP/bin/check/named-checkzone - CHECKCONF=$TOP/bin/check/named-checkconf --PK11GEN="$TOP/bin/pkcs11/pkcs11-keygen -s ${SLOT:-0} -p 1234" --PK11LIST="$TOP/bin/pkcs11/pkcs11-list -s ${SLOT:-0} -p 1234" --PK11DEL="$TOP/bin/pkcs11/pkcs11-destroy -s ${SLOT:-0} -p 1234" -+PK11GEN="$TOP/bin/pkcs11/pkcs11-keygen -q -s ${SLOT:-0} -p ${HSMPIN:-1234}" -+PK11LIST="$TOP/bin/pkcs11/pkcs11-list -s ${SLOT:-0} -p ${HSMPIN:-1234}" -+PK11DEL="$TOP/bin/pkcs11/pkcs11-destroy -s ${SLOT:-0} -p ${HSMPIN:-1234} -w 0" - JOURNALPRINT=$TOP/bin/tools/named-journalprint - VERIFY=$TOP/bin/dnssec/dnssec-verify - ARPANAME=$TOP/bin/tools/arpaname -@@ -63,7 +63,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin - database dlv dlvauto dlz dlzexternal dname dns64 dnssec ecdsa - formerr forward glue gost ixfr inline limits logfileconfig - lwresd masterfile masterformat metadata notify nsupdate pending -- pkcs11 redirect resolver rndc rpz rrl rrsetorder rsabigexponent -+ @PKCS11_TEST@ redirect resolver rndc rpz rrl rrsetorder rsabigexponent - smartsign sortlist spf staticstub stub tkey tsig tsiggss unknown - upforwd verify views wildcard xfer xferquota zero zonechecks" - -diff --git a/bin/tests/system/dnssec/prereq.sh b/bin/tests/system/dnssec/prereq.sh -index cb7c0c7..113e372 100644 ---- a/bin/tests/system/dnssec/prereq.sh -+++ b/bin/tests/system/dnssec/prereq.sh -@@ -23,6 +23,7 @@ if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1 - then - rm -f Kfoo* - else -- echo "I:This test requires that --with-openssl was used." >&2 -+ echo "I:This test requires cryptography" >&2 -+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 - exit 1 - fi -diff --git a/bin/tests/system/ecdsa/prereq.sh.in b/bin/tests/system/ecdsa/prereq.sh.in -index 434b53c..4214a30 100644 ---- a/bin/tests/system/ecdsa/prereq.sh.in -+++ b/bin/tests/system/ecdsa/prereq.sh.in -@@ -16,9 +16,16 @@ - - # $Id$ - --OPENSSL_ECDSA="@OPENSSL_ECDSA@" --if test -z "$OPENSSL_ECDSA" --then -- echo "I:This test requires a openssl version with ecdsa support." >&2 -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+../../../tools/genrandom 400 random.data -+ -+fail=0 -+$KEYGEN -q -a ecdsap256sha256 test > /dev/null 2>&1 || fail=1 -+rm -f Ktest* random.data -+ -+if [ $fail != 0 ] -+ then -+ echo "I:This test requires support for ECDSA cryptography." >&2 - exit 255 - fi -diff --git a/bin/tests/system/gost/prereq.sh.in b/bin/tests/system/gost/prereq.sh.in -index 98ec507..0e4079e 100644 ---- a/bin/tests/system/gost/prereq.sh.in -+++ b/bin/tests/system/gost/prereq.sh.in -@@ -16,9 +16,16 @@ - - # $Id: prereq.sh.in,v 1.4 2010/12/27 13:38:43 marka Exp $ - --OPENSSL_GOST="@OPENSSL_GOST@" --if test -z "$OPENSSL_GOST" --then -- echo "I:This test requires a openssl version with gost support." >&2 -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+../../../tools/genrandom 400 random.data -+ -+fail=0 -+$KEYGEN -q -a eccgost test > /dev/null 2>&1 || fail=1 -+rm -f Ktest* random.data -+ -+if [ $fail != 0 ] -+ then -+ echo "I:This test requires support for GOST cryptography." >&2 - exit 255 - fi -diff --git a/bin/tests/system/inline/clean.sh b/bin/tests/system/inline/clean.sh -index dae21e5..b6dda0b 100644 ---- a/bin/tests/system/inline/clean.sh -+++ b/bin/tests/system/inline/clean.sh -@@ -74,7 +74,7 @@ rm -f ns5/bits.bk.signed - rm -f ns5/bits.bk.signed.jnl - rm -f */*.jbk - rm -f random.data --rm -f dig.out.ns*.test* -+rm -f dig.out.ns* - rm -f signing.out* - rm -f freeze.test* - rm -f thaw.test* -diff --git a/bin/tests/system/metadata/prereq.sh b/bin/tests/system/metadata/prereq.sh -index b7ce1ea..006bcf5 100644 ---- a/bin/tests/system/metadata/prereq.sh -+++ b/bin/tests/system/metadata/prereq.sh -@@ -22,6 +22,7 @@ if $KEYGEN -q -r random.data foo > /dev/null 2>&1 - then - rm -f Kfoo* - else -- echo "I:This test requires that --with-openssl was used." >&2 -+ echo "I:This test requires cryptography" >&2 -+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 - exit 1 - fi -diff --git a/bin/tests/system/pending/prereq.sh b/bin/tests/system/pending/prereq.sh -index 0b6998e..f0848d7 100644 ---- a/bin/tests/system/pending/prereq.sh -+++ b/bin/tests/system/pending/prereq.sh -@@ -16,12 +16,25 @@ - - # $Id: prereq.sh,v 1.3 2009/11/18 23:48:06 tbox Exp $ - -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh - ../../../tools/genrandom 400 random.data - --if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1 --then -- rm -f Kfoo* -+rsafail=0 eccfail=0 -+ -+$KEYGEN -q -r random.data foo > /dev/null 2>&1 || rsafail=1 -+rm -f Kfoo* -+ -+$KEYGEN -q -a ECDSAP256SHA256 -r random.data foo > /dev/null 2>&1 || eccfail=1 -+rm -f Kfoo* -+ -+if [ $rsafail = 0 -a $eccfail = 0 ]; then -+ echo both > supported -+elif [ $rsafail = 1 -a $eccfail = 1 ]; then -+ echo "I:This test requires PKCS#11 support for either RSA or ECDSA cryptography." >&2 -+ exit 255 -+elif [ $rsafail = 0 ]; then -+ echo rsaonly > supported - else -- echo "I:This test requires that --with-openssl was used." >&2 -- exit 1 -+ echo ecconly > supported - fi -diff --git a/bin/tests/system/pkcs11/clean.sh b/bin/tests/system/pkcs11/clean.sh -index d7a557b..29d0149 100644 ---- a/bin/tests/system/pkcs11/clean.sh -+++ b/bin/tests/system/pkcs11/clean.sh -@@ -17,5 +17,6 @@ - # $Id: clean.sh,v 1.3 2010/06/08 23:50:24 tbox Exp $ - - rm -f K* ns1/K* keyset-* dsset-* ns1/*.db ns1/*.signed ns1/*.jnl --rm -f dig.out random.data --rm -f ns1/key ns1/named.memstats -+rm -f dig.out random.data pin -+rm -f ns1/*.key ns1/named.memstats -+rm -f supported -diff --git a/bin/tests/system/pkcs11/ns1/named.conf b/bin/tests/system/pkcs11/ns1/named.conf -index 09a850f..48b8adf 100644 ---- a/bin/tests/system/pkcs11/ns1/named.conf -+++ b/bin/tests/system/pkcs11/ns1/named.conf -@@ -39,8 +39,14 @@ controls { - inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; - }; - --zone "example." { -+zone "rsa.example." { -+ type master; -+ file "rsa.example.db.signed"; -+ allow-update { any; }; -+}; -+ -+zone "ecc.example." { - type master; -- file "example.db.signed"; -+ file "ecc.example.db.signed"; - allow-update { any; }; - }; -diff --git a/bin/tests/system/pkcs11/setup.sh b/bin/tests/system/pkcs11/setup.sh -index c044d75..a17a83d 100644 ---- a/bin/tests/system/pkcs11/setup.sh -+++ b/bin/tests/system/pkcs11/setup.sh -@@ -21,21 +21,59 @@ SYSTEMTESTTOP=.. - - RANDFILE=random.data - --zone=example - infile=ns1/example.db.in --zonefile=ns1/example.db - --$PK11GEN -b 1024 -l robie-zsk1 -i 01 --$PK11GEN -b 1024 -l robie-zsk2 -i 02 --$PK11GEN -b 2048 -l robie-ksk -+/bin/echo -n ${HSMPIN:-1234}> pin -+PWD=`pwd` - --zsk1=`$KEYFRLAB -a RSASHA1 -l robie-zsk1 example` --zsk2=`$KEYFRLAB -a RSASHA1 -l robie-zsk2 example` --ksk=`$KEYFRLAB -a RSASHA1 -f ksk -l robie-ksk example` -+supported=`cat supported` - --cat $infile $zsk1.key $ksk.key > $zonefile --$SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile > /dev/null 2> signer.err || cat signer.err --rm -f signer.err -+zone=rsa.example -+zonefile=ns1/rsa.example.db -+if [ "$supported" != "ecconly" ]; then -+ $PK11GEN -a RSA -b 1024 -l robie-rsa-zsk1 -i 01 -+ $PK11GEN -a RSA -b 1024 -l robie-rsa-zsk2 -i 02 -+ $PK11GEN -a RSA -b 2048 -l robie-rsa-ksk -+ -+ rsazsk1=`$KEYFRLAB -a RSASHA1 \ -+ -l "object=robie-rsa-zsk1;pin-source=$PWD/pin" rsa.example` -+ rsazsk2=`$KEYFRLAB -a RSASHA1 \ -+ -l "object=robie-rsa-zsk2;pin-source=$PWD/pin" rsa.example` -+ rsaksk=`$KEYFRLAB -a RSASHA1 -f ksk \ -+ -l "object=robie-rsa-ksk;pin-source=$PWD/pin" rsa.example` -+ -+ cat $infile $rsazsk1.key $rsaksk.key > $zonefile -+ $SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \ -+ > /dev/null 2> signer.err || cat signer.err -+ cp $rsazsk2.key ns1/rsa.key -+ mv Krsa* ns1 -+else -+ # RSA not available and will not be tested; make a placeholder -+ cp $infile ${zonefile}.signed -+fi -+ -+zone=ecc.example -+zonefile=ns1/ecc.example.db -+if [ "$supported" != "rsaonly" ]; then -+ $PK11GEN -a ECC -b 256 -l robie-ecc-zsk1 -i 03 -+ $PK11GEN -a ECC -b 256 -l robie-ecc-zsk2 -i 04 -+ $PK11GEN -a ECC -b 384 -l robie-ecc-ksk - --cp $zsk2.key ns1/key --mv Kexample* ns1 -+ ecczsk1=`$KEYFRLAB -a ECDSAP256SHA256 \ -+ -l "object=robie-ecc-zsk1;pin-source=$PWD/pin" ecc.example` -+ ecczsk2=`$KEYFRLAB -a ECDSAP256SHA256 \ -+ -l "object=robie-ecc-zsk2;pin-source=$PWD/pin" ecc.example` -+ eccksk=`$KEYFRLAB -a ECDSAP384SHA384 -f ksk \ -+ -l "object=robie-ecc-ksk;pin-source=$PWD/pin" ecc.example` -+ -+ cat $infile $ecczsk1.key $eccksk.key > $zonefile -+ $SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \ -+ > /dev/null 2> signer.err || cat signer.err -+ cp $ecczsk2.key ns1/ecc.key -+ mv Kecc* ns1 -+else -+ # ECC not available and will not be tested; make a placeholder -+ cp $infile ${zonefile}.signed -+fi -+ -+rm -f signer.err -diff --git a/bin/tests/system/pkcs11/tests.sh b/bin/tests/system/pkcs11/tests.sh -index 4694afc..01f1523 100644 ---- a/bin/tests/system/pkcs11/tests.sh -+++ b/bin/tests/system/pkcs11/tests.sh -@@ -26,47 +26,59 @@ DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300" - status=0 - ret=0 - --zonefile=ns1/example.db -+supported=`cat supported` -+case $supported in -+ rsaonly) algs="rsa" ;; -+ ecconly) algs="ecc" ;; -+ both) algs="rsa ecc" ;; -+esac - --echo "I:testing PKCS#11 key generation" -+for alg in $algs; do -+ zonefile=ns1/$alg.example.db -+ echo "I:testing PKCS#11 key generation ($alg)" -+ count=`$PK11LIST | grep robie-$alg-ksk | wc -l` -+ if [ $count != 2 ]; then echo "I:failed"; status=1; fi - --count=`$PK11LIST | grep robie-ksk | wc -l` --if [ $count != 2 ]; then echo "I:failed"; status=1; fi -+ echo "I:testing offline signing with PKCS#11 keys ($alg)" - --echo "I:testing offline signing with PKCS#11 keys" -+ count=`grep RRSIG $zonefile.signed | wc -l` -+ if [ $count != 12 ]; then echo "I:failed"; status=1; fi - --count=`grep RRSIG $zonefile.signed | wc -l` --if [ $count != 12 ]; then echo "I:failed"; status=1; fi -+ echo "I:testing inline signing with PKCS#11 keys ($alg)" - --echo "I:testing inline signing with PKCS#11 keys" -+ $NSUPDATE > /dev/null < /dev/null < dig.out || ret=1 --if [ $ret != 0 ]; then echo "I:failed"; fi --status=`expr $status + $ret` --count=`grep RRSIG dig.out | wc -l` --if [ $count != 4 ]; then echo "I:failed"; status=1; fi -- --echo "I:testing PKCS#11 key destroy" -- --ret=0 --$PK11DEL -l robie-zsk1 || ret=1 --$PK11DEL -i 02 || ret=1 --if [ $ret != 0 ]; then echo "I:failed"; fi --status=`expr $status + $ret` --count=`$PK11LIST | grep robie-zsk | wc -l` --if [ $count != 0 ]; then echo "I:failed"; fi --status=`expr $status + $count` -+ echo "I:waiting 20 seconds for key changes to take effect" -+ sleep 20 -+ -+ $DIG $DIGOPTS ns.$alg.example. @10.53.0.1 a > dig.out || ret=1 -+ if [ $ret != 0 ]; then echo "I:failed"; fi -+ status=`expr $status + $ret` -+ count=`grep RRSIG dig.out | wc -l` -+ if [ $count != 4 ]; then echo "I:failed"; status=1; fi -+ -+ echo "I:testing PKCS#11 key destroy ($alg)" -+ ret=0 -+ $PK11DEL -l robie-$alg-ksk -w0 > /dev/null 2>&1 || ret=1 -+ $PK11DEL -l robie-$alg-zsk1 -w0 > /dev/null 2>&1 || ret=1 -+ case $alg in -+ rsa) id=02 ;; -+ ecc) id=04 ;; -+ esac -+ $PK11DEL -i $id -w0 > /dev/null 2>&1 || ret=1 -+ if [ $ret != 0 ]; then echo "I:failed"; fi -+ status=`expr $status + $ret` -+ count=`$PK11LIST | grep robie-$alg | wc -l` -+ if [ $count != 0 ]; then echo "I:failed"; fi -+ status=`expr $status + $count` -+done - - echo "I:exit status: $status" - exit $status -diff --git a/bin/tests/system/pkcs11ssl/clean.sh b/bin/tests/system/pkcs11ssl/clean.sh -new file mode 100644 -index 0000000..14ec725 ---- /dev/null -+++ b/bin/tests/system/pkcs11ssl/clean.sh -@@ -0,0 +1,20 @@ -+#!/bin/sh -+# -+# Copyright (C) 2010, 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+rm -f K* ns1/K* keyset-* dsset-* ns1/*.db ns1/*.signed ns1/*.jnl -+rm -f dig.out random.data pin -+rm -f ns1/*.key ns1/named.memstats -+rm -f supported -diff --git a/bin/tests/system/pkcs11ssl/ns1/example.db.in b/bin/tests/system/pkcs11ssl/ns1/example.db.in -new file mode 100644 -index 0000000..7166fa8 ---- /dev/null -+++ b/bin/tests/system/pkcs11ssl/ns1/example.db.in -@@ -0,0 +1,29 @@ -+; Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -+; -+; Permission to use, copy, modify, and/or distribute this software for any -+; purpose with or without fee is hereby granted, provided that the above -+; copyright notice and this permission notice appear in all copies. -+; -+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+; PERFORMANCE OF THIS SOFTWARE. -+ -+; $Id: example.db.in,v 1.3 2010/06/08 23:50:24 tbox Exp $ -+ -+$TTL 300 ; 5 minutes -+@ IN SOA ns root ( -+ 2000082401 ; serial -+ 1800 ; refresh (30 minutes) -+ 1800 ; retry (30 minutes) -+ 1814400 ; expire (3 weeks) -+ 3600 ; minimum (1 hour) -+ ) -+ NS ns -+ns A 10.53.0.1 -+ -+txt TXT "recursed" -+ -diff --git a/bin/tests/system/pkcs11ssl/ns1/named.conf b/bin/tests/system/pkcs11ssl/ns1/named.conf -new file mode 100644 -index 0000000..90b8117 ---- /dev/null -+++ b/bin/tests/system/pkcs11ssl/ns1/named.conf -@@ -0,0 +1,52 @@ -+/* -+ * Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id: named.conf,v 1.3 2010/06/08 23:50:24 tbox Exp $ */ -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.1; -+ notify-source 10.53.0.1; -+ transfer-source 10.53.0.1; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.1; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ notify no; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+zone "rsa.example." { -+ type master; -+ file "rsa.example.db.signed"; -+ allow-update { any; }; -+}; -+ -+zone "ecc.example." { -+ type master; -+ file "ecc.example.db.signed"; -+ allow-update { any; }; -+}; -diff --git a/bin/tests/system/pkcs11ssl/prereq.sh b/bin/tests/system/pkcs11ssl/prereq.sh -new file mode 100644 -index 0000000..b5133f4 ---- /dev/null -+++ b/bin/tests/system/pkcs11ssl/prereq.sh -@@ -0,0 +1,34 @@ -+#!/bin/sh -+# -+# Copyright (C) 2010, 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id: prereq.sh,v 1.3 2010/06/08 23:50:24 tbox Exp $ -+ -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+../../../tools/genrandom 400 random.data -+ -+echo rsaonly > supported -+exit 0 -+ -+rsafail=0 eccfail=0 -+ -+$KEYGEN -q -r random.data foo > /dev/null 2>&1 || rsafail=1 -+rm -f Kfoo* -+ -+if [ $rsafail = 1 ]; then -+ echo "I:This test requires OpenSSL built with PKCS#11 support." >&2 -+ exit 255 -+fi -diff --git a/bin/tests/system/pkcs11ssl/setup.sh b/bin/tests/system/pkcs11ssl/setup.sh -new file mode 100644 -index 0000000..c13b275 ---- /dev/null -+++ b/bin/tests/system/pkcs11ssl/setup.sh -@@ -0,0 +1,46 @@ -+#!/bin/sh -+# -+# Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+ -+RANDFILE=random.data -+infile=ns1/example.db.in -+ -+/bin/echo -n ${HSMPIN:-1234}> pin -+PWD=`pwd` -+ -+zone=rsa.example -+zonefile=ns1/rsa.example.db -+ -+$PK11GEN -a RSA -b 1024 -l robie-rsa-zsk1 -i 01 -+$PK11GEN -a RSA -b 1024 -l robie-rsa-zsk2 -i 02 -+$PK11GEN -a RSA -b 2048 -l robie-rsa-ksk -+ -+rsazsk1=`$KEYFRLAB -a RSASHA1 \ -+ -l "robie-rsa-zsk1" rsa.example` -+rsazsk2=`$KEYFRLAB -a RSASHA1 \ -+ -l "robie-rsa-zsk2" rsa.example` -+rsaksk=`$KEYFRLAB -a RSASHA1 -f ksk \ -+ -l "robie-rsa-ksk" rsa.example` -+ -+cat $infile $rsazsk1.key $rsaksk.key > $zonefile -+$SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \ -+ > /dev/null 2> signer.err || cat signer.err -+cp $rsazsk2.key ns1/rsa.key -+mv Krsa* ns1 -+ -+rm -f signer.err -diff --git a/bin/tests/system/pkcs11ssl/tests.sh b/bin/tests/system/pkcs11ssl/tests.sh -new file mode 100644 -index 0000000..7785d5a ---- /dev/null -+++ b/bin/tests/system/pkcs11ssl/tests.sh -@@ -0,0 +1,71 @@ -+#!/bin/sh -+# -+# Copyright (C) 2010, 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id: tests.sh,v 1.3 2010/06/08 23:50:24 tbox Exp $ -+ -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+ -+RANDFILE=random.data -+ -+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300" -+ -+status=0 -+ret=0 -+ -+alg=rsa -+zonefile=ns1/rsa.example.db -+echo "I:testing PKCS#11 key generation (rsa)" -+count=`$PK11LIST | grep robie-rsa-ksk | wc -l` -+if [ $count != 2 ]; then echo "I:failed"; status=1; fi -+ -+echo "I:testing offline signing with PKCS#11 keys (rsa)" -+ -+count=`grep RRSIG $zonefile.signed | wc -l` -+if [ $count != 12 ]; then echo "I:failed"; status=1; fi -+ -+echo "I:testing inline signing with PKCS#11 keys (rsa)" -+ -+$NSUPDATE > /dev/null < dig.out || ret=1 -+if [ $ret != 0 ]; then echo "I:failed"; fi -+status=`expr $status + $ret` -+count=`grep RRSIG dig.out | wc -l` -+if [ $count != 4 ]; then echo "I:failed"; status=1; fi -+ -+echo "I:testing PKCS#11 key destroy (rsa)" -+ret=0 -+$PK11DEL -l robie-rsa-ksk -w0 > /dev/null 2>&1 || ret=1 -+$PK11DEL -l robie-rsa-zsk1 -w0 > /dev/null 2>&1 || ret=1 -+$PK11DEL -i $id -w0 > /dev/null 2>&1 || ret=1 -+if [ $ret != 0 ]; then echo "I:failed"; fi -+status=`expr $status + $ret` -+count=`$PK11LIST | grep robie-rsa | wc -l` -+if [ $count != 0 ]; then echo "I:failed"; fi -+status=`expr $status + $count` -+ -+echo "I:exit status: $status" -+exit $status -diff --git a/bin/tests/system/pkcs11ssl/usepkcs11 b/bin/tests/system/pkcs11ssl/usepkcs11 -new file mode 100644 -index 0000000..ef46412 ---- /dev/null -+++ b/bin/tests/system/pkcs11ssl/usepkcs11 -@@ -0,0 +1 @@ -+This test relies on PKCS#11! -diff --git a/bin/tests/system/rsabigexponent/Makefile.in b/bin/tests/system/rsabigexponent/Makefile.in -index d32eb15..ce8958b 100644 ---- a/bin/tests/system/rsabigexponent/Makefile.in -+++ b/bin/tests/system/rsabigexponent/Makefile.in -@@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@ - - CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@ - --CDEFINES = @USE_OPENSSL@ -+CDEFINES = @CRYPTO@ - CWARNINGS = - - DNSLIBS = ../../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@ -diff --git a/bin/tests/system/rsabigexponent/bigkey.c b/bin/tests/system/rsabigexponent/bigkey.c -index aa2e8ec..436254c 100644 ---- a/bin/tests/system/rsabigexponent/bigkey.c -+++ b/bin/tests/system/rsabigexponent/bigkey.c -@@ -16,7 +16,7 @@ - - /* $Id$ */ - --#ifdef OPENSSL -+#if defined(OPENSSL) || defined(PKCS11CRYPTO) - #include - - #include -@@ -44,8 +44,16 @@ - #include - #include - -+#ifdef OPENSSL - #include - #if OPENSSL_VERSION_NUMBER <= 0x00908000L -+#define USE_FIX_KEY_FILES -+#endif -+#else -+#define USE_FIX_KEY_FILES -+#endif -+ -+#ifdef USE_FIX_KEY_FILES - - /* - * Use a fixed key file pair if OpenSSL doesn't support > 32 bit exponents. -@@ -235,16 +243,16 @@ main(int argc, char **argv) { - } - #endif - --#else /* OPENSSL */ -+#else /* OPENSSL || PKCS11CRYPTO */ - - #include - #include - - int --main(int argc, char **argv) { -- fprintf(stderr, "Compiled without OpenSSL\n"); -+main() { -+ fprintf(stderr, "Compiled without Crypto\n"); - exit(1); - } - --#endif /* OPENSSL */ -+#endif /* OPENSSL || PKCS11CRYPTO */ - /*! \file */ -diff --git a/bin/tests/system/rsabigexponent/prereq.sh b/bin/tests/system/rsabigexponent/prereq.sh -index 8edbf1d..6259fb6 100644 ---- a/bin/tests/system/rsabigexponent/prereq.sh -+++ b/bin/tests/system/rsabigexponent/prereq.sh -@@ -22,6 +22,7 @@ if ./bigkey > /dev/null 2>&1 - then - rm -f Kexample.* - else -- echo "I:This test requires that --with-openssl was used." >&2 -+ echo "I:This test requires cryptography" >&2 -+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 - exit 1 - fi -diff --git a/bin/tests/system/smartsign/prereq.sh b/bin/tests/system/smartsign/prereq.sh -index e47b769..9ed2fa8 100644 ---- a/bin/tests/system/smartsign/prereq.sh -+++ b/bin/tests/system/smartsign/prereq.sh -@@ -22,6 +22,7 @@ if $KEYGEN -q -r random.data foo > /dev/null 2>&1 - then - rm -f Kfoo* - else -- echo "I:This test requires that --with-openssl was used." >&2 -+ echo "I:This test requires cryptography" >&2 -+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 - exit 1 - fi -diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c -index ff2c2ee..af17582 100644 ---- a/bin/tests/system/tkey/keycreate.c -+++ b/bin/tests/system/tkey/keycreate.c -@@ -228,6 +228,7 @@ main(int argc, char *argv[]) { - dns_result_register(); - - mctx = NULL; -+ isc_mem_debugging = ISC_MEM_DEBUGRECORD; - RUNCHECK(isc_mem_create(0, 0, &mctx)); - - ectx = NULL; -diff --git a/bin/tests/system/tkey/prereq.sh b/bin/tests/system/tkey/prereq.sh -index fca4a27..66295fe 100644 ---- a/bin/tests/system/tkey/prereq.sh -+++ b/bin/tests/system/tkey/prereq.sh -@@ -23,6 +23,7 @@ if $KEYGEN -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1 - then - rm -f foo* - else -- echo "I:This test requires that --with-openssl was used." >&2 -+ echo "I:This test requires cryptography" >&2 -+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 - exit 1 - fi -diff --git a/config.h.in b/config.h.in -index 4139e1d..f2eb59a 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -132,14 +132,11 @@ int sigwait(const unsigned int *set, int *sig); - /** define if you have strerror in the C library. */ - #undef HAVE_STRERROR - --/** Define if you are running under Compaq TruCluster. */ --#undef HAVE_TRUCLUSTER -- - /* Define if OpenSSL includes DSA support */ - #undef HAVE_OPENSSL_DSA - --/* Define if OpenSSL includes ECDSA support */ --#undef HAVE_OPENSSL_ECDSA -+/* Define if you have getpassphrase in the C library. */ -+#undef HAVE_GETPASSPHRASE - - /* Define to the length type used by the socket API (socklen_t, size_t, int). */ - #undef ISC_SOCKADDR_LEN_T -@@ -187,6 +184,9 @@ int sigwait(const unsigned int *set, int *sig); - /* Define to 1 if you have the `chroot' function. */ - #undef HAVE_CHROOT - -+/* Define if clock_gettime is available. */ -+#undef HAVE_CLOCK_GETTIME -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_DEVPOLL_H - -@@ -292,6 +292,12 @@ int sigwait(const unsigned int *set, int *sig); - /* Define if your OpenSSL version supports GOST. */ - #undef HAVE_OPENSSL_GOST - -+/* Define if your PKCS11 provider supports ECDSA. */ -+#undef HAVE_PKCS11_ECDSA -+ -+/* Define if your PKCS11 provider supports GOST. */ -+#undef HAVE_PKCS11_GOST -+ - /* Define to 1 if you have the `readline' function. */ - #undef HAVE_READLINE - -@@ -418,6 +424,9 @@ int sigwait(const unsigned int *set, int *sig); - (O_NDELAY/O_NONBLOCK). */ - #undef PORT_NONBLOCK - -+/* Define if GOST private keys are encoded in ASN.1. */ -+#undef PREFER_GOSTASN1 -+ - /* The size of `void *', as computed by sizeof. */ - /* #undef SIZEOF_VOID_P */ - -diff --git a/configure.in b/configure.in -index 8a06905..24eafb7 100644 ---- a/configure.in -+++ b/configure.in -@@ -640,25 +640,76 @@ AC_ARG_WITH(openssl, - (Required for DNSSEC)], - use_openssl="$withval", use_openssl="auto") - -+# -+# was --enable-native-pkcs11 specified? -+# (note it implies both --without-openssl and --with-pkcs11) -+# -+AC_ARG_ENABLE(native-pkcs11, -+ [ --enable-native-pkcs11 use native PKCS11 for all crypto [[default=no]]], -+ want_native_pkcs11="$enableval", want_native_pkcs11="no") -+ -+AC_ARG_WITH(pkcs11, -+[ --with-pkcs11[=PATH] Build with PKCS11 support [yes|no|path] -+ (PATH is for the PKCS11 provider)], -+ use_pkcs11="$withval", use_pkcs11="auto") -+ - openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw" - if test "$use_openssl" = "auto" - then -- for d in $openssldirs -- do -- if test -f $d/include/openssl/opensslv.h -- then -- use_openssl=$d -- break -- fi -- done -+ if test "$want_native_pkcs11" = "yes" -+ then -+ use_openssl="native_pkcs11" -+ else -+ for d in $openssldirs -+ do -+ if test -f $d/include/openssl/opensslv.h -+ then -+ use_openssl=$d -+ break -+ fi -+ done -+ fi - fi - OPENSSL_ECDSA="" - OPENSSL_GOST="" -+AC_ARG_WITH(gost, -+[ --with-gost Crypto GOST [yes|no|raw|asn1].], -+ with_gost="$withval", with_gost="auto") -+AC_ARG_WITH(ecdsa, [ --with-ecdsa OpenSSL ECDSA], -+ with_ecdsa="$withval", with_ecdsa="auto") -+ -+gosttype="raw" -+case "$with_gost" in -+ raw) -+ with_gost="yes" -+ ;; -+ asn1) -+ AC_DEFINE(PREFER_GOSTASN1, 1, -+ [Define if GOST private keys are encoded in ASN.1.]) -+ gosttype="asn1" -+ with_gost="yes" -+ ;; -+ auto|yes|no) -+ ;; -+ *) -+ AC_MSG_ERROR(unknown GOST private key encoding) -+ ;; -+esac -+ - case "$use_openssl" in -+ native_pkcs11) -+ AC_MSG_RESULT(disabled because of native PKCS11) -+ DST_OPENSSL_INC="" -+ CRYPTO="" -+ OPENSSLGOSTLINKOBJS="" -+ OPENSSLGOSTLINKSRS="" -+ OPENSSLLINKOBJS="" -+ OPENSSLLINKSRCS="" -+ ;; - no) - AC_MSG_RESULT(no) - DST_OPENSSL_INC="" -- USE_OPENSSL="" -+ CRYPTO="" - OPENSSLGOSTLINKOBJS="" - OPENSSLGOSTLINKSRS="" - OPENSSLLINKOBJS="" -@@ -666,7 +717,7 @@ case "$use_openssl" in - ;; - auto) - DST_OPENSSL_INC="" -- USE_OPENSSL="" -+ CRYPTO="" - OPENSSLGOSTLINKOBJS="" - OPENSSLGOSTLINKSRS="" - OPENSSLLINKOBJS="" -@@ -676,6 +727,11 @@ case "$use_openssl" in - If you don't want OpenSSL, use --without-openssl]) - ;; - *) -+ if test "$want_native_pkcs11" = "yes" -+ then -+ AC_MSG_RESULT() -+ AC_MSG_ERROR([OpenSSL and native PKCS11 cannot be used together.]) -+ fi - if test "$use_openssl" = "yes" - then - # User did not specify a path - guess it -@@ -697,7 +753,7 @@ If you don't want OpenSSL, use --without-openssl]) - then - AC_MSG_ERROR(["$use_openssl/include/openssl/opensslv.h" not found]) - fi -- USE_OPENSSL='-DOPENSSL' -+ CRYPTO='-DOPENSSL' - if test "$use_openssl" = "/usr" - then - DST_OPENSSL_INC="" -@@ -733,6 +789,7 @@ If you don't want OpenSSL, use --without-openssl]) - fi - AC_MSG_RESULT(using OpenSSL from $use_openssl/lib and $use_openssl/include) - -+ saved_cc="$CC" - saved_cflags="$CFLAGS" - saved_libs="$LIBS" - CFLAGS="$CFLAGS $DST_OPENSSL_INC" -@@ -839,8 +896,7 @@ int main() { - [AC_MSG_RESULT(no) - have_ecdsa="no"], - [AC_MSG_RESULT(using --with-ecdsa)]) -- AC_ARG_WITH(ecdsa, [ --with-ecdsa OpenSSL ECDSA], -- with_ecdsa="$withval", with_ecdsa="auto") -+ - case "$with_ecdsa" in - yes) - case "$have_ecdsa" in -@@ -869,6 +925,15 @@ int main() { - - AC_MSG_CHECKING(for OpenSSL GOST support) - have_gost="" -+ case "$use_pkcs11" in -+ auto|no) -+ ;; -+ *) -+ if $use_threads; then -+ CC="$CC -pthread" -+ fi -+ ;; -+ esac - AC_TRY_RUN([ - #include - #include -@@ -896,8 +961,7 @@ int main() { - [AC_MSG_RESULT(no) - have_gost="no"], - [AC_MSG_RESULT(using --with-gost)]) -- AC_ARG_WITH(gost, [ --with-gost OpenSSL GOST], -- with_gost="$withval", with_gost="auto") -+ - case "$with_gost" in - yes) - case "$have_gost" in -@@ -910,7 +974,7 @@ int main() { - *) - case "$have_gost" in - yes|no) ;; -- *) AC_MSG_ERROR([need --with-gost=[[yes or no]]]) ;; -+ *) AC_MSG_ERROR([need --with-gost=[[yes, no, raw or asn1]]]) ;; - esac - ;; - esac -@@ -938,7 +1002,6 @@ esac - # it as needed) if it is found. - # - --AC_SUBST(USE_OPENSSL) - AC_SUBST(DST_OPENSSL_INC) - AC_SUBST(OPENSSLGOSTLINKOBJS) - AC_SUBST(OPENSSLGOSTLINKSRCS) -@@ -958,7 +1021,7 @@ AC_ARG_ENABLE(openssl-hash, - want_openssl_hash="$enableval", want_openssl_hash="no") - case $want_openssl_hash in - yes) -- if test "$USE_OPENSSL" = "" -+ if test "$CRYPTO" = "" - then - AC_MSG_ERROR([No OpenSSL for hash functions]) - fi -@@ -973,6 +1036,41 @@ esac - AC_SUBST(ISC_PLATFORM_OPENSSLHASH) - AC_SUBST(ISC_OPENSSL_INC) - -+AC_ARG_WITH(libtool, -+ [ --with-libtool use GNU libtool], -+ use_libtool="$withval", use_libtool="no") -+ -+case $use_libtool in -+ yes) -+ AM_PROG_LIBTOOL -+ O=lo -+ A=la -+ LIBTOOL_MKDEP_SED='s;\.o;\.lo;' -+ LIBTOOL_MODE_COMPILE='--mode=compile --tag=CC' -+ LIBTOOL_MODE_INSTALL='--mode=install --tag=CC' -+ LIBTOOL_MODE_LINK='--mode=link --tag=CC' -+ case "$host" in -+ *) LIBTOOL_ALLOW_UNDEFINED= ;; -+ esac -+ case "$host" in -+ *-ibm-aix*) LIBTOOL_IN_MAIN="-Wl,-bI:T_testlist.imp" ;; -+ *) LIBTOOL_IN_MAIN= ;; -+ esac; -+ ;; -+ *) -+ O=o -+ A=a -+ LIBTOOL= -+ AC_SUBST(LIBTOOL) -+ LIBTOOL_MKDEP_SED= -+ LIBTOOL_MODE_COMPILE= -+ LIBTOOL_MODE_INSTALL= -+ LIBTOOL_MODE_LINK= -+ LIBTOOL_ALLOW_UNDEFINED= -+ LIBTOOL_IN_MAIN= -+ ;; -+esac -+ - # - # PKCS11 (aka crypto hardware) support - # -@@ -980,25 +1078,102 @@ AC_SUBST(ISC_OPENSSL_INC) - # - - AC_MSG_CHECKING(for PKCS11 support) --AC_ARG_WITH(pkcs11, --[ --with-pkcs11[=PATH] Build with PKCS11 support [yes|no|path] -- (PATH is for the PKCS11 provider)], -- use_pkcs11="$withval", use_pkcs11="no") -+ -+if test "$use_pkcs11" = "auto" -+then -+ if test "$want_native_pkcs11" = "yes" -+ then -+ use_pkcs11="yes" -+ else -+ use_pkcs11="no" -+ fi -+fi - - case "$use_pkcs11" in - no|'') -- AC_MSG_RESULT(disabled) -- USE_PKCS11='' -- PKCS11_TOOLS='' -+ AC_MSG_RESULT(no) -+ USE_PKCS11="" -+ PKCS11_TEST="" -+ PKCS11_TOOLS="" -+ ISC_PK11_C="" -+ ISC_PK11_O="" -+ ISC_PK11_API_C="" -+ ISC_PK11_API_O="" -+ ISC_PK11_RESULT_C="" -+ ISC_PK11_RESULT_O="" -+ ISC_ISCPK11_API_C="" -+ ISC_ISCPK11_API_O="" - ;; - yes|*) -- AC_MSG_RESULT(using OpenSSL with PKCS11 support) -+ AC_MSG_RESULT(yes) -+ if ! $use_threads; then -+ AC_MSG_ERROR([PKCS11 requires thread support]) -+ fi -+ if test "$CRYPTO" != "" -+ then -+ AC_MSG_CHECKING(for OpenSSL with PKCS11 support) -+ saved_cc="$CC" -+ saved_cflags="$CFLAGS" -+ saved_libs="$LIBS" -+ CC="$CC -pthread" -+ CFLAGS="$CFLAGS $DST_OPENSSL_INC" -+ LIBS="$LIBS $DNS_OPENSSL_LIBS" -+ AC_TRY_RUN([ -+#include -+#include -+int main() { -+ ENGINE *e; -+ -+ OPENSSL_config(NULL); -+ e = ENGINE_by_id("pkcs11"); -+ if (e == NULL) -+ return (1); -+ if (ENGINE_init(e) <= 0) -+ return (1); -+ return (0); -+} -+], -+ [AC_MSG_RESULT(yes) -+ PKCS11_TEST=pkcs11ssl -+ PKCS11_ENGINE='-DPKCS11_ENGINE="\"pkcs11\""'], -+ [AC_MSG_RESULT(no) -+ PKCS11_TEST='' -+ PKCS11_ENGINE='-DPKCS11_ENGINE=NULL'], -+ [AC_MSG_RESULT(cross compile, defaulting to no) -+ PKCS11_TEST='' -+ PKCS11_ENGINE='-DPKCS11_ENGINE=NULL']) -+ CC="$saved_cc" -+ CFLAGS="$saved_cflags" -+ LIBS="$saved_libs" -+ else -+ PKCS11_TEST='' -+ PKCS11_ENGINE='-DPKCS11_ENGINE=NULL' -+ -+ fi - USE_PKCS11='-DUSE_PKCS11' - PKCS11_TOOLS=pkcs11 -- ;; -+ AC_CHECK_FUNC(getpassphrase, AC_DEFINE(HAVE_GETPASSPHRASE),) -+ ISC_PK11_C="pk11.c" -+ ISC_PK11_O="pk11.$O" -+ ISC_PK11_API_C="pk11_api.c" -+ ISC_PK11_API_O="pk11_api.$O" -+ ISC_PK11_RESULT_C="pk11_result.c" -+ ISC_PK11_RESULT_O="pk11_result.$O" -+ ISC_ISCPK11_API_C="unix/pk11_api.c" -+ ISC_ISCPK11_API_O="unix/pk11_api.$O" -+ ;; - esac - AC_SUBST(USE_PKCS11) - AC_SUBST(PKCS11_TOOLS) -+AC_SUBST(PKCS11_ENGINE) -+AC_SUBST(ISC_PK11_C) -+AC_SUBST(ISC_PK11_O) -+AC_SUBST(ISC_PK11_API_C) -+AC_SUBST(ISC_PK11_API_O) -+AC_SUBST(ISC_PK11_RESULT_C) -+AC_SUBST(ISC_PK11_RESULT_O) -+AC_SUBST(ISC_ISCPK11_API_C) -+AC_SUBST(ISC_ISCPK11_API_O) - - AC_MSG_CHECKING(for PKCS11 tools) - case "$use_pkcs11" in -@@ -1006,13 +1181,77 @@ case "$use_pkcs11" in - AC_MSG_RESULT(disabled) - PKCS11_PROVIDER="undefined" - ;; -- *) -- AC_MSG_RESULT(PKCS11 provider is "$use_pkcs11") -+ yes|'') -+ PKCS11_PROVIDER="undefined" -+ AC_MSG_RESULT(enabled) -+ ;; -+ *) - PKCS11_PROVIDER="$use_pkcs11" -+ AC_MSG_RESULT([enabled, PKCS11 provider is $PKCS11_PROVIDER]) - ;; - esac - AC_SUBST(PKCS11_PROVIDER) - -+ -+PKCS11_ECDSA="" -+PKCS11_GOST="" -+AC_MSG_CHECKING(for native PKCS11) -+ -+case "$want_native_pkcs11" in -+ yes) -+ AC_MSG_RESULT(using native PKCS11 crypto) -+ CRYPTO="-DPKCS11CRYPTO" -+ PKCS11LINKOBJS='${PKCS11LINKOBJS}' -+ PKCS11LINKSRCS='${PKCS11LINKSRCS}' -+ PKCS11_TEST=pkcs11 -+ AC_MSG_CHECKING(for PKCS11 ECDSA) -+ case "$with_ecdsa" in -+ no) -+ AC_MSG_RESULT([disabled]) -+ ;; -+ *) -+ AC_MSG_RESULT(enabled) -+ PKCS11_ECDSA="yes" -+ AC_DEFINE(HAVE_PKCS11_ECDSA, 1, -+ [Define if your PKCS11 provider supports ECDSA.]) -+ ;; -+ esac -+ AC_MSG_CHECKING(for PKCS11 GOST) -+ case "$with_gost" in -+ yes) -+ AC_MSG_RESULT(enabled) -+ PKCS11_GOST="yes" -+ AC_DEFINE(HAVE_PKCS11_GOST, 1, -+ [Define if your PKCS11 provider supports GOST.]) -+ ;; -+ *) -+ AC_MSG_RESULT([disabled]) -+ ;; -+ esac -+ ;; -+ no|'') -+ AC_MSG_RESULT(disabled) -+ ;; -+esac -+ -+AC_SUBST(PKCS11LINKOBJS) -+AC_SUBST(PKCS11LINKSRCS) -+AC_SUBST(CRYPTO) -+AC_SUBST(PKCS11_ECDSA) -+AC_SUBST(PKCS11_GOST) -+AC_SUBST(PKCS11_TEST) -+ -+# for PKCS11 benchmarks -+have_clock_gt=no -+AC_CHECK_FUNC(clock_gettime,have_clock_gt=yes,) -+if test "$have_clock_gt" = "no"; then -+ AC_CHECK_LIB(rt,clock_gettime,have_clock_gt=ye,,) -+ fi -+if test "$have_clock_gt" = "yes"; then -+ AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if clock_gettime is available.]) -+fi -+ -+ - AC_MSG_CHECKING(for GSSAPI library) - AC_ARG_WITH(gssapi, - [ --with-gssapi=PATH Specify path for system-supplied GSSAPI [[default=yes]]], -@@ -1245,6 +1484,21 @@ case "$use_randomdev" in - esac - - # -+# Only check dsa signature generation on these platforms when performing -+# system tests. -+# -+CHECK_DSA=0 -+if grep "#define PATH_RANDOMDEV " confdefs.h > /dev/null -+then -+ case "$host" in -+ *darwin*|*freebsd*) -+ CHECK_DSA=1 -+ ;; -+ esac -+fi -+AC_SUBST(CHECK_DSA) -+ -+# - # Do we have arc4random() ? - # - AC_CHECK_FUNC(arc4random, AC_DEFINE(HAVE_ARC4RANDOM)) -@@ -1633,41 +1887,6 @@ esac - AC_SUBST(PURIFY) - - --AC_ARG_WITH(libtool, -- [ --with-libtool use GNU libtool], -- use_libtool="$withval", use_libtool="no") -- --case $use_libtool in -- yes) -- AM_PROG_LIBTOOL -- O=lo -- A=la -- LIBTOOL_MKDEP_SED='s;\.o;\.lo;' -- LIBTOOL_MODE_COMPILE='--mode=compile --tag=CC' -- LIBTOOL_MODE_INSTALL='--mode=install --tag=CC' -- LIBTOOL_MODE_LINK='--mode=link --tag=CC' -- case "$host" in -- *) LIBTOOL_ALLOW_UNDEFINED= ;; -- esac -- case "$host" in -- *-ibm-aix*) LIBTOOL_IN_MAIN="-Wl,-bI:T_testlist.imp" ;; -- *) LIBTOOL_IN_MAIN= ;; -- esac; -- ;; -- *) -- O=o -- A=a -- LIBTOOL= -- AC_SUBST(LIBTOOL) -- LIBTOOL_MKDEP_SED= -- LIBTOOL_MODE_COMPILE= -- LIBTOOL_MODE_INSTALL= -- LIBTOOL_MODE_LINK= -- LIBTOOL_ALLOW_UNDEFINED= -- LIBTOOL_IN_MAIN= -- ;; --esac -- - # - # enable/disable dumping stack backtrace. Also check if the system supports - # glibc-compatible backtrace() function. -@@ -3419,6 +3638,9 @@ BIND9_CONFIGARGS="`echo $BIND9_CONFIGARGS | sed 's/^ //'`" - BIND9_CONFIGARGS="CONFIGARGS=${BIND9_CONFIGARGS}" - AC_SUBST(BIND9_CONFIGARGS) - -+AC_SUBST_FILE(LIBISCPK11_API) -+LIBISCPK11_API="$srcdir/lib/iscpk11/api" -+ - AC_SUBST_FILE(LIBISC_API) - LIBISC_API="$srcdir/lib/isc/api" - -@@ -3728,6 +3950,8 @@ AC_CONFIG_FILES([ - bin/tests/mem/Makefile - bin/tests/names/Makefile - bin/tests/net/Makefile -+ bin/tests/pkcs11/Makefile -+ bin/tests/pkcs11/benchmarks/Makefile - bin/tests/rbt/Makefile - bin/tests/resolver/Makefile - bin/tests/sockaddr/Makefile -@@ -3811,11 +4035,14 @@ AC_CONFIG_FILES([ - lib/isc/include/Makefile - lib/isc/include/isc/Makefile - lib/isc/include/isc/platform.h -+ lib/isc/include/pk11/Makefile -+ lib/isc/include/pkcs11/Makefile - lib/isc/tests/Makefile - lib/isc/nls/Makefile - lib/isc/unix/Makefile - lib/isc/unix/include/Makefile - lib/isc/unix/include/isc/Makefile -+ lib/isc/unix/include/pkcs11/Makefile - lib/isccc/Makefile - lib/isccc/include/Makefile - lib/isccc/include/isccc/Makefile -@@ -3885,12 +4112,8 @@ test "$use_pkcs11" = "no" || echo " PKCS#11/Cryptoki support (--with-pkcs11)" - if test "$enable_full_report" = "yes"; then - test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" || \ - echo " IPv6 support (--enable-ipv6)" -- test "X$USE_OPENSSL" = "X" || \ -+ test "X$CRYPTO" = "X" -o "$want_native_pkcs11" = "yes" || \ - echo " OpenSSL cryptography/DNSSEC (--with-openssl)" -- test "$OPENSSL_GOST" != "yes" || \ -- echo " GOST algorithm support (--with-gost)" -- test "$OPENSSL_ECDSA" != "yes" || \ -- echo " ECDSA algorithm support (--with-ecdsa)" - test "X$PYTHON" = "X" || echo " Python tools (--with-python)" - test "X$libxml2_libs" = "X" || echo " XML statistics (--with-libxml2)" - fi -@@ -3923,24 +4146,28 @@ test "$enable_filter" = "yes" || \ - test "$use_gssapi" = "no" && echo " GSS-API (--with-gssapi)" - test "$want_backtrace" = "yes" || \ - echo " Print backtrace on crash (--enable-backtrace)" --test "$use_pkcs11" = "no" && echo " PKCS#11/Cryptoki support (--with-pkcs11)" - --test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" && \ -- echo " IPv6 support (--enable-ipv6)" --test "X$USE_OPENSSL" = "X" && \ -- echo " OpenSSL cryptography/DNSSEC (--with-openssl)" --test "X$USE_OPENSSL" != "X" -a "$OPENSSL_GOST" != "yes" && \ -+test "X$CRYPTO" = "X" -o "$want_native_pkcs11" = "yes" && \ -+ echo " OpenSSL cryptography/DNSSEC (--with-openssl)" -+test "$want_native_pkcs11" != "yes" && \ -+ echo " Native PKCS#11 cryptography/DNSSEC (--enable-native-pkcs11)" -+test "X$CRYPTO" = "X" -o "$OPENSSL_GOST" = "yes" -o "$PKCS11_GOST" = "yes" || \ - echo " GOST algorithm support (--with-gost)" --test "X$USE_OPENSSL" != "X" -a "$OPENSSL_ECDSA" != "yes" && \ -+test "X$CRYPTO" = "X" -o "$OPENSSL_ECDSA" = "yes" -o "$PKCS11_ECDSA" = "yes" || \ - echo " ECDSA algorithm support (--with-ecdsa)" -+test "$use_pkcs11" = "no" && echo " PKCS#11/Cryptoki support (--with-pkcs11)" -+test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" && \ -+ echo " IPv6 support (--enable-ipv6)" - test "X$PYTHON" = "X" && echo " Python tools (--with-python)" - test "X$libxml2_libs" = "X" && echo " XML statistics (--with-libxml2)" - - echo "========================================================================" - --if test "X$USE_OPENSSL" = "X"; then -+if test "X$CRYPTO" = "X"; then - cat << \EOF --BIND is being built without OpenSSL. This means it will not have DNSSEC support. -+BIND 9 is being built without cryptography support. This means it will -+not have DNSSEC support. Use --with-openssl, or --with-pkcs11 and -+--enable-native-pkcs11 to enable cryptography. - EOF - fi - -diff --git a/doc/arm/pkcs11.xml b/doc/arm/pkcs11.xml -index b4e22bb..5388a29 100644 ---- a/doc/arm/pkcs11.xml -+++ b/doc/arm/pkcs11.xml -@@ -20,162 +20,259 @@ - - - -- PKCS #11 (Cryptoki) support -- PKCS #11 (Public Key Cryptography Standard #11) defines a -- platform- independent API for the control of hardware security -- modules (HSMs) and other cryptographic support devices. -- BIND 9 is known to work with two HSMs: The Sun SCA 6000 -- cryptographic acceleration board, tested under Solaris x86, and -- the AEP Keyper network-attached key storage device, tested with -- Debian Linux, Solaris x86 and Windows Server 2003. -+ PKCS#11 (Cryptoki) support -+ -+ PKCS#11 (Public Key Cryptography Standard #11) defines a -+ platform-independent API for the control of hardware security -+ modules (HSMs) and other cryptographic support devices. -+ -+ -+ BIND 9 is known to work with three HSMs: The AEP Keyper, which has -+ been tested with Debian Linux, Solaris x86 and Windows Server 2003; -+ the Thales nShield, tested with Debian Linux; and the Sun SCA 6000 -+ cryptographic acceleration board, tested with Solaris x86. In -+ addition, BIND can be used with SoftHSM, a software-based HSM -+ simulator produced by the OpenDNSSEC project. -+ -+ -+ PKCS#11 makes use of a "provider library": a dynamically loadable -+ library which provides a low-level PKCS#11 interface to drive the HSM -+ hardware. The PKCS#11 provider library comes from the HSM vendor, and -+ it is specific to the HSM to be controlled. -+ -+ -+ There are two available mechanisms for PKCS#11 support in BIND 9: -+ OpenSSL-based PKCS#11 and native PKCS#11. When using the first -+ mechanism, BIND uses a modified version of OpenSSL, which loads -+ the provider library and operates the HSM indirectly; any -+ cryptographic operations not supported by the HSM can be carried -+ out by OpenSSL instead. The second mechanism enables BIND to bypass -+ OpenSSL completely; BIND loads the provider library itself, and uses -+ the PKCS#11 API to drive the HSM directly. -+ - - Prerequisites -- See the HSM vendor documentation for information about -- installing, initializing, testing and troubleshooting the -- HSM. -- BIND 9 uses OpenSSL for cryptography, but stock OpenSSL -- does not yet fully support PKCS #11. However, a PKCS #11 engine -- for OpenSSL is available from the OpenSolaris project. It has -- been modified by ISC to work with with BIND 9, and to provide -- new features such as PIN management and key by -- reference. -- The patched OpenSSL depends on a "PKCS #11 provider". -- This is a shared library object, providing a low-level PKCS #11 -- interface to the HSM hardware. It is dynamically loaded by -- OpenSSL at runtime. The PKCS #11 provider comes from the HSM -- vendor, and is specific to the HSM to be controlled. -- There are two "flavors" of PKCS #11 support provided by -- the patched OpenSSL, one of which must be chosen at -- configuration time. The correct choice depends on the HSM -- hardware: -+ -+ See the documentation provided by your HSM vendor for -+ information about installing, initializing, testing and -+ troubleshooting the HSM. -+ -+ -+ -+ Native PKCS#11 -+ -+ Native PKCS#11 mode will only work with an HSM capable of carrying -+ out every cryptographic operation BIND 9 may -+ need. The HSM's provider library must have a complete implementation -+ of the PKCS#11 API, so that all these functions are accessible. As of -+ this writing, only the Thales nShield HSM and the latest development -+ version of SoftHSM can be used in this fashion. For other HSM's, -+ including the AEP Keyper, Sun SCA 6000 and older versions of SoftHSM, -+ use OpenSSL-based PKCS#11. (Note: As more HSMs become capable of -+ supporting native PKCS#11, it is expected that OpenSSL-based -+ PKCS#11 will eventually be deprecated.) -+ -+ -+ To build BIND with native PKCS#11, configure as follows: -+ -+ -+$ cd bind9 -+$ ./configure --enable-native-pkcs11 \ -+ --with-pkcs11=provider-library-path -+ -+ -+ This will cause all BIND tools, including named -+ and the dnssec-* and pkcs11-* -+ tools, to use the PKCS#11 provider library specified in -+ provider-library-path for cryptography. -+ (The provider library path can be overridden using the -+ in named and the -+ dnssec-* tools, or the in -+ the pkcs11-* tools.) -+ -+ -+ -+ OpenSSL-based PKCS#11 -+ -+ OpenSSL-based PKCS#11 mode uses a modified version of the -+ OpenSSL library; stock OpenSSL does not fully support PKCS#11. -+ ISC provides a patch to OpenSSL to correct this. This patch is -+ based on work originally done by the OpenSolaris project; it has been -+ modified by ISC to provide new features such as PIN management and -+ key-by-reference. -+ -+ -+ There are two "flavors" of PKCS#11 support provided by -+ the patched OpenSSL, one of which must be chosen at -+ configuration time. The correct choice depends on the HSM -+ hardware: -+ - - -- Use 'crypto-accelerator' with HSMs that have hardware -- cryptographic acceleration features, such as the SCA 6000 -- board. This causes OpenSSL to run all supported -- cryptographic operations in the HSM. -+ -+ Use 'crypto-accelerator' with HSMs that have hardware -+ cryptographic acceleration features, such as the SCA 6000 -+ board. This causes OpenSSL to run all supported -+ cryptographic operations in the HSM. -+ - - -- Use 'sign-only' with HSMs that are designed to -- function primarily as secure key storage devices, but lack -- hardware acceleration. These devices are highly secure, but -- are not necessarily any faster at cryptography than the -- system CPU — often, they are slower. It is therefore -- most efficient to use them only for those cryptographic -- functions that require access to the secured private key, -- such as zone signing, and to use the system CPU for all -- other computationally-intensive operations. The AEP Keyper -- is an example of such a device. -+ -+ Use 'sign-only' with HSMs that are designed to -+ function primarily as secure key storage devices, but lack -+ hardware acceleration. These devices are highly secure, but -+ are not necessarily any faster at cryptography than the -+ system CPU — often, they are slower. It is therefore -+ most efficient to use them only for those cryptographic -+ functions that require access to the secured private key, -+ such as zone signing, and to use the system CPU for all -+ other computationally-intensive operations. The AEP Keyper -+ is an example of such a device. -+ - - -- The modified OpenSSL code is included in the BIND 9 release, -- in the form of a context diff against the latest verions of -- OpenSSL. OpenSSL 0.9.8, 1.0.0 and 1.0.1 are supported; there are -- separate diffs for each version. In the examples to follow, -- we use OpenSSL 0.9.8, but the same methods work with OpenSSL 1.0.0 -- and 1.0.1. -+ -+ The modified OpenSSL code is included in the BIND 9 release, -+ in the form of a context diff against the latest verions of -+ OpenSSL. OpenSSL 0.9.8, 1.0.0, and 1.0.1 are supported; there are -+ separate diffs for each version. In the examples to follow, -+ we use OpenSSL 0.9.8, but the same methods work with OpenSSL -+ 1.0.0 and 1.0.1. - - -- The latest OpenSSL versions at the time of the BIND release -- are 0.9.8y, 1.0.0k and 1.0.1e. -- ISC will provide an updated patch as new versions of OpenSSL -+ The latest OpenSSL versions as of this writing (January 2014) -+ are 0.9.8y, 1.0.0l, and 1.0.1f. -+ ISC will provide updated patches as new versions of OpenSSL - are released. The version number in the following examples -- is expected to change. -+ is expected to change. -+ - -- Before building BIND 9 with PKCS #11 support, it will be -- necessary to build OpenSSL with this patch in place and inform -- it of the path to the HSM-specific PKCS #11 provider -- library. -- Obtain OpenSSL 0.9.8s: -- --$ wget http://www.openssl.org/source/openssl-0.9.8s.tar.gz -- -- Extract the tarball: -- --$ tar zxf openssl-0.9.8s.tar.gz -+ Before building BIND 9 with PKCS#11 support, it will be -+ necessary to build OpenSSL with the patch in place, and configure -+ it with the path to your HSM's PKCS#11 provider library. -+ -+ -+ Patching OpenSSL -+ -+$ wget http://www.openssl.org/source/openssl-0.9.8y.tar.gz -+ -+ Extract the tarball: -+ -+$ tar zxf openssl-0.9.8y.tar.gz - -- Apply the patch from the BIND 9 release: -- --$ patch -p1 -d openssl-0.9.8s \ -- < bind9/bin/pkcs11/openssl-0.9.8s-patch -+ Apply the patch from the BIND 9 release: -+ -+$ patch -p1 -d openssl-0.9.8y \ -+ < bind9/bin/pkcs11/openssl-0.9.8y-patch - -- (Note that the patch file may not be compatible with the -- "patch" utility on all operating systems. You may need to -- install GNU patch.) -- When building OpenSSL, place it in a non-standard -- location so that it does not interfere with OpenSSL libraries -- elsewhere on the system. In the following examples, we choose -- to install into "/opt/pkcs11/usr". We will use this location -- when we configure BIND 9. -+ -+ Note that the patch file may not be compatible with the -+ "patch" utility on all operating systems. You may need to -+ install GNU patch. -+ -+ -+ When building OpenSSL, place it in a non-standard -+ location so that it does not interfere with OpenSSL libraries -+ elsewhere on the system. In the following examples, we choose -+ to install into "/opt/pkcs11/usr". We will use this location -+ when we configure BIND 9. -+ -+ -+ Later, when building BIND 9, the location of the custom-built -+ OpenSSL library will need to be specified via configure. -+ -+ - - - Building OpenSSL for the AEP Keyper on Linux -- The AEP Keyper is a highly secure key storage device, -- but does not provide hardware cryptographic acceleration. It -- can carry out cryptographic operations, but it is probably -- slower than your system's CPU. Therefore, we choose the -- 'sign-only' flavor when building OpenSSL. -- The Keyper-specific PKCS #11 provider library is -- delivered with the Keyper software. In this example, we place -- it /opt/pkcs11/usr/lib: -+ -+ The AEP Keyper is a highly secure key storage device, -+ but does not provide hardware cryptographic acceleration. It -+ can carry out cryptographic operations, but it is probably -+ slower than your system's CPU. Therefore, we choose the -+ 'sign-only' flavor when building OpenSSL. -+ -+ -+ The Keyper-specific PKCS#11 provider library is -+ delivered with the Keyper software. In this example, we place -+ it /opt/pkcs11/usr/lib: -+ - - $ cp pkcs11.GCC4.0.2.so.4.05 /opt/pkcs11/usr/lib/libpkcs11.so - -- This library is only available for Linux as a 32-bit -- binary. If we are compiling on a 64-bit Linux system, it is -- necessary to force a 32-bit build, by specifying -m32 in the -- build options. -- Finally, the Keyper library requires threads, so we -- must specify -pthread. -+ -+ This library is only available for Linux as a 32-bit -+ binary. If we are compiling on a 64-bit Linux system, it is -+ necessary to force a 32-bit build, by specifying -m32 in the -+ build options. -+ -+ -+ Finally, the Keyper library requires threads, so we -+ must specify -pthread. -+ - --$ cd openssl-0.9.8s -+$ cd openssl-0.9.8y - $ ./Configure linux-generic32 -m32 -pthread \ - --pk11-libname=/opt/pkcs11/usr/lib/libpkcs11.so \ - --pk11-flavor=sign-only \ - --prefix=/opt/pkcs11/usr - -- After configuring, run "make" -- and "make test". If "make -- test" fails with "pthread_atfork() not found", you forgot to -- add the -pthread above. -+ -+ After configuring, run "make" -+ and "make test". If "make -+ test" fails with "pthread_atfork() not found", you forgot to -+ add the -pthread above. -+ - - - - Building OpenSSL for the SCA 6000 on Solaris -- The SCA-6000 PKCS #11 provider is installed as a system -- library, libpkcs11. It is a true crypto accelerator, up to 4 -- times faster than any CPU, so the flavor shall be -- 'crypto-accelerator'. -- In this example, we are building on Solaris x86 on an -- AMD64 system. -+ -+ The SCA-6000 PKCS#11 provider is installed as a system -+ library, libpkcs11. It is a true crypto accelerator, up to 4 -+ times faster than any CPU, so the flavor shall be -+ 'crypto-accelerator'. -+ -+ -+ In this example, we are building on Solaris x86 on an -+ AMD64 system. -+ - --$ cd openssl-0.9.8s -+$ cd openssl-0.9.8y - $ ./Configure solaris64-x86_64-cc \ - --pk11-libname=/usr/lib/64/libpkcs11.so \ - --pk11-flavor=crypto-accelerator \ - --prefix=/opt/pkcs11/usr - -- (For a 32-bit build, use "solaris-x86-cc" and -- /usr/lib/libpkcs11.so.) -- After configuring, run -- make and -- make test. -+ -+ (For a 32-bit build, use "solaris-x86-cc" and /usr/lib/libpkcs11.so.) -+ -+ -+ After configuring, run -+ make and -+ make test. -+ - - - - Building OpenSSL for SoftHSM -- SoftHSM is a software library provided by the OpenDNSSEC -- project (http://www.opendnssec.org) which provides a PKCS#11 -- interface to a virtual HSM, implemented in the form of encrypted -- data on the local filesystem. It uses the Botan library for -- encryption and SQLite3 for data storage. Though less secure -- than a true HSM, it can provide more secure key storage than -- traditional key files, and can allow you to experiment with -- PKCS#11 when an HSM is not available. -- The SoftHSM cryptographic store must be installed and -- initialized before using it with OpenSSL, and the SOFTHSM_CONF -- environment variable must always point to the SoftHSM configuration -- file: -+ -+ SoftHSM is a software library provided by the OpenDNSSEC -+ project (http://www.opendnssec.org) which provides a PKCS#11 -+ interface to a virtual HSM, implemented in the form of encrypted -+ data on the local filesystem. SoftHSM can be configured to use -+ either OpenSSL or the Botan library for encryption, and SQLite3 -+ for data storage. Though less secure than a true HSM, it can -+ provide more secure key storage than traditional key files, -+ and can allow you to experiment with PKCS#11 when an HSM is -+ not available. -+ -+ -+ The SoftHSM cryptographic store must be installed and -+ initialized before using it with OpenSSL, and the SOFTHSM_CONF -+ environment variable must always point to the SoftHSM configuration -+ file: -+ - - $ cd softhsm-1.3.0 - $ configure --prefix=/opt/pkcs11/usr -@@ -185,25 +282,31 @@ $ export SOFTHSM_CONF=/opt/pkcs11/softhsm.conf - $ echo "0:/opt/pkcs11/softhsm.db" > $SOFTHSM_CONF - $ /opt/pkcs11/usr/bin/softhsm --init-token 0 --slot 0 --label softhsm - -- SoftHSM can perform all cryptographic operations, but -- since it only uses your system CPU, there is no need to use it -- for anything but signing. Therefore, we choose the 'sign-only' -- flavor when building OpenSSL. -+ -+ SoftHSM can perform all cryptographic operations, but -+ since it only uses your system CPU, there is no advantage to using -+ it for anything but signing. Therefore, we choose the 'sign-only' -+ flavor when building OpenSSL. -+ - --$ cd openssl-0.9.8s -+$ cd openssl-0.9.8y - $ ./Configure linux-x86_64 -pthread \ -- --pk11-libname=/opt/pkcs11/usr/lib/libpkcs11.so \ -+ --pk11-libname=/opt/pkcs11/usr/lib/libsofthsm.so \ - --pk11-flavor=sign-only \ - --prefix=/opt/pkcs11/usr - -- After configuring, run "make" -- and "make test". -+ -+ After configuring, run "make" -+ and "make test". -+ - -- Once you have built OpenSSL, run -- "apps/openssl engine pkcs11" to confirm -- that PKCS #11 support was compiled in correctly. The output -- should be one of the following lines, depending on the flavor -- selected: -+ -+ Once you have built OpenSSL, run -+ "apps/openssl engine pkcs11" to confirm -+ that PKCS#11 support was compiled in correctly. The output -+ should be one of the following lines, depending on the flavor -+ selected: -+ - - (pkcs11) PKCS #11 engine support (sign only) - -@@ -211,29 +314,31 @@ $ ./Configure linux-x86_64 -pthread \ - - (pkcs11) PKCS #11 engine support (crypto accelerator) - -- Next, run -- "apps/openssl engine pkcs11 -t". This will -- attempt to initialize the PKCS #11 engine. If it is able to -- do so successfully, it will report -- [ available ]. -- If the output is correct, run -- "make install" which will install the -- modified OpenSSL suite to -- /opt/pkcs11/usr. -- -- -- Building BIND 9 with PKCS#11 -- When building BIND 9, the location of the custom-built -- OpenSSL library must be specified via configure. -+ -+ Next, run -+ "apps/openssl engine pkcs11 -t". This will -+ attempt to initialize the PKCS#11 engine. If it is able to -+ do so successfully, it will report -+ [ available ]. -+ -+ -+ If the output is correct, run -+ "make install" which will install the -+ modified OpenSSL suite to /opt/pkcs11/usr. -+ - - - Configuring BIND 9 for Linux with the AEP Keyper -- To link with the PKCS #11 provider, threads must be -- enabled in the BIND 9 build. -- The PKCS #11 library for the AEP Keyper is currently -- only available as a 32-bit binary. If we are building on a -- 64-bit host, we must force a 32-bit build by adding "-m32" to -- the CC options on the "configure" command line. -+ -+ To link with the PKCS#11 provider, threads must be -+ enabled in the BIND 9 build. -+ -+ -+ The PKCS#11 library for the AEP Keyper is currently -+ only available as a 32-bit binary. If we are building on a -+ 64-bit host, we must force a 32-bit build by adding "-m32" to -+ the CC options on the "configure" command line. -+ - - $ cd ../bind9 - $ ./configure CC="gcc -m32" --enable-threads \ -@@ -244,8 +349,10 @@ $ ./configure CC="gcc -m32" --enable-threads \ - - - Configuring BIND 9 for Solaris with the SCA 6000 -- To link with the PKCS #11 provider, threads must be -- enabled in the BIND 9 build. -+ -+ To link with the PKCS#11 provider, threads must be -+ enabled in the BIND 9 build. -+ - - $ cd ../bind9 - $ ./configure CC="cc -xarch=amd64" --enable-threads \ -@@ -253,11 +360,13 @@ $ ./configure CC="cc -xarch=amd64" --enable-threads \ - --with-pkcs11=/usr/lib/64/libpkcs11.so - - (For a 32-bit build, omit CC="cc -xarch=amd64".) -- If configure complains about OpenSSL not working, you -- may have a 32/64-bit architecture mismatch. Or, you may have -- incorrectly specified the path to OpenSSL (it should be the -- same as the --prefix argument to the OpenSSL -- Configure). -+ -+ If configure complains about OpenSSL not working, you -+ may have a 32/64-bit architecture mismatch. Or, you may have -+ incorrectly specified the path to OpenSSL (it should be the -+ same as the --prefix argument to the OpenSSL -+ Configure). -+ - - - -@@ -266,63 +375,85 @@ $ ./configure CC="cc -xarch=amd64" --enable-threads \ - $ cd ../bind9 - $ ./configure --enable-threads \ - --with-openssl=/opt/pkcs11/usr \ -- --with-pkcs11=/opt/pkcs11/usr/lib/libpkcs11.so -+ --with-pkcs11=/opt/pkcs11/usr/lib/libsofthsm.so - - -- After configuring, run -- "make", -- "make test" and -- "make install". -- (Note: If "make test" fails in the "pkcs11" system test, you may -- have forgotten to set the SOFTHSM_CONF environment variable.) -+ -+ After configuring, run -+ "make", -+ "make test" and -+ "make install". -+ -+ -+ (Note: If "make test" fails in the "pkcs11" system test, you may -+ have forgotten to set the SOFTHSM_CONF environment variable.) -+ - - -- PKCS #11 Tools -- BIND 9 includes a minimal set of tools to operate the -- HSM, including -- pkcs11-keygen to generate a new key pair -- within the HSM, -- pkcs11-list to list objects currently -- available, and -- pkcs11-destroy to remove objects. -- In UNIX/Linux builds, these tools are built only if BIND -- 9 is configured with the --with-pkcs11 option. (NOTE: If -- --with-pkcs11 is set to "yes", rather than to the path of the -- PKCS #11 provider, then the tools will be built but the -- provider will be left undefined. Use the -m option or the -- PKCS11_PROVIDER environment variable to specify the path to the -- provider.) -+ PKCS#11 Tools -+ -+ BIND 9 includes a minimal set of tools to operate the -+ HSM, including -+ pkcs11-keygen to generate a new key pair -+ within the HSM, -+ pkcs11-list to list objects currently -+ available, -+ pkcs11-destroy to remove objects, and -+ pkcs11-tokens to list available tokens. -+ -+ -+ In UNIX/Linux builds, these tools are built only if BIND -+ 9 is configured with the --with-pkcs11 option. (Note: If -+ --with-pkcs11 is set to "yes", rather than to the path of the -+ PKCS#11 provider, then the tools will be built but the -+ provider will be left undefined. Use the -m option or the -+ PKCS11_PROVIDER environment variable to specify the path to the -+ provider.) -+ - - - Using the HSM -- First, we must set up the runtime environment so the -- OpenSSL and PKCS #11 libraries can be loaded: -+ -+ For OpenSSL-based PKCS#11, we must first set up the runtime -+ environment so the OpenSSL and PKCS#11 libraries can be loaded: -+ - - $ export LD_LIBRARY_PATH=/opt/pkcs11/usr/lib:${LD_LIBRARY_PATH} - -- When operating an AEP Keyper, it is also necessary to -- specify the location of the "machine" file, which stores -- information about the Keyper for use by PKCS #11 provider -- library. If the machine file is in -- /opt/Keyper/PKCS11Provider/machine, -- use: -+ -+ This causes named and other binaries to load -+ the OpenSSL library from /opt/pkcs11/usr/lib -+ rather than from the default location. This step is not necessary -+ when using native PKCS#11. -+ -+ -+ Some HSMs require other environment variables to be set. -+ For example, when operating an AEP Keyper, it is necessary to -+ specify the location of the "machine" file, which stores -+ information about the Keyper for use by the provider -+ library. If the machine file is in -+ /opt/Keyper/PKCS11Provider/machine, -+ use: -+ - - $ export KEYPER_LIBRARY_PATH=/opt/Keyper/PKCS11Provider - -- -- These environment variables must be set whenever running -- any tool that uses the HSM, including -- pkcs11-keygen, -- pkcs11-list, -- pkcs11-destroy, -- dnssec-keyfromlabel, -- dnssec-signzone, -- dnssec-keygen(which will use the HSM for -- random number generation), and -- named. -- We can now create and use keys in the HSM. In this case, -- we will create a 2048 bit key and give it the label -- "sample-ksk": -+ -+ Such environment variables must be set whenever running -+ any tool that uses the HSM, including -+ pkcs11-keygen, -+ pkcs11-list, -+ pkcs11-destroy, -+ dnssec-keyfromlabel, -+ dnssec-signzone, -+ dnssec-keygen, and -+ named. -+ -+ -+ We can now create and use keys in the HSM. In this case, -+ we will create a 2048 bit key and give it the label -+ "sample-ksk": -+ - - $ pkcs11-keygen -b 2048 -l sample-ksk - -@@ -333,44 +464,56 @@ Enter PIN: - object[0]: handle 2147483658 class 3 label[8] 'sample-ksk' id[0] - object[1]: handle 2147483657 class 2 label[8] 'sample-ksk' id[0] - -- Before using this key to sign a zone, we must create a -- pair of BIND 9 key files. The "dnssec-keyfromlabel" utility -- does this. In this case, we will be using the HSM key -- "sample-ksk" as the key-signing key for "example.net": -+ -+ Before using this key to sign a zone, we must create a -+ pair of BIND 9 key files. The "dnssec-keyfromlabel" utility -+ does this. In this case, we will be using the HSM key -+ "sample-ksk" as the key-signing key for "example.net": -+ - - $ dnssec-keyfromlabel -l sample-ksk -f KSK example.net - -- The resulting K*.key and K*.private files can now be used -- to sign the zone. Unlike normal K* files, which contain both -- public and private key data, these files will contain only the -- public key data, plus an identifier for the private key which -- remains stored within the HSM. The HSM handles signing with the -- private key. -- If you wish to generate a second key in the HSM for use -- as a zone-signing key, follow the same procedure above, using a -- different keylabel, a smaller key size, and omitting "-f KSK" -- from the dnssec-keyfromlabel arguments: -+ -+ The resulting K*.key and K*.private files can now be used -+ to sign the zone. Unlike normal K* files, which contain both -+ public and private key data, these files will contain only the -+ public key data, plus an identifier for the private key which -+ remains stored within the HSM. Signing with the private key takes -+ place inside the HSM. -+ -+ -+ If you wish to generate a second key in the HSM for use -+ as a zone-signing key, follow the same procedure above, using a -+ different keylabel, a smaller key size, and omitting "-f KSK" -+ from the dnssec-keyfromlabel arguments: -+ - - $ pkcs11-keygen -b 1024 -l sample-zsk - $ dnssec-keyfromlabel -l sample-zsk example.net - -- Alternatively, you may prefer to generate a conventional -- on-disk key, using dnssec-keygen: -+ -+ Alternatively, you may prefer to generate a conventional -+ on-disk key, using dnssec-keygen: -+ - - $ dnssec-keygen example.net - -- This provides less security than an HSM key, but since -- HSMs can be slow or cumbersome to use for security reasons, it -- may be more efficient to reserve HSM keys for use in the less -- frequent key-signing operation. The zone-signing key can be -- rolled more frequently, if you wish, to compensate for a -- reduction in key security. -- Now you can sign the zone. (Note: If not using the -S -- option to -- dnssec-signzone, it will be necessary to add -- the contents of both -- K*.key files to the zone master file before -- signing it.) -+ -+ This provides less security than an HSM key, but since -+ HSMs can be slow or cumbersome to use for security reasons, it -+ may be more efficient to reserve HSM keys for use in the less -+ frequent key-signing operation. The zone-signing key can be -+ rolled more frequently, if you wish, to compensate for a -+ reduction in key security. (Note: When using native PKCS#11, -+ there is no speed advantage to using on-disk keys, as cryptographic -+ operations will be done by the HSM regardless.) -+ -+ -+ Now you can sign the zone. (Note: If not using the -S -+ option to dnssec-signzone, it will be -+ necessary to add the contents of both K*.key -+ files to the zone master file before signing it.) -+ - - $ dnssec-signzone -S example.net - Enter PIN: -@@ -383,36 +526,50 @@ example.net.signed - - - Specifying the engine on the command line -- The OpenSSL engine can be specified in -- named and all of the BIND -- dnssec-* tools by using the "-E -- <engine>" command line option. If BIND 9 is built with -- the --with-pkcs11 option, this option defaults to "pkcs11". -- Specifying the engine will generally not be necessary unless -- for some reason you wish to use a different OpenSSL -- engine. -- If you wish to disable use of the "pkcs11" engine — -- for troubleshooting purposes, or because the HSM is unavailable -- — set the engine to the empty string. For example: -+ -+ When using OpenSSL-based PKCS#11, the "engine" to be used by -+ OpenSSL can be specified in named and all of -+ the BIND dnssec-* tools by using the "-E -+ <engine>" command line option. If BIND 9 is built with -+ the --with-pkcs11 option, this option defaults to "pkcs11". -+ Specifying the engine will generally not be necessary unless -+ for some reason you wish to use a different OpenSSL -+ engine. -+ -+ -+ If you wish to disable use of the "pkcs11" engine — -+ for troubleshooting purposes, or because the HSM is unavailable -+ — set the engine to the empty string. For example: -+ - - $ dnssec-signzone -E '' -S example.net - -- This causes -- dnssec-signzone to run as if it were compiled -- without the --with-pkcs11 option. -+ -+ This causes -+ dnssec-signzone to run as if it were compiled -+ without the --with-pkcs11 option. -+ -+ -+ When built with native PKCS#11 mode, the "engine" option has a -+ different meaning: it specifies the path to the PKCS#11 provider -+ library. This may be useful when testing a new provider library. -+ - - - Running named with automatic zone re-signing -- If you want -- named to dynamically re-sign zones using HSM -- keys, and/or to to sign new records inserted via nsupdate, then -- named must have access to the HSM PIN. This can be accomplished -- by placing the PIN into the openssl.cnf file (in the above -- examples, -- /opt/pkcs11/usr/ssl/openssl.cnf). -- The location of the openssl.cnf file can be overridden by -- setting the OPENSSL_CONF environment variable before running -- named. -+ -+ If you want named to dynamically re-sign zones -+ using HSM keys, and/or to to sign new records inserted via nsupdate, -+ then named must have access to the HSM PIN. In OpenSSL-based PKCS#11, -+ this is accomplished by placing the PIN into the openssl.cnf file -+ (in the above examples, -+ /opt/pkcs11/usr/ssl/openssl.cnf). -+ -+ -+ The location of the openssl.cnf file can be overridden by -+ setting the OPENSSL_CONF environment variable before running -+ named. -+ - Sample openssl.cnf: - - openssl_conf = openssl_def -@@ -423,22 +580,25 @@ $ dnssec-signzone -E '' -S example.net - [ pkcs11_section ] - PIN = <PLACE PIN HERE> - -- This will also allow the dnssec-* tools to access the HSM -- without PIN entry. (The pkcs11-* tools access the HSM directly, -- not via OpenSSL, so a PIN will still be required to use -- them.) -- -+ -+ This will also allow the dnssec-* tools to access the HSM -+ without PIN entry. (The pkcs11-* tools access the HSM directly, -+ not via OpenSSL, so a PIN will still be required to use -+ them.) -+ -+ -+ In native PKCS#11 mode, the PIN can be provided in a file specified -+ as an attribute of the key's label. For example, if a key had the label -+ pkcs11:object=local-zsk;pin-source=/etc/hsmpin", -+ then the PIN would be read from the file -+ /etc/hsmpin. -+ - -- Placing the HSM's PIN in a text file in -- this manner may reduce the security advantage of using an -- HSM. Be sure this is what you want to do before configuring -- OpenSSL in this way. -+ -+ Placing the HSM's PIN in a text file in this manner may reduce the -+ security advantage of using an HSM. Be sure this is what you want to -+ do before configuring OpenSSL in this way. -+ - - -- -- - -diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in -index 0c5e93b..41fac95 100644 ---- a/lib/dns/Makefile.in -+++ b/lib/dns/Makefile.in -@@ -27,10 +27,10 @@ top_srcdir = @top_srcdir@ - - USE_ISC_SPNEGO = @USE_ISC_SPNEGO@ - --CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} \ -- ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ -+CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} \ -+ @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ - --CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@ ${USE_ISC_SPNEGO} -+CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@ ${USE_ISC_SPNEGO} - - CWARNINGS = - -@@ -47,7 +47,10 @@ OPENSSLLINKOBJS = openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \ - opensslecdsa_link.@O@ @OPENSSLGOSTLINKOBJS@ \ - opensslrsa_link.@O@ - --DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \ -+PKCS11LINKOBJS = pkcs11dh_link.@O@ pkcs11dsa_link.@O@ pkcs11rsa_link.@O@ \ -+ pkcs11ecdsa_link.@O@ pkcs11gost_link.@O@ pkcs11.@O@ -+ -+DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ @PKCS11LINKOBJS@ \ - dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \ - gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@ - -@@ -79,7 +82,10 @@ OPENSSLGOSTLINKSRCS = opensslgost_link.c - OPENSSLLINKSRCS = openssl_link.c openssldh_link.c openssldsa_link.c \ - opensslecdsa_link.c @OPENSSLGOSTLINKSRCS@ opensslrsa_link.c - --DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \ -+PKCS11LINKSRCS = pkcs11dh_link.c pkcs11dsa_link.c pkcs11rsa_link.c \ -+ pkcs11ecdsa_link.c pkcs11gost_link.c pkcs11.c -+ -+DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ @PKCS11LINKSRCS@ \ - dst_api.c dst_lib.c dst_parse.c \ - dst_result.c gssapi_link.c gssapictx.c \ - hmac_link.c key.c -diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c -index cf97404..00a0080 100644 ---- a/lib/dns/dnssec.c -+++ b/lib/dns/dnssec.c -@@ -275,7 +275,8 @@ dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, - if (ret != ISC_R_SUCCESS) - goto cleanup_databuf; - -- ret = dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx); -+ ret = dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_DNSSEC, ISC_TRUE, &ctx); - if (ret != ISC_R_SUCCESS) - goto cleanup_databuf; - -@@ -470,7 +471,8 @@ dns_dnssec_verify3(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, - } - - again: -- ret = dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx); -+ ret = dst_context_create4(key, mctx, DNS_LOGCATEGORY_DNSSEC, -+ ISC_FALSE, maxbits, &ctx); - if (ret != ISC_R_SUCCESS) - goto cleanup_struct; - -@@ -872,7 +874,8 @@ dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) { - - isc_buffer_init(&databuf, data, sizeof(data)); - -- RETERR(dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx)); -+ RETERR(dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_DNSSEC, ISC_TRUE, &ctx)); - - /* - * Digest the fields of the SIG - we can cheat and use -@@ -1022,7 +1025,8 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, - goto failure; - } - -- RETERR(dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx)); -+ RETERR(dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_DNSSEC, ISC_FALSE, &ctx)); - - /* - * Digest the SIG(0) record, except for the signature. -diff --git a/lib/dns/ds.c b/lib/dns/ds.c -index e72ecbb..b51476b 100644 ---- a/lib/dns/ds.c -+++ b/lib/dns/ds.c -@@ -38,11 +38,8 @@ - - #include - --#ifdef HAVE_OPENSSL_GOST --#include --#include -- --extern const EVP_MD * EVP_gost(void); -+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) -+#include "dst_gost.h" - #endif - - isc_result_t -@@ -59,9 +56,8 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, - isc_sha1_t sha1; - isc_sha256_t sha256; - isc_sha384_t sha384; --#ifdef HAVE_OPENSSL_GOST -- EVP_MD_CTX ctx; -- const EVP_MD *md; -+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) -+ isc_gost_t gost; - #endif - - REQUIRE(key != NULL); -@@ -88,29 +84,23 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, - isc_sha1_final(&sha1, digest); - break; - --#ifdef HAVE_OPENSSL_GOST --#define CHECK(x) \ -- if ((x) != 1) { \ -- EVP_MD_CTX_cleanup(&ctx); \ -- return (DST_R_CRYPTOFAILURE); \ -- } -+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) -+#define RETERR(x) do { \ -+ isc_result_t ret = (x); \ -+ if (ret != ISC_R_SUCCESS) { \ -+ isc_gost_invalidate(&gost); \ -+ return (ret); \ -+ } \ -+} while (0) - - case DNS_DSDIGEST_GOST: -- md = EVP_gost(); -- if (md == NULL) -- return (DST_R_CRYPTOFAILURE); -- EVP_MD_CTX_init(&ctx); -- CHECK(EVP_DigestInit(&ctx, md)); -+ RETERR(isc_gost_init(&gost)); - dns_name_toregion(name, &r); -- CHECK(EVP_DigestUpdate(&ctx, -- (const void *) r.base, -- (size_t) r.length)); -+ RETERR(isc_gost_update(&gost, r.base, r.length)); - dns_rdata_toregion(key, &r); - INSIST(r.length >= 4); -- CHECK(EVP_DigestUpdate(&ctx, -- (const void *) r.base, -- (size_t) r.length)); -- CHECK(EVP_DigestFinal(&ctx, digest, NULL)); -+ RETERR(isc_gost_update(&gost, r.base, r.length)); -+ RETERR(isc_gost_final(&gost, digest)); - break; - #endif - -@@ -147,7 +137,7 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, - ds.length = ISC_SHA1_DIGESTLENGTH; - break; - --#ifdef HAVE_OPENSSL_GOST -+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) - case DNS_DSDIGEST_GOST: - ds.length = ISC_GOST_DIGESTLENGTH; - break; -diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c -index 6416273..d96473f 100644 ---- a/lib/dns/dst_api.c -+++ b/lib/dns/dst_api.c -@@ -75,9 +75,7 @@ - #define DST_AS_STR(t) ((t).value.as_textregion.base) - - static dst_func_t *dst_t_func[DST_MAX_ALGS]; --#ifdef BIND9 - static isc_entropy_t *dst_entropy_pool = NULL; --#endif - static unsigned int dst_entropy_flags = 0; - static isc_boolean_t dst_initialized = ISC_FALSE; - -@@ -169,7 +167,7 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, - #endif - REQUIRE(dst_initialized == ISC_FALSE); - --#ifndef OPENSSL -+#if !defined(OPENSSL) && !defined(PKCS11CRYPTO) - UNUSED(engine); - #endif - -@@ -234,7 +232,24 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, - RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256])); - RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); - #endif --#endif /* OPENSSL */ -+#elif PKCS11CRYPTO -+ RETERR(dst__pkcs11_init(mctx, engine)); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5])); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1])); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1])); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256])); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512])); -+ RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_DSA])); -+ RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); -+ RETERR(dst__pkcs11dh_init(&dst_t_func[DST_ALG_DH])); -+#ifdef HAVE_PKCS11_ECDSA -+ RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256])); -+ RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); -+#endif -+#ifdef HAVE_PKCS11_GOST -+ RETERR(dst__pkcs11gost_init(&dst_t_func[DST_ALG_ECCGOST])); -+#endif -+#endif /* if OPENSSL, elif PKCS11CRYPTO */ - #ifdef GSSAPI - RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI])); - #endif -@@ -259,7 +274,9 @@ dst_lib_destroy(void) { - dst_t_func[i]->cleanup(); - #ifdef OPENSSL - dst__openssl_destroy(); --#endif -+#elif PKCS11CRYPTO -+ (void) dst__pkcs11_destroy(); -+#endif /* if OPENSSL, elif PKCS11CRYPTO */ - if (dst__memory_pool != NULL) - isc_mem_detach(&dst__memory_pool); - #ifdef BIND9 -@@ -279,13 +296,31 @@ dst_algorithm_supported(unsigned int alg) { - - isc_result_t - dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) { -- return (dst_context_create2(key, mctx, -- DNS_LOGCATEGORY_GENERAL, dctxp)); -+ return (dst_context_create4(key, mctx, DNS_LOGCATEGORY_GENERAL, -+ ISC_TRUE, 0, dctxp)); - } - - isc_result_t - dst_context_create2(dst_key_t *key, isc_mem_t *mctx, -- isc_logcategory_t *category, dst_context_t **dctxp) { -+ isc_logcategory_t *category, dst_context_t **dctxp) -+{ -+ return (dst_context_create4(key, mctx, category, ISC_TRUE, 0, dctxp)); -+} -+ -+isc_result_t -+dst_context_create3(dst_key_t *key, isc_mem_t *mctx, -+ isc_logcategory_t *category, isc_boolean_t useforsigning, -+ dst_context_t **dctxp) -+{ -+ return (dst_context_create4(key, mctx, category, -+ useforsigning, 0, dctxp)); -+} -+ -+isc_result_t -+dst_context_create4(dst_key_t *key, isc_mem_t *mctx, -+ isc_logcategory_t *category, isc_boolean_t useforsigning, -+ int maxbits, dst_context_t **dctxp) -+{ - dst_context_t *dctx; - isc_result_t result; - -@@ -294,7 +329,7 @@ dst_context_create2(dst_key_t *key, isc_mem_t *mctx, - REQUIRE(mctx != NULL); - REQUIRE(dctxp != NULL && *dctxp == NULL); - -- if (key->func->createctx == NULL) -+ if (key->func->createctx == NULL && key->func->createctx2 == NULL) - return (DST_R_UNSUPPORTEDALG); - if (key->keydata.generic == NULL) - return (DST_R_NULLKEY); -@@ -305,7 +340,14 @@ dst_context_create2(dst_key_t *key, isc_mem_t *mctx, - dctx->key = key; - dctx->mctx = mctx; - dctx->category = category; -- result = key->func->createctx(key, dctx); -+ if (useforsigning) -+ dctx->use = DO_SIGN; -+ else -+ dctx->use = DO_VERIFY; -+ if (key->func->createctx2 != NULL) -+ result = key->func->createctx2(key, maxbits, dctx); -+ else -+ result = key->func->createctx(key, dctx); - if (result != ISC_R_SUCCESS) { - isc_mem_put(mctx, dctx, sizeof(dst_context_t)); - return (result); -@@ -1796,7 +1838,7 @@ algorithm_status(unsigned int alg) { - - if (dst_algorithm_supported(alg)) - return (ISC_R_SUCCESS); --#ifndef OPENSSL -+#if !defined(OPENSSL) && !defined(PKCS11CRYPTO) - if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || - alg == DST_ALG_DSA || alg == DST_ALG_DH || - alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA || -@@ -1842,11 +1884,18 @@ dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { - - if (len == 0) - return (ISC_R_SUCCESS); -+ -+#ifdef PKCS11CRYPTO -+ UNUSED(pseudo); -+ UNUSED(flags); -+ return (pk11_rand_bytes(buf, len)); -+#else /* PKCS11CRYPTO */ - if (pseudo) - flags &= ~ISC_ENTROPY_GOODONLY; - else - flags |= ISC_ENTROPY_BLOCKING; - return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags)); -+#endif /* PKCS11CRYPTO */ - #else - UNUSED(buf); - UNUSED(len); -@@ -1858,7 +1907,7 @@ dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { - - unsigned int - dst__entropy_status(void) { --#ifdef BIND9 -+#ifndef PKCS11CRYPTO - #ifdef GSSAPI - unsigned int flags = dst_entropy_flags; - isc_result_t ret; -diff --git a/lib/dns/dst_gost.h b/lib/dns/dst_gost.h -new file mode 100644 -index 0000000..37a4200 ---- /dev/null -+++ b/lib/dns/dst_gost.h -@@ -0,0 +1,57 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef DST_GOST_H -+#define DST_GOST_H 1 -+ -+#include -+#include -+#include -+ -+#define ISC_GOST_DIGESTLENGTH 32U -+ -+#ifdef HAVE_OPENSSL_GOST -+#include -+ -+typedef EVP_MD_CTX isc_gost_t; -+#endif -+#ifdef HAVE_PKCS11_GOST -+#include -+ -+typedef pk11_context_t isc_gost_t; -+#endif -+ -+ISC_LANG_BEGINDECLS -+ -+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) -+ -+isc_result_t -+isc_gost_init(isc_gost_t *ctx); -+ -+void -+isc_gost_invalidate(isc_gost_t *ctx); -+ -+isc_result_t -+isc_gost_update(isc_gost_t *ctx, const unsigned char *data, unsigned int len); -+ -+isc_result_t -+isc_gost_final(isc_gost_t *ctx, unsigned char *digest); -+ -+ISC_LANG_ENDDECLS -+ -+#endif /* HAVE_OPENSSL_GOST || HAVE_PKCS11_GOST */ -+ -+#endif /* DST_GOST_H */ -diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h -index 49ca424..b15135e 100644 ---- a/lib/dns/dst_internal.h -+++ b/lib/dns/dst_internal.h -@@ -84,6 +84,12 @@ typedef struct dst_hmacsha256_key dst_hmacsha256_key_t; - typedef struct dst_hmacsha384_key dst_hmacsha384_key_t; - typedef struct dst_hmacsha512_key dst_hmacsha512_key_t; - -+/*% -+ * Indicate whether a DST context will be used for signing -+ * or for verification -+ */ -+typedef enum { DO_SIGN, DO_VERIFY } dst_use_t; -+ - /*% DST Key Structure */ - struct dst_key { - unsigned int magic; -@@ -112,6 +118,8 @@ struct dst_key { - DSA *dsa; - DH *dh; - EVP_PKEY *pkey; -+#elif PKCS11CRYPTO -+ pk11_object_t *pkey; - #endif - dst_hmacmd5_key_t *hmacmd5; - dst_hmacsha1_key_t *hmacsha1; -@@ -139,6 +147,7 @@ struct dst_key { - - struct dst_context { - unsigned int magic; -+ dst_use_t use; - dst_key_t *key; - isc_mem_t *mctx; - isc_logcategory_t *category; -@@ -157,6 +166,8 @@ struct dst_context { - isc_hmacsha512_t *hmacsha512ctx; - #ifdef OPENSSL - EVP_MD_CTX *evp_md_ctx; -+#elif PKCS11CRYPTO -+ pk11_context_t *pk11_ctx; - #endif - } ctxdata; - }; -@@ -166,6 +177,8 @@ struct dst_func { - * Context functions - */ - isc_result_t (*createctx)(dst_key_t *key, dst_context_t *dctx); -+ isc_result_t (*createctx2)(dst_key_t *key, int maxbits, -+ dst_context_t *dctx); - void (*destroyctx)(dst_context_t *dctx); - isc_result_t (*adddata)(dst_context_t *dctx, const isc_region_t *data); - -@@ -209,6 +222,7 @@ struct dst_func { - * Initializers - */ - isc_result_t dst__openssl_init(const char *engine); -+#define dst__pkcs11_init pk11_initialize - - isc_result_t dst__hmacmd5_init(struct dst_func **funcp); - isc_result_t dst__hmacsha1_init(struct dst_func **funcp); -@@ -218,20 +232,30 @@ isc_result_t dst__hmacsha384_init(struct dst_func **funcp); - isc_result_t dst__hmacsha512_init(struct dst_func **funcp); - isc_result_t dst__opensslrsa_init(struct dst_func **funcp, - unsigned char algorithm); -+isc_result_t dst__pkcs11rsa_init(struct dst_func **funcp); - isc_result_t dst__openssldsa_init(struct dst_func **funcp); -+isc_result_t dst__pkcs11dsa_init(struct dst_func **funcp); - isc_result_t dst__openssldh_init(struct dst_func **funcp); -+isc_result_t dst__pkcs11dh_init(struct dst_func **funcp); - isc_result_t dst__gssapi_init(struct dst_func **funcp); -+#ifdef HAVE_OPENSSL_ECDSA -+isc_result_t dst__opensslecdsa_init(struct dst_func **funcp); -+#endif -+#ifdef HAVE_PKCS11_ECDSA -+isc_result_t dst__pkcs11ecdsa_init(struct dst_func **funcp); -+#endif - #ifdef HAVE_OPENSSL_GOST - isc_result_t dst__opensslgost_init(struct dst_func **funcp); - #endif --#ifdef HAVE_OPENSSL_ECDSA --isc_result_t dst__opensslecdsa_init(struct dst_func **funcp); -+#ifdef HAVE_PKCS11_GOST -+isc_result_t dst__pkcs11gost_init(struct dst_func **funcp); - #endif - - /*% - * Destructors - */ - void dst__openssl_destroy(void); -+#define dst__pkcs11_destroy pk11_finalize - - /*% - * Memory allocators using the DST memory pool. -diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c -index 6348cc1..ec622d9 100644 ---- a/lib/dns/dst_parse.c -+++ b/lib/dns/dst_parse.c -@@ -93,7 +93,6 @@ static struct parse_map map[] = { - {TAG_RSA_COEFFICIENT, "Coefficient:"}, - {TAG_RSA_ENGINE, "Engine:" }, - {TAG_RSA_LABEL, "Label:" }, -- {TAG_RSA_PIN, "PIN:" }, - - {TAG_DH_PRIME, "Prime(p):"}, - {TAG_DH_GENERATOR, "Generator(g):"}, -@@ -107,8 +106,11 @@ static struct parse_map map[] = { - {TAG_DSA_PUBLIC, "Public_value(y):"}, - - {TAG_GOST_PRIVASN1, "GostAsn1:"}, -+ {TAG_GOST_PRIVRAW, "PrivateKey:"}, - - {TAG_ECDSA_PRIVATEKEY, "PrivateKey:"}, -+ {TAG_ECDSA_ENGINE, "Engine:" }, -+ {TAG_ECDSA_LABEL, "Label:" }, - - {TAG_HMACMD5_KEY, "Key:"}, - {TAG_HMACMD5_BITS, "Bits:"}, -@@ -262,22 +264,42 @@ check_gost(const dst_private_t *priv, isc_boolean_t external) { - - if (priv->nelements != GOST_NTAGS) - return (-1); -- if (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) -+ if ((priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) && -+ (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 1))) - return (-1); - return (0); - } - - static int - check_ecdsa(const dst_private_t *priv, isc_boolean_t external) { -+ int i, j; -+ isc_boolean_t have[ECDSA_NTAGS]; -+ isc_boolean_t ok; -+ unsigned int mask; - - if (external) - return ((priv->nelements == 0) ? 0 : -1); - -- if (priv->nelements != ECDSA_NTAGS) -- return (-1); -- if (priv->elements[0].tag != TAG(DST_ALG_ECDSA256, 0)) -- return (-1); -- return (0); -+ for (i = 0; i < ECDSA_NTAGS; i++) -+ have[i] = ISC_FALSE; -+ for (j = 0; j < priv->nelements; j++) { -+ for (i = 0; i < ECDSA_NTAGS; i++) -+ if (priv->elements[j].tag == TAG(DST_ALG_ECDSA256, i)) -+ break; -+ if (i == ECDSA_NTAGS) -+ return (-1); -+ have[i] = ISC_TRUE; -+ } -+ -+ mask = ~0; -+ mask <<= sizeof(mask) * 8 - TAG_SHIFT; -+ mask >>= sizeof(mask) * 8 - TAG_SHIFT; -+ -+ if (have[TAG_ECDSA_ENGINE & mask]) -+ ok = have[TAG_ECDSA_LABEL & mask]; -+ else -+ ok = have[TAG_ECDSA_PRIVATEKEY & mask]; -+ return (ok ? 0 : -1 ); - } - - static int -diff --git a/lib/dns/dst_parse.h b/lib/dns/dst_parse.h -index f048bf0..a8a5641 100644 ---- a/lib/dns/dst_parse.h -+++ b/lib/dns/dst_parse.h -@@ -63,7 +63,6 @@ - #define TAG_RSA_COEFFICIENT ((DST_ALG_RSAMD5 << TAG_SHIFT) + 7) - #define TAG_RSA_ENGINE ((DST_ALG_RSAMD5 << TAG_SHIFT) + 8) - #define TAG_RSA_LABEL ((DST_ALG_RSAMD5 << TAG_SHIFT) + 9) --#define TAG_RSA_PIN ((DST_ALG_RSAMD5 << TAG_SHIFT) + 10) - - #define DH_NTAGS 4 - #define TAG_DH_PRIME ((DST_ALG_DH << TAG_SHIFT) + 0) -@@ -80,9 +79,12 @@ - - #define GOST_NTAGS 1 - #define TAG_GOST_PRIVASN1 ((DST_ALG_ECCGOST << TAG_SHIFT) + 0) -+#define TAG_GOST_PRIVRAW ((DST_ALG_ECCGOST << TAG_SHIFT) + 1) - --#define ECDSA_NTAGS 1 -+#define ECDSA_NTAGS 4 - #define TAG_ECDSA_PRIVATEKEY ((DST_ALG_ECDSA256 << TAG_SHIFT) + 0) -+#define TAG_ECDSA_ENGINE ((DST_ALG_ECDSA256 << TAG_SHIFT) + 1) -+#define TAG_ECDSA_LABEL ((DST_ALG_ECDSA256 << TAG_SHIFT) + 2) - - #define OLD_HMACMD5_NTAGS 1 - #define HMACMD5_NTAGS 2 -diff --git a/lib/dns/dst_pkcs11.h b/lib/dns/dst_pkcs11.h -new file mode 100644 -index 0000000..1c35b6b ---- /dev/null -+++ b/lib/dns/dst_pkcs11.h -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef DST_PKCS11_H -+#define DST_PKCS11_H 1 -+ -+#include -+#include -+#include -+ -+ISC_LANG_BEGINDECLS -+ -+isc_result_t -+dst__pkcs11_toresult(const char *funcname, const char *file, int line, -+ isc_result_t fallback, CK_RV rv); -+ -+#define PK11_CALL(func, args, fallback) \ -+ ((void) (((rv = (func) args) == CKR_OK) || \ -+ ((ret = dst__pkcs11_toresult(#func, __FILE__, __LINE__, \ -+ fallback, rv)), 0))) -+ -+#define PK11_RET(func, args, fallback) \ -+ ((void) (((rv = (func) args) == CKR_OK) || \ -+ ((ret = dst__pkcs11_toresult(#func, __FILE__, __LINE__, \ -+ fallback, rv)), 0))); \ -+ if (rv != CKR_OK) goto err; -+ -+ISC_LANG_ENDDECLS -+ -+#endif /* DST_PKCS11_H */ -diff --git a/lib/dns/dst_result.c b/lib/dns/dst_result.c -index 30aa1fa..79fa7d3 100644 ---- a/lib/dns/dst_result.c -+++ b/lib/dns/dst_result.c -@@ -50,7 +50,8 @@ static const char *text[DST_R_NRESULTS] = { - "failure computing a shared secret", /*%< 18 */ - "no randomness available", /*%< 19 */ - "bad key type", /*%< 20 */ -- "no engine" /*%< 21 */ -+ "no engine", /*%< 21 */ -+ "illegal operation for an external key",/*%< 22 */ - }; - - #define DST_RESULT_RESULTSET 2 -diff --git a/lib/dns/gssapi_link.c b/lib/dns/gssapi_link.c -index 5ad81cd..1c35959 100644 ---- a/lib/dns/gssapi_link.c -+++ b/lib/dns/gssapi_link.c -@@ -358,6 +358,7 @@ gssapi_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) { - - static dst_func_t gssapi_functions = { - gssapi_create_signverify_ctx, -+ NULL, /*%< createctx2 */ - gssapi_destroy_signverify_ctx, - gssapi_adddata, - gssapi_sign, -diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c -index 1f1a0ca..7a56c79 100644 ---- a/lib/dns/hmac_link.c -+++ b/lib/dns/hmac_link.c -@@ -282,6 +282,9 @@ hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (result != ISC_R_SUCCESS) - return (result); - -+ if (key->external) -+ result = DST_R_EXTERNALKEY; -+ - key->key_bits = 0; - for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) { - switch (priv.elements[i].tag) { -@@ -310,6 +313,7 @@ hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - static dst_func_t hmacmd5_functions = { - hmacmd5_createctx, -+ NULL, /*%< createctx2 */ - hmacmd5_destroyctx, - hmacmd5_adddata, - hmacmd5_sign, -@@ -528,6 +532,9 @@ hmacsha1_tofile(const dst_key_t *key, const char *directory) { - if (key->keydata.hmacsha1 == NULL) - return (DST_R_NULLKEY); - -+ if (key->external) -+ return (DST_R_EXTERNALKEY); -+ - hkey = key->keydata.hmacsha1; - - priv.elements[cnt].tag = TAG_HMACSHA1_KEY; -@@ -559,8 +566,11 @@ hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (result != ISC_R_SUCCESS) - return (result); - -+ if (key->external) -+ result = DST_R_EXTERNALKEY; -+ - key->key_bits = 0; -- for (i = 0; i < priv.nelements; i++) { -+ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) { - switch (priv.elements[i].tag) { - case TAG_HMACSHA1_KEY: - isc_buffer_init(&b, priv.elements[i].data, -@@ -587,6 +597,7 @@ hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - static dst_func_t hmacsha1_functions = { - hmacsha1_createctx, -+ NULL, /*%< createctx2 */ - hmacsha1_destroyctx, - hmacsha1_adddata, - hmacsha1_sign, -@@ -807,6 +818,9 @@ hmacsha224_tofile(const dst_key_t *key, const char *directory) { - if (key->keydata.hmacsha224 == NULL) - return (DST_R_NULLKEY); - -+ if (key->external) -+ return (DST_R_EXTERNALKEY); -+ - hkey = key->keydata.hmacsha224; - - priv.elements[cnt].tag = TAG_HMACSHA224_KEY; -@@ -838,6 +852,9 @@ hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (result != ISC_R_SUCCESS) - return (result); - -+ if (key->external) -+ result = DST_R_EXTERNALKEY; -+ - key->key_bits = 0; - for (i = 0; i < priv.nelements; i++) { - switch (priv.elements[i].tag) { -@@ -866,6 +883,7 @@ hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - static dst_func_t hmacsha224_functions = { - hmacsha224_createctx, -+ NULL, /*%< createctx2 */ - hmacsha224_destroyctx, - hmacsha224_adddata, - hmacsha224_sign, -@@ -1086,6 +1104,9 @@ hmacsha256_tofile(const dst_key_t *key, const char *directory) { - if (key->keydata.hmacsha256 == NULL) - return (DST_R_NULLKEY); - -+ if (key->external) -+ return (DST_R_EXTERNALKEY); -+ - hkey = key->keydata.hmacsha256; - - priv.elements[cnt].tag = TAG_HMACSHA256_KEY; -@@ -1117,8 +1138,11 @@ hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (result != ISC_R_SUCCESS) - return (result); - -+ if (key->external) -+ result = DST_R_EXTERNALKEY; -+ - key->key_bits = 0; -- for (i = 0; i < priv.nelements; i++) { -+ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) { - switch (priv.elements[i].tag) { - case TAG_HMACSHA256_KEY: - isc_buffer_init(&b, priv.elements[i].data, -@@ -1145,6 +1169,7 @@ hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - static dst_func_t hmacsha256_functions = { - hmacsha256_createctx, -+ NULL, /*%< createctx2 */ - hmacsha256_destroyctx, - hmacsha256_adddata, - hmacsha256_sign, -@@ -1365,6 +1390,9 @@ hmacsha384_tofile(const dst_key_t *key, const char *directory) { - if (key->keydata.hmacsha384 == NULL) - return (DST_R_NULLKEY); - -+ if (key->external) -+ return (DST_R_EXTERNALKEY); -+ - hkey = key->keydata.hmacsha384; - - priv.elements[cnt].tag = TAG_HMACSHA384_KEY; -@@ -1396,8 +1424,11 @@ hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (result != ISC_R_SUCCESS) - return (result); - -+ if (key->external) -+ result = DST_R_EXTERNALKEY; -+ - key->key_bits = 0; -- for (i = 0; i < priv.nelements; i++) { -+ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) { - switch (priv.elements[i].tag) { - case TAG_HMACSHA384_KEY: - isc_buffer_init(&b, priv.elements[i].data, -@@ -1424,6 +1455,7 @@ hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - static dst_func_t hmacsha384_functions = { - hmacsha384_createctx, -+ NULL, /*%< createctx2 */ - hmacsha384_destroyctx, - hmacsha384_adddata, - hmacsha384_sign, -@@ -1644,6 +1676,9 @@ hmacsha512_tofile(const dst_key_t *key, const char *directory) { - if (key->keydata.hmacsha512 == NULL) - return (DST_R_NULLKEY); - -+ if (key->external) -+ return (DST_R_EXTERNALKEY); -+ - hkey = key->keydata.hmacsha512; - - priv.elements[cnt].tag = TAG_HMACSHA512_KEY; -@@ -1675,8 +1710,11 @@ hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (result != ISC_R_SUCCESS) - return (result); - -+ if (key->external) -+ result = DST_R_EXTERNALKEY; -+ - key->key_bits = 0; -- for (i = 0; i < priv.nelements; i++) { -+ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) { - switch (priv.elements[i].tag) { - case TAG_HMACSHA512_KEY: - isc_buffer_init(&b, priv.elements[i].data, -@@ -1703,6 +1741,7 @@ hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - static dst_func_t hmacsha512_functions = { - hmacsha512_createctx, -+ NULL, /*%< createctx2 */ - hmacsha512_destroyctx, - hmacsha512_adddata, - hmacsha512_sign, -diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h -index 1fdce4c..bdbd269 100644 ---- a/lib/dns/include/dst/dst.h -+++ b/lib/dns/include/dst/dst.h -@@ -175,6 +175,16 @@ isc_result_t - dst_context_create2(dst_key_t *key, isc_mem_t *mctx, - isc_logcategory_t *category, dst_context_t **dctxp); - -+isc_result_t -+dst_context_create3(dst_key_t *key, isc_mem_t *mctx, -+ isc_logcategory_t *category, isc_boolean_t useforsigning, -+ dst_context_t **dctxp); -+ -+isc_result_t -+dst_context_create4(dst_key_t *key, isc_mem_t *mctx, -+ isc_logcategory_t *category, isc_boolean_t useforsigning, -+ int maxbits, dst_context_t **dctxp); -+ - /*%< - * Creates a context to be used for a sign or verify operation. - * -diff --git a/lib/dns/include/dst/result.h b/lib/dns/include/dst/result.h -index 00640a1..cf9428f 100644 ---- a/lib/dns/include/dst/result.h -+++ b/lib/dns/include/dst/result.h -@@ -57,8 +57,9 @@ - #define DST_R_NORANDOMNESS (ISC_RESULTCLASS_DST + 19) - #define DST_R_BADKEYTYPE (ISC_RESULTCLASS_DST + 20) - #define DST_R_NOENGINE (ISC_RESULTCLASS_DST + 21) -+#define DST_R_EXTERNALKEY (ISC_RESULTCLASS_DST + 22) - --#define DST_R_NRESULTS 22 /* Number of results */ -+#define DST_R_NRESULTS 23 /* Number of results */ - - ISC_LANG_BEGINDECLS - -diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c -index 36b8a41..55752da 100644 ---- a/lib/dns/openssldh_link.c -+++ b/lib/dns/openssldh_link.c -@@ -463,6 +463,9 @@ openssldh_tofile(const dst_key_t *key, const char *directory) { - if (key->keydata.dh == NULL) - return (DST_R_NULLKEY); - -+ if (key->external) -+ return (DST_R_EXTERNALKEY); -+ - dh = key->keydata.dh; - - memset(bufs, 0, sizeof(bufs)); -@@ -528,6 +531,9 @@ openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - if (ret != ISC_R_SUCCESS) - return (ret); - -+ if (key->external) -+ DST_RET(DST_R_EXTERNALKEY); -+ - dh = DH_new(); - if (dh == NULL) - DST_RET(ISC_R_NOMEMORY); -@@ -630,6 +636,7 @@ openssldh_cleanup(void) { - - static dst_func_t openssldh_functions = { - NULL, /*%< createctx */ -+ NULL, /*%< createctx2 */ - NULL, /*%< destroyctx */ - NULL, /*%< adddata */ - NULL, /*%< openssldh_sign */ -diff --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c -index a24baae..fd6e91e 100644 ---- a/lib/dns/openssldsa_link.c -+++ b/lib/dns/openssldsa_link.c -@@ -522,7 +522,7 @@ openssldsa_tofile(const dst_key_t *key, const char *directory) { - - if (key->keydata.dsa == NULL) - return (DST_R_NULLKEY); -- -+ - if (key->external) { - priv.nelements = 0; - return (dst__privstruct_writefile(key, &priv, directory)); -@@ -573,20 +573,31 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - isc_mem_t *mctx = key->mctx; - #define DST_RET(a) {ret = a; goto err;} - -- UNUSED(pub); -- - /* read private key file */ - ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv); - if (ret != ISC_R_SUCCESS) - return (ret); - -+ if (key->external) { -+ if (priv.nelements != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ if (pub == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ key->keydata.pkey = pub->keydata.pkey; -+ pub->keydata.pkey = NULL; -+ key->key_size = pub->key_size; -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ISC_R_SUCCESS); -+ } -+ - dsa = DSA_new(); - if (dsa == NULL) - DST_RET(ISC_R_NOMEMORY); - dsa->flags &= ~DSA_FLAG_CACHE_MONT_P; - key->keydata.dsa = dsa; - -- for (i=0; i < priv.nelements; i++) { -+ for (i = 0; i < priv.nelements; i++) { - BIGNUM *bn; - bn = BN_bin2bn(priv.elements[i].data, - priv.elements[i].length, NULL); -@@ -612,22 +623,8 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - } - } - dst__privstruct_free(&priv, mctx); -- -- if (key->external) { -- if (pub == NULL) -- DST_RET(DST_R_INVALIDPRIVATEKEY); -- dsa->q = pub->keydata.dsa->q; -- pub->keydata.dsa->q = NULL; -- dsa->p = pub->keydata.dsa->p; -- pub->keydata.dsa->p = NULL; -- dsa->g = pub->keydata.dsa->g; -- pub->keydata.dsa->g = NULL; -- dsa->pub_key = pub->keydata.dsa->pub_key; -- pub->keydata.dsa->pub_key = NULL; -- } -- -+ memset(&priv, 0, sizeof(priv)); - key->key_size = BN_num_bits(dsa->p); -- - return (ISC_R_SUCCESS); - - err: -@@ -639,6 +636,7 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - static dst_func_t openssldsa_functions = { - openssldsa_createctx, -+ NULL, /*%< createctx2 */ - openssldsa_destroyctx, - openssldsa_adddata, - openssldsa_sign, -diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c -index 7eff9a0..c64cc55 100644 ---- a/lib/dns/opensslecdsa_link.c -+++ b/lib/dns/opensslecdsa_link.c -@@ -18,7 +18,7 @@ - - #include - --#ifdef HAVE_OPENSSL_ECDSA -+#if defined(OPENSSL) && defined(HAVE_OPENSSL_ECDSA) - - #if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA384) - #error "ECDSA without EVP for SHA2?" -@@ -474,7 +474,7 @@ opensslecdsa_tofile(const dst_key_t *key, const char *directory) { - priv.elements[0].length = BN_num_bytes(privkey); - BN_bn2bin(privkey, buf); - priv.elements[0].data = buf; -- priv.nelements = ECDSA_NTAGS; -+ priv.nelements = 1; - ret = dst__privstruct_writefile(key, &priv, directory); - - err: -@@ -519,60 +519,50 @@ static isc_result_t - opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - dst_private_t priv; - isc_result_t ret; -- EVP_PKEY *pkey, *pubpkey; -- EC_KEY *eckey = NULL, *pubeckey = NULL; -- const EC_POINT *pubkey; -- BIGNUM *privkey; -+ EVP_PKEY *pkey; -+ EC_KEY *eckey = NULL; -+ BIGNUM *privkey = NULL; - int group_nid; - isc_mem_t *mctx = key->mctx; - - REQUIRE(key->key_alg == DST_ALG_ECDSA256 || - key->key_alg == DST_ALG_ECDSA384); - -- if (key->key_alg == DST_ALG_ECDSA256) -- group_nid = NID_X9_62_prime256v1; -- else -- group_nid = NID_secp384r1; -- -- eckey = EC_KEY_new_by_curve_name(group_nid); -- if (eckey == NULL) -- return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); -- - /* read private key file */ - ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv); - if (ret != ISC_R_SUCCESS) - goto err; - - if (key->external) { -- /* -- * Copy the public key to this new key. -- */ -- if (pub == NULL) -- DST_RET(DST_R_INVALIDPRIVATEKEY); -- pubpkey = pub->keydata.pkey; -- pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey); -- if (pubeckey == NULL) -- DST_RET(DST_R_INVALIDPRIVATEKEY); -- pubkey = EC_KEY_get0_public_key(pubeckey); -- if (pubkey == NULL) -- DST_RET(DST_R_INVALIDPRIVATEKEY); -- if (EC_KEY_set_public_key(eckey, pubkey) != 1) -- DST_RET(DST_R_INVALIDPRIVATEKEY); -- if (EC_KEY_check_key(eckey) != 1) -+ if (priv.nelements != 0) - DST_RET(DST_R_INVALIDPRIVATEKEY); -- } else { -- privkey = BN_bin2bn(priv.elements[0].data, -- priv.elements[0].length, NULL); -- if (privkey == NULL) -- DST_RET(ISC_R_NOMEMORY); -- if (!EC_KEY_set_private_key(eckey, privkey)) -- DST_RET(ISC_R_NOMEMORY); -- if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS) -+ if (pub == NULL) - DST_RET(DST_R_INVALIDPRIVATEKEY); -+ key->keydata.pkey = pub->keydata.pkey; -+ pub->keydata.pkey = NULL; - dst__privstruct_free(&priv, mctx); - memset(&priv, 0, sizeof(priv)); -+ return (ISC_R_SUCCESS); - } -- -+ -+ if (key->key_alg == DST_ALG_ECDSA256) -+ group_nid = NID_X9_62_prime256v1; -+ else -+ group_nid = NID_secp384r1; -+ -+ eckey = EC_KEY_new_by_curve_name(group_nid); -+ if (eckey == NULL) -+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); -+ -+ privkey = BN_bin2bn(priv.elements[0].data, -+ priv.elements[0].length, NULL); -+ if (privkey == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ if (!EC_KEY_set_private_key(eckey, privkey)) -+ DST_RET(ISC_R_NOMEMORY); -+ if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ - pkey = EVP_PKEY_new(); - if (pkey == NULL) - DST_RET (ISC_R_NOMEMORY); -@@ -584,10 +574,10 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - ret = ISC_R_SUCCESS; - - err: -+ if (privkey != NULL) -+ BN_clear_free(privkey); - if (eckey != NULL) - EC_KEY_free(eckey); -- if (pubeckey != NULL) -- EC_KEY_free(pubeckey); - dst__privstruct_free(&priv, mctx); - memset(&priv, 0, sizeof(priv)); - return (ret); -@@ -595,6 +585,7 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - static dst_func_t opensslecdsa_functions = { - opensslecdsa_createctx, -+ NULL, /*%< createctx2 */ - opensslecdsa_destroyctx, - opensslecdsa_adddata, - opensslecdsa_sign, -diff --git a/lib/dns/opensslgost_link.c b/lib/dns/opensslgost_link.c -index 325a7c0..9b4ff55 100644 ---- a/lib/dns/opensslgost_link.c -+++ b/lib/dns/opensslgost_link.c -@@ -30,6 +30,7 @@ - #include "dst_internal.h" - #include "dst_openssl.h" - #include "dst_parse.h" -+#include "dst_gost.h" - - #include - #include -@@ -44,6 +45,60 @@ const EVP_MD *EVP_gost(void) { - return (opensslgost_digest); - } - -+/* ISC methods */ -+ -+isc_result_t -+isc_gost_init(isc_gost_t *ctx) { -+ const EVP_MD *md; -+ int ret; -+ -+ INSIST(ctx != NULL); -+ -+ md = EVP_gost(); -+ if (md == NULL) -+ return (DST_R_CRYPTOFAILURE); -+ EVP_MD_CTX_init(ctx); -+ ret = EVP_DigestInit(ctx, md); -+ if (ret != 1) -+ return (DST_R_CRYPTOFAILURE); -+ return (ISC_R_SUCCESS); -+} -+ -+void -+isc_gost_invalidate(isc_gost_t *ctx) { -+ EVP_MD_CTX_cleanup(ctx); -+} -+ -+isc_result_t -+isc_gost_update(isc_gost_t *ctx, const unsigned char *data, -+ unsigned int len) -+{ -+ int ret; -+ -+ INSIST(ctx != NULL); -+ INSIST(data != NULL); -+ -+ ret = EVP_DigestUpdate(ctx, (const void *) data, (size_t) len); -+ if (ret != 1) -+ return (DST_R_CRYPTOFAILURE); -+ return (ISC_R_SUCCESS); -+} -+ -+isc_result_t -+isc_gost_final(isc_gost_t *ctx, unsigned char *digest) { -+ int ret; -+ -+ INSIST(ctx != NULL); -+ INSIST(digest != NULL); -+ -+ ret = EVP_DigestFinal(ctx, digest, NULL); -+ if (ret != 1) -+ return (DST_R_CRYPTOFAILURE); -+ return (ISC_R_SUCCESS); -+} -+ -+/* DST methods */ -+ - #define DST_RET(a) {ret = a; goto err;} - - static isc_result_t opensslgost_todns(const dst_key_t *key, -@@ -285,6 +340,8 @@ opensslgost_fromdns(dst_key_t *key, isc_buffer_t *data) { - return (ISC_R_SUCCESS); - } - -+#ifdef PREFER_GOSTASN1 -+ - static isc_result_t - opensslgost_tofile(const dst_key_t *key, const char *directory) { - EVP_PKEY *pkey; -@@ -318,7 +375,7 @@ opensslgost_tofile(const dst_key_t *key, const char *directory) { - priv.elements[0].tag = TAG_GOST_PRIVASN1; - priv.elements[0].length = len; - priv.elements[0].data = der; -- priv.nelements = GOST_NTAGS; -+ priv.nelements = 1; - - result = dst__privstruct_writefile(key, &priv, directory); - fail: -@@ -327,42 +384,146 @@ opensslgost_tofile(const dst_key_t *key, const char *directory) { - return (result); - } - -+#else -+ -+static isc_result_t -+opensslgost_tofile(const dst_key_t *key, const char *directory) { -+ EVP_PKEY *pkey; -+ EC_KEY *eckey; -+ const BIGNUM *privkey; -+ dst_private_t priv; -+ isc_result_t ret; -+ unsigned char *buf = NULL; -+ -+ if (key->keydata.pkey == NULL) -+ return (DST_R_NULLKEY); -+ -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } -+ -+ pkey = key->keydata.pkey; -+ eckey = EVP_PKEY_get0(pkey); -+ if (eckey == NULL) -+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); -+ privkey = EC_KEY_get0_private_key(eckey); -+ if (privkey == NULL) -+ return (ISC_R_FAILURE); -+ -+ buf = isc_mem_get(key->mctx, BN_num_bytes(privkey)); -+ if (buf == NULL) -+ return (ISC_R_NOMEMORY); -+ -+ priv.elements[0].tag = TAG_GOST_PRIVRAW; -+ priv.elements[0].length = BN_num_bytes(privkey); -+ BN_bn2bin(privkey, buf); -+ priv.elements[0].data = buf; -+ priv.nelements = 1; -+ -+ ret = dst__privstruct_writefile(key, &priv, directory); -+ -+ if (buf != NULL) -+ isc_mem_put(key->mctx, buf, BN_num_bytes(privkey)); -+ return (ret); -+} -+#endif -+ -+static unsigned char gost_dummy_key[71] = { -+ 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06, -+ 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30, -+ 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, -+ 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, -+ 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20, 0x1b, -+ 0x3f, 0x94, 0xf7, 0x1a, 0x5f, 0x2f, 0xe7, 0xe5, -+ 0x74, 0x0b, 0x8c, 0xd4, 0xb7, 0x18, 0xdd, 0x65, -+ 0x68, 0x26, 0xd1, 0x54, 0xfb, 0x77, 0xba, 0x63, -+ 0x72, 0xd9, 0xf0, 0x63, 0x87, 0xe0, 0xd6 -+}; -+ - static isc_result_t - opensslgost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - dst_private_t priv; - isc_result_t ret; - isc_mem_t *mctx = key->mctx; - EVP_PKEY *pkey = NULL; -+ EC_KEY *eckey; -+ const EC_POINT *pubkey = NULL; -+ BIGNUM *privkey = NULL; - const unsigned char *p; - -- UNUSED(pub); -- - /* read private key file */ - ret = dst__privstruct_parse(key, DST_ALG_ECCGOST, lexer, mctx, &priv); - if (ret != ISC_R_SUCCESS) - return (ret); - - if (key->external) { -- INSIST(priv.nelements == 0); -+ if (priv.nelements != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); - if (pub == NULL) - DST_RET(DST_R_INVALIDPRIVATEKEY); - key->keydata.pkey = pub->keydata.pkey; - pub->keydata.pkey = NULL; -- } else { -- INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1); -+ key->key_size = pub->key_size; -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ISC_R_SUCCESS); -+ } -+ -+ INSIST((priv.elements[0].tag == TAG_GOST_PRIVASN1) || -+ (priv.elements[0].tag == TAG_GOST_PRIVRAW)); -+ -+ if (priv.elements[0].tag == TAG_GOST_PRIVASN1) { - p = priv.elements[0].data; - if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, - (long) priv.elements[0].length) == NULL) -- DST_RET(dst__openssl_toresult2("d2i_PrivateKey", -- DST_R_INVALIDPRIVATEKEY)); -- key->keydata.pkey = pkey; -+ DST_RET(dst__openssl_toresult2( -+ "d2i_PrivateKey", -+ DST_R_INVALIDPRIVATEKEY)); -+ } else { -+ if ((pub != NULL) && (pub->keydata.pkey != NULL)) { -+ eckey = EVP_PKEY_get0(pub->keydata.pkey); -+ pubkey = EC_KEY_get0_public_key(eckey); -+ } -+ -+ privkey = BN_bin2bn(priv.elements[0].data, -+ priv.elements[0].length, NULL); -+ if (privkey == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ -+ /* can't create directly the whole key */ -+ p = gost_dummy_key; -+ if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, -+ (long) sizeof(gost_dummy_key)) == NULL) -+ DST_RET(dst__openssl_toresult2( -+ "d2i_PrivateKey", -+ DST_R_INVALIDPRIVATEKEY)); -+ -+ eckey = EVP_PKEY_get0(pkey); -+ if (eckey == NULL) -+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); -+ if (!EC_KEY_set_private_key(eckey, privkey)) -+ DST_RET(ISC_R_NOMEMORY); -+ -+ /* have to (re)set the public key */ -+#ifdef notyet -+ (void) gost2001_compute_public(eckey); -+#else -+ if ((pubkey != NULL) && !EC_KEY_set_public_key(eckey, pubkey)) -+ DST_RET(ISC_R_NOMEMORY); -+#endif -+ BN_clear_free(privkey); -+ privkey = NULL; - } -+ key->keydata.pkey = pkey; - key->key_size = EVP_PKEY_bits(pkey); - dst__privstruct_free(&priv, mctx); - memset(&priv, 0, sizeof(priv)); - return (ISC_R_SUCCESS); - - err: -+ if (privkey != NULL) -+ BN_clear_free(privkey); - if (pkey != NULL) - EVP_PKEY_free(pkey); - opensslgost_destroy(key); -@@ -382,6 +543,7 @@ opensslgost_cleanup(void) { - - static dst_func_t opensslgost_functions = { - opensslgost_createctx, -+ NULL, /*%< createctx2 */ - opensslgost_destroyctx, - opensslgost_adddata, - opensslgost_sign, -diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c -index 894c7ae..1edeb8d 100644 ---- a/lib/dns/opensslrsa_link.c -+++ b/lib/dns/opensslrsa_link.c -@@ -1196,6 +1196,24 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - EVP_PKEY *pkey = NULL; - #endif - -+ /* read private key file */ -+ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ if (key->external) { -+ if (priv.nelements != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ if (pub == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ key->keydata.pkey = pub->keydata.pkey; -+ pub->keydata.pkey = NULL; -+ key->key_size = pub->key_size; -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ISC_R_SUCCESS); -+ } -+ - #if USE_EVP - if (pub != NULL && pub->keydata.pkey != NULL) - pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey); -@@ -1206,14 +1224,6 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - } - #endif - -- /* read private key file */ -- ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); -- if (ret != ISC_R_SUCCESS) -- goto err; -- -- if (key->external && priv.nelements != 0) -- DST_RET(DST_R_INVALIDPRIVATEKEY); -- - for (i = 0; i < priv.nelements; i++) { - switch (priv.elements[i].tag) { - case TAG_RSA_ENGINE: -@@ -1297,8 +1307,6 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - continue; - case TAG_RSA_LABEL: - continue; -- case TAG_RSA_PIN: -- continue; - default: - bn = BN_bin2bn(priv.elements[i].data, - priv.elements[i].length, NULL); -@@ -1338,10 +1346,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { - - if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) - DST_RET(DST_R_INVALIDPRIVATEKEY); -- if (!key->external) { -- if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) -- DST_RET(ISC_R_RANGE); -- } -+ if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) -+ DST_RET(ISC_R_RANGE); - key->key_size = BN_num_bits(rsa->n); - if (pubrsa != NULL) - RSA_free(pubrsa); -@@ -1448,6 +1454,7 @@ opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, - - static dst_func_t opensslrsa_functions = { - opensslrsa_createctx, -+ NULL, /*%< createctx2 */ - opensslrsa_destroyctx, - opensslrsa_adddata, - opensslrsa_sign, -diff --git a/lib/dns/pkcs11.c b/lib/dns/pkcs11.c -new file mode 100644 -index 0000000..7aa15fa ---- /dev/null -+++ b/lib/dns/pkcs11.c -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifdef PKCS11CRYPTO -+ -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+#include "dst_pkcs11.h" -+ -+isc_result_t -+dst__pkcs11_toresult(const char *funcname, const char *file, int line, -+ isc_result_t fallback, CK_RV rv) -+{ -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, -+ DNS_LOGMODULE_CRYPTO, ISC_LOG_WARNING, -+ "%s:%d: %s: Error = 0x%.8lX\n", -+ file, line, funcname, rv); -+ if (rv == CKR_HOST_MEMORY) -+ return (ISC_R_NOMEMORY); -+ return (fallback); -+} -+ -+ -+#else /* PKCS11CRYPTO */ -+ -+#include -+ -+EMPTY_TRANSLATION_UNIT -+ -+#endif /* PKCS11CRYPTO */ -+/*! \file */ -diff --git a/lib/dns/pkcs11dh_link.c b/lib/dns/pkcs11dh_link.c -new file mode 100644 -index 0000000..87afc02 ---- /dev/null -+++ b/lib/dns/pkcs11dh_link.c -@@ -0,0 +1,1140 @@ -+/* -+ * Portions Copyright (C) 20012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * -+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+#ifdef PKCS11CRYPTO -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "dst_internal.h" -+#include "dst_parse.h" -+#include "dst_pkcs11.h" -+ -+#include -+#include -+#define WANT_DH_PRIMES -+#include -+ -+#include -+ -+/* -+ * PKCS#3 DH keys: -+ * mechanisms: -+ * CKM_DH_PKCS_PARAMETER_GEN, -+ * CKM_DH_PKCS_KEY_PAIR_GEN, -+ * CKM_DH_PKCS_DERIVE -+ * domain parameters: -+ * object class CKO_DOMAIN_PARAMETERS -+ * key type CKK_DH -+ * attribute CKA_PRIME (prime p) -+ * attribute CKA_BASE (base g) -+ * optional attribute CKA_PRIME_BITS (p length in bits) -+ * public key: -+ * object class CKO_PUBLIC_KEY -+ * key type CKK_DH -+ * attribute CKA_PRIME (prime p) -+ * attribute CKA_BASE (base g) -+ * attribute CKA_VALUE (public value y) -+ * private key: -+ * object class CKO_PRIVATE_KEY -+ * key type CKK_DH -+ * attribute CKA_PRIME (prime p) -+ * attribute CKA_BASE (base g) -+ * attribute CKA_VALUE (private value x) -+ * optional attribute CKA_VALUE_BITS (x length in bits) -+ * reuse CKA_PRIVATE_EXPONENT for key pair private value -+ */ -+ -+#define CKA_VALUE2 CKA_PRIVATE_EXPONENT -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+#define DST_RET(a) {ret = a; goto err;} -+ -+static void pkcs11dh_destroy(dst_key_t *key); -+static isc_result_t pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data); -+ -+static isc_result_t -+pkcs11dh_loadpriv(const dst_key_t *key, -+ CK_SESSION_HANDLE session, -+ CK_OBJECT_HANDLE *hKey) -+{ -+ CK_RV rv; -+ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE keyType = CKK_DH; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_PRIME, NULL, 0 }, -+ { CKA_BASE, NULL, 0 }, -+ { CKA_VALUE, NULL, 0 } -+ }; -+ CK_ATTRIBUTE *attr; -+ const pk11_object_t *priv; -+ isc_result_t ret; -+ unsigned int i; -+ -+ priv = key->keydata.pkey; -+ if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) { -+ *hKey = priv->object; -+ return (ISC_R_SUCCESS); -+ } -+ -+ attr = pk11_attribute_bytype(priv, CKA_PRIME); -+ if (attr == NULL) -+ return (DST_R_INVALIDPRIVATEKEY); -+ keyTemplate[6].pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (keyTemplate[6].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen); -+ keyTemplate[6].ulValueLen = attr->ulValueLen; -+ -+ attr = pk11_attribute_bytype(priv, CKA_BASE); -+ if (attr == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ keyTemplate[7].pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (keyTemplate[7].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen); -+ keyTemplate[7].ulValueLen = attr->ulValueLen; -+ -+ attr = pk11_attribute_bytype(priv, CKA_VALUE2); -+ if (attr == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ keyTemplate[8].pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (keyTemplate[8].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen); -+ keyTemplate[8].ulValueLen = attr->ulValueLen; -+ -+ PK11_CALL(pkcs_C_CreateObject, -+ (session, keyTemplate, (CK_ULONG) 9, hKey), -+ DST_R_COMPUTESECRETFAILURE); -+ if (rv == CKR_OK) -+ ret = ISC_R_SUCCESS; -+ -+ err: -+ for (i = 6; i <= 8; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(key->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11dh_computesecret(const dst_key_t *pub, const dst_key_t *priv, -+ isc_buffer_t *secret) -+{ -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_DH_PKCS_DERIVE, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; -+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; -+ CK_OBJECT_HANDLE hDerived = CK_INVALID_HANDLE; -+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; -+ CK_ATTRIBUTE *attr; -+ CK_ULONG secLen; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE_LEN, &secLen, (CK_ULONG) sizeof(secLen) } -+ }; -+ CK_ATTRIBUTE valTemplate[] = -+ { -+ { CKA_VALUE, NULL, 0 } -+ }; -+ CK_BYTE *secValue; -+ pk11_context_t ctx; -+ isc_result_t ret; -+ unsigned int i; -+ isc_region_t r; -+ -+ REQUIRE(pub->keydata.pkey != NULL); -+ REQUIRE(priv->keydata.pkey != NULL); -+ REQUIRE(priv->keydata.pkey->repr != NULL); -+ attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_PRIME); -+ if (attr == NULL) -+ return (DST_R_INVALIDPUBLICKEY); -+ REQUIRE(attr != NULL); -+ secLen = attr->ulValueLen; -+ attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE); -+ if (attr == NULL) -+ return (DST_R_INVALIDPUBLICKEY); -+ -+ ret = pk11_get_session(&ctx, OP_DH, ISC_TRUE, ISC_FALSE, ISC_FALSE, -+ NULL, pk11_get_best_token(OP_DH)); -+ if (ret != ISC_R_SUCCESS) -+ return (ret); -+ -+ mech.ulParameterLen = attr->ulValueLen; -+ mech.pParameter = isc_mem_get(pub->mctx, mech.ulParameterLen); -+ if (mech.pParameter == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(mech.pParameter, attr->pValue, mech.ulParameterLen); -+ -+ ret = pkcs11dh_loadpriv(priv, ctx.session, &hKey); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ PK11_RET(pkcs_C_DeriveKey, -+ (ctx.session, &mech, hKey, -+ keyTemplate, (CK_ULONG) 6, &hDerived), -+ DST_R_COMPUTESECRETFAILURE); -+ -+ attr = valTemplate; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (ctx.session, hDerived, attr, (CK_ULONG) 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(pub->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (ctx.session, hDerived, attr, (CK_ULONG) 1), -+ DST_R_CRYPTOFAILURE); -+ -+ /* strip leading zeros */ -+ secValue = (CK_BYTE_PTR) attr->pValue; -+ for (i = 0; i < attr->ulValueLen; i++) -+ if (secValue[i] != 0) -+ break; -+ isc_buffer_availableregion(secret, &r); -+ if (r.length < attr->ulValueLen - i) -+ DST_RET(ISC_R_NOSPACE); -+ memcpy(r.base, secValue + i, attr->ulValueLen - i); -+ isc_buffer_add(secret, attr->ulValueLen - i); -+ ret = ISC_R_SUCCESS; -+ -+ err: -+ if (hDerived != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx.session, hDerived); -+ if (valTemplate[0].pValue != NULL) { -+ memset(valTemplate[0].pValue, 0, valTemplate[0].ulValueLen); -+ isc_mem_put(pub->mctx, -+ valTemplate[0].pValue, -+ valTemplate[0].ulValueLen); -+ } -+ if ((hKey != CK_INVALID_HANDLE) && !priv->keydata.pkey->ontoken) -+ (void) pkcs_C_DestroyObject(ctx.session, hKey); -+ if (mech.pParameter != NULL) { -+ memset(mech.pParameter, 0, mech.ulParameterLen); -+ isc_mem_put(pub->mctx, mech.pParameter, mech.ulParameterLen); -+ } -+ pk11_return_session(&ctx); -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11dh_compare(const dst_key_t *key1, const dst_key_t *key2) { -+ pk11_object_t *dh1, *dh2; -+ CK_ATTRIBUTE *attr1, *attr2; -+ -+ dh1 = key1->keydata.pkey; -+ dh2 = key2->keydata.pkey; -+ -+ if ((dh1 == NULL) && (dh2 == NULL)) -+ return (ISC_TRUE); -+ else if ((dh1 == NULL) || (dh2 == NULL)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dh1, CKA_PRIME); -+ attr2 = pk11_attribute_bytype(dh2, CKA_PRIME); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dh1, CKA_BASE); -+ attr2 = pk11_attribute_bytype(dh2, CKA_BASE); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dh1, CKA_VALUE); -+ attr2 = pk11_attribute_bytype(dh2, CKA_VALUE); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dh1, CKA_VALUE2); -+ attr2 = pk11_attribute_bytype(dh2, CKA_VALUE2); -+ if (((attr1 != NULL) || (attr2 != NULL)) && -+ ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))) -+ return (ISC_FALSE); -+ -+ if (!dh1->ontoken && !dh2->ontoken) -+ return (ISC_TRUE); -+ else if (dh1->ontoken || dh2->ontoken || -+ (dh1->object != dh2->object)) -+ return (ISC_FALSE); -+ -+ return (ISC_TRUE); -+} -+ -+static isc_boolean_t -+pkcs11dh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { -+ pk11_object_t *dh1, *dh2; -+ CK_ATTRIBUTE *attr1, *attr2; -+ -+ dh1 = key1->keydata.pkey; -+ dh2 = key2->keydata.pkey; -+ -+ if ((dh1 == NULL) && (dh2 == NULL)) -+ return (ISC_TRUE); -+ else if ((dh1 == NULL) || (dh2 == NULL)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dh1, CKA_PRIME); -+ attr2 = pk11_attribute_bytype(dh2, CKA_PRIME); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dh1, CKA_BASE); -+ attr2 = pk11_attribute_bytype(dh2, CKA_BASE); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ return (ISC_TRUE); -+} -+ -+static isc_result_t -+pkcs11dh_generate(dst_key_t *key, int generator, void (*callback)(int)) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_DH_PKCS_PARAMETER_GEN, NULL, 0 }; -+ CK_OBJECT_HANDLE domainparams = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS dClass = CKO_DOMAIN_PARAMETERS; -+ CK_KEY_TYPE keyType = CKK_DH; -+ CK_ULONG bits = 0; -+ CK_ATTRIBUTE dTemplate[] = -+ { -+ { CKA_CLASS, &dClass, (CK_ULONG) sizeof(dClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIME_BITS, &bits, (CK_ULONG) sizeof(bits) } -+ }; -+ CK_ATTRIBUTE pTemplate[] = -+ { -+ { CKA_PRIME, NULL, 0 }, -+ { CKA_BASE, NULL, 0 } -+ }; -+ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; -+ CK_ATTRIBUTE pubTemplate[] = -+ { -+ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, -+ { CKA_KEY_TYPE,&keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIME, NULL, 0 }, -+ { CKA_BASE, NULL, 0 }, -+ }; -+ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; -+ CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY; -+ CK_ATTRIBUTE privTemplate[] = -+ { -+ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *dh = NULL; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ -+ UNUSED(callback); -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_DH, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_DH)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ bits = key->key_size; -+ if ((generator == 0) && -+ ((bits == 768) || (bits == 1024) || (bits == 1536))) { -+ if (bits == 768) { -+ pubTemplate[4].pValue = -+ isc_mem_get(key->mctx, sizeof(pk11_dh_bn768)); -+ if (pubTemplate[4].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(pubTemplate[4].pValue, -+ pk11_dh_bn768, sizeof(pk11_dh_bn768)); -+ pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn768); -+ } else if (bits == 1024) { -+ pubTemplate[4].pValue = -+ isc_mem_get(key->mctx, sizeof(pk11_dh_bn1024)); -+ if (pubTemplate[4].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(pubTemplate[4].pValue, -+ pk11_dh_bn1024, sizeof(pk11_dh_bn1024)); -+ pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1024); -+ } else { -+ pubTemplate[4].pValue = -+ isc_mem_get(key->mctx, sizeof(pk11_dh_bn1536)); -+ if (pubTemplate[4].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(pubTemplate[4].pValue, -+ pk11_dh_bn1536, sizeof(pk11_dh_bn1536)); -+ pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1536); -+ } -+ pubTemplate[5].pValue = isc_mem_get(key->mctx, -+ sizeof(pk11_dh_bn2)); -+ if (pubTemplate[5].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(pubTemplate[5].pValue, pk11_dh_bn2, sizeof(pk11_dh_bn2)); -+ pubTemplate[5].ulValueLen = sizeof(pk11_dh_bn2); -+ } else { -+ PK11_RET(pkcs_C_GenerateKey, -+ (pk11_ctx->session, &mech, -+ dTemplate, (CK_ULONG) 5, &domainparams), -+ DST_R_CRYPTOFAILURE); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, domainparams, -+ pTemplate, (CK_ULONG) 2), -+ DST_R_CRYPTOFAILURE); -+ pTemplate[0].pValue = isc_mem_get(key->mctx, -+ pTemplate[0].ulValueLen); -+ if (pTemplate[0].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen); -+ pTemplate[1].pValue = isc_mem_get(key->mctx, -+ pTemplate[1].ulValueLen); -+ if (pTemplate[1].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, domainparams, -+ pTemplate, (CK_ULONG) 2), -+ DST_R_CRYPTOFAILURE); -+ -+ pubTemplate[4].pValue = pTemplate[0].pValue; -+ pubTemplate[4].ulValueLen = pTemplate[0].ulValueLen; -+ pTemplate[0].pValue = NULL; -+ pubTemplate[5].pValue = pTemplate[1].pValue; -+ pubTemplate[5].ulValueLen = pTemplate[1].ulValueLen; -+ pTemplate[1].pValue = NULL; -+ } -+ -+ mech.mechanism = CKM_DH_PKCS_KEY_PAIR_GEN; -+ PK11_RET(pkcs_C_GenerateKeyPair, -+ (pk11_ctx->session, &mech, -+ pubTemplate, (CK_ULONG) 6, -+ privTemplate, (CK_ULONG) 7, -+ &pub, &priv), -+ DST_R_CRYPTOFAILURE); -+ -+ dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh)); -+ if (dh == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(dh, 0, sizeof(*dh)); -+ key->keydata.pkey = dh; -+ dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4); -+ if (dh->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(dh->repr, 0, sizeof(*attr) * 4); -+ dh->attrcnt = 4; -+ -+ attr = dh->repr; -+ attr[0].type = CKA_PRIME; -+ attr[0].pValue = pubTemplate[4].pValue; -+ attr[0].ulValueLen = pubTemplate[4].ulValueLen; -+ pubTemplate[4].pValue = NULL; -+ -+ attr[1].type = CKA_BASE; -+ attr[1].pValue = pubTemplate[5].pValue; -+ attr[1].ulValueLen = pubTemplate[5].ulValueLen; -+ pubTemplate[5].pValue =NULL; -+ -+ attr += 2; -+ attr->type = CKA_VALUE; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ -+ attr++; -+ attr->type = CKA_VALUE; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->type = CKA_VALUE2; -+ -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11dh_destroy(key); -+ if (priv != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ if (pub != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ if (domainparams != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams); -+ -+ if (pubTemplate[4].pValue != NULL) { -+ memset(pubTemplate[4].pValue, 0, pubTemplate[4].ulValueLen); -+ isc_mem_put(key->mctx, -+ pubTemplate[4].pValue, -+ pubTemplate[4].ulValueLen); -+ } -+ if (pubTemplate[5].pValue != NULL) { -+ memset(pubTemplate[5].pValue, 0, pubTemplate[5].ulValueLen); -+ isc_mem_put(key->mctx, -+ pubTemplate[5].pValue, -+ pubTemplate[5].ulValueLen); -+ } -+ if (pTemplate[0].pValue != NULL) { -+ memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen); -+ isc_mem_put(key->mctx, -+ pTemplate[0].pValue, -+ pTemplate[0].ulValueLen); -+ } -+ if (pTemplate[1].pValue != NULL) { -+ memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen); -+ isc_mem_put(key->mctx, -+ pTemplate[1].pValue, -+ pTemplate[1].ulValueLen); -+ } -+ -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11dh_isprivate(const dst_key_t *key) { -+ pk11_object_t *dh = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (dh == NULL) -+ return (ISC_FALSE); -+ attr = pk11_attribute_bytype(dh, CKA_VALUE2); -+ return (ISC_TF((attr != NULL) || dh->ontoken)); -+} -+ -+static void -+pkcs11dh_destroy(dst_key_t *key) { -+ pk11_object_t *dh = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (dh == NULL) -+ return; -+ -+ INSIST((dh->object == CK_INVALID_HANDLE) || dh->ontoken); -+ -+ for (attr = pk11_attribute_first(dh); -+ attr != NULL; -+ attr = pk11_attribute_next(dh, attr)) -+ switch (attr->type) { -+ case CKA_VALUE: -+ case CKA_VALUE2: -+ case CKA_PRIME: -+ case CKA_BASE: -+ if (attr->pValue != NULL) { -+ memset(attr->pValue, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, -+ attr->pValue, -+ attr->ulValueLen); -+ } -+ break; -+ } -+ if (dh->repr != NULL) { -+ memset(dh->repr, 0, dh->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr)); -+ } -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ key->keydata.pkey = NULL; -+} -+ -+static void -+uint16_toregion(isc_uint16_t val, isc_region_t *region) { -+ *region->base++ = (val & 0xff00) >> 8; -+ *region->base++ = (val & 0x00ff); -+} -+ -+static isc_uint16_t -+uint16_fromregion(isc_region_t *region) { -+ isc_uint16_t val; -+ unsigned char *cp = region->base; -+ -+ val = ((unsigned int)(cp[0])) << 8; -+ val |= ((unsigned int)(cp[1])); -+ -+ region->base += 2; -+ return (val); -+} -+ -+static isc_result_t -+pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *dh; -+ CK_ATTRIBUTE *attr; -+ isc_region_t r; -+ isc_uint16_t dnslen, plen = 0, glen = 0, publen = 0; -+ CK_BYTE *prime = NULL, *base = NULL, *pub = NULL; -+ -+ REQUIRE(key->keydata.pkey != NULL); -+ -+ dh = key->keydata.pkey; -+ -+ for (attr = pk11_attribute_first(dh); -+ attr != NULL; -+ attr = pk11_attribute_next(dh, attr)) -+ switch (attr->type) { -+ case CKA_VALUE: -+ pub = (CK_BYTE *) attr->pValue; -+ publen = (isc_uint16_t) attr->ulValueLen; -+ break; -+ case CKA_PRIME: -+ prime = (CK_BYTE *) attr->pValue; -+ plen = (isc_uint16_t) attr->ulValueLen; -+ break; -+ case CKA_BASE: -+ base = (CK_BYTE *) attr->pValue; -+ glen = (isc_uint16_t) attr->ulValueLen; -+ break; -+ } -+ REQUIRE((prime != NULL) && (base != NULL) && (pub != NULL)); -+ -+ isc_buffer_availableregion(data, &r); -+ -+ if ((glen == 1) && (memcmp(pk11_dh_bn2, base, glen) == 0) && -+ (((plen == sizeof(pk11_dh_bn768)) && -+ (memcmp(pk11_dh_bn768, prime, plen) == 0)) || -+ ((plen == sizeof(pk11_dh_bn1024)) && -+ (memcmp(pk11_dh_bn1024, prime, plen) == 0)) || -+ ((plen == sizeof(pk11_dh_bn1536)) && -+ (memcmp(pk11_dh_bn1536, prime, plen) == 0)))) { -+ plen = 1; -+ glen = 0; -+ } -+ -+ dnslen = plen + glen + publen + 6; -+ if (r.length < (unsigned int) dnslen) -+ return (ISC_R_NOSPACE); -+ -+ uint16_toregion(plen, &r); -+ if (plen == 1) { -+ if (memcmp(pk11_dh_bn768, prime, sizeof(pk11_dh_bn768)) == 0) -+ *r.base = 1; -+ else if (memcmp(pk11_dh_bn1024, prime, -+ sizeof(pk11_dh_bn1024)) == 0) -+ *r.base = 2; -+ else -+ *r.base = 3; -+ } -+ else -+ memcpy(r.base, prime, plen); -+ r.base += plen; -+ -+ uint16_toregion(glen, &r); -+ if (glen > 0) -+ memcpy(r.base, base, glen); -+ r.base += glen; -+ -+ uint16_toregion(publen, &r); -+ memcpy(r.base, pub, publen); -+ r.base += publen; -+ -+ isc_buffer_add(data, dnslen); -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *dh; -+ isc_region_t r; -+ isc_uint16_t plen, glen, plen_, glen_, publen; -+ CK_BYTE *prime = NULL, *base = NULL, *pub = NULL; -+ CK_ATTRIBUTE *attr; -+ int special = 0; -+ -+ isc_buffer_remainingregion(data, &r); -+ if (r.length == 0) -+ return (ISC_R_SUCCESS); -+ -+ dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh)); -+ if (dh == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(dh, 0, sizeof(*dh)); -+ -+ /* -+ * Read the prime length. 1 & 2 are table entries, > 16 means a -+ * prime follows, otherwise an error. -+ */ -+ if (r.length < 2) { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ plen = uint16_fromregion(&r); -+ if (plen < 16 && plen != 1 && plen != 2) { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ if (r.length < plen) { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ plen_ = plen; -+ if (plen == 1 || plen == 2) { -+ if (plen == 1) -+ special = *r.base++; -+ else -+ special = uint16_fromregion(&r); -+ switch (special) { -+ case 1: -+ prime = pk11_dh_bn768; -+ plen_ = sizeof(pk11_dh_bn768); -+ break; -+ case 2: -+ prime = pk11_dh_bn1024; -+ plen_ = sizeof(pk11_dh_bn1024); -+ break; -+ case 3: -+ prime = pk11_dh_bn1536; -+ plen_ = sizeof(pk11_dh_bn1536); -+ break; -+ default: -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ } -+ else { -+ prime = r.base; -+ r.base += plen; -+ } -+ -+ /* -+ * Read the generator length. This should be 0 if the prime was -+ * special, but it might not be. If it's 0 and the prime is not -+ * special, we have a problem. -+ */ -+ if (r.length < 2) { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ glen = uint16_fromregion(&r); -+ if (r.length < glen) { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ glen_ = glen; -+ if (special != 0) { -+ if (glen == 0) { -+ base = pk11_dh_bn2; -+ glen_ = sizeof(pk11_dh_bn2); -+ } -+ else { -+ base = r.base; -+ if (memcmp(base, pk11_dh_bn2, glen) == 0) { -+ base = pk11_dh_bn2; -+ glen_ = sizeof(pk11_dh_bn2); -+ } -+ else { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ } -+ } -+ else { -+ if (glen == 0) { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ base = r.base; -+ } -+ r.base += glen; -+ -+ if (r.length < 2) { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ publen = uint16_fromregion(&r); -+ if (r.length < publen) { -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ pub = r.base; -+ r.base += publen; -+ -+ key->key_size = pk11_numbits(prime, plen_); -+ -+ dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3); -+ if (dh->repr == NULL) -+ goto nomemory; -+ memset(dh->repr, 0, sizeof(*attr) * 3); -+ dh->attrcnt = 3; -+ -+ attr = dh->repr; -+ attr[0].type = CKA_PRIME; -+ attr[0].pValue = isc_mem_get(key->mctx, plen_); -+ if (attr[0].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[0].pValue, prime, plen_); -+ attr[0].ulValueLen = (CK_ULONG) plen_; -+ -+ attr[1].type = CKA_BASE; -+ attr[1].pValue = isc_mem_get(key->mctx, glen_); -+ if (attr[1].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[1].pValue, base, glen_); -+ attr[1].ulValueLen = (CK_ULONG) glen_; -+ -+ attr[2].type = CKA_VALUE; -+ attr[2].pValue = isc_mem_get(key->mctx, publen); -+ if (attr[2].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[2].pValue, pub, publen); -+ attr[2].ulValueLen = (CK_ULONG) publen; -+ -+ isc_buffer_forward(data, plen + glen + publen + 6); -+ -+ key->keydata.pkey = dh; -+ -+ return (ISC_R_SUCCESS); -+ -+ nomemory: -+ for (attr = pk11_attribute_first(dh); -+ attr != NULL; -+ attr = pk11_attribute_next(dh, attr)) -+ switch (attr->type) { -+ case CKA_VALUE: -+ case CKA_PRIME: -+ case CKA_BASE: -+ if (attr->pValue != NULL) { -+ memset(attr->pValue, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, -+ attr->pValue, -+ attr->ulValueLen); -+ } -+ break; -+ } -+ if (dh->repr != NULL) { -+ memset(dh->repr, 0, dh->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr)); -+ } -+ memset(dh, 0, sizeof(*dh)); -+ isc_mem_put(key->mctx, dh, sizeof(*dh)); -+ return (ISC_R_NOMEMORY); -+} -+ -+static isc_result_t -+pkcs11dh_tofile(const dst_key_t *key, const char *directory) { -+ int i; -+ pk11_object_t *dh; -+ CK_ATTRIBUTE *attr; -+ CK_ATTRIBUTE *prime = NULL, *base = NULL, *pub = NULL, *prv = NULL; -+ dst_private_t priv; -+ unsigned char *bufs[4]; -+ isc_result_t result; -+ -+ if (key->keydata.pkey == NULL) -+ return (DST_R_NULLKEY); -+ -+ if (key->external) -+ return (DST_R_EXTERNALKEY); -+ -+ dh = key->keydata.pkey; -+ -+ for (attr = pk11_attribute_first(dh); -+ attr != NULL; -+ attr = pk11_attribute_next(dh, attr)) -+ switch (attr->type) { -+ case CKA_VALUE: -+ pub = attr; -+ break; -+ case CKA_VALUE2: -+ prv = attr; -+ break; -+ case CKA_PRIME: -+ prime = attr; -+ break; -+ case CKA_BASE: -+ base = attr; -+ break; -+ } -+ if ((prime == NULL) || (base == NULL) || -+ (pub == NULL) || (prv == NULL)) -+ return (DST_R_NULLKEY); -+ -+ memset(bufs, 0, sizeof(bufs)); -+ for (i = 0; i < 4; i++) { -+ bufs[i] = isc_mem_get(key->mctx, prime->ulValueLen); -+ if (bufs[i] == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto fail; -+ } -+ memset(bufs[i], 0, prime->ulValueLen); -+ } -+ -+ i = 0; -+ -+ priv.elements[i].tag = TAG_DH_PRIME; -+ priv.elements[i].length = (unsigned short) prime->ulValueLen; -+ memcpy(bufs[i], prime->pValue, prime->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ -+ priv.elements[i].tag = TAG_DH_GENERATOR; -+ priv.elements[i].length = (unsigned short) base->ulValueLen; -+ memcpy(bufs[i], base->pValue, base->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ -+ priv.elements[i].tag = TAG_DH_PRIVATE; -+ priv.elements[i].length = (unsigned short) prv->ulValueLen; -+ memcpy(bufs[i], prv->pValue, prv->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ -+ priv.elements[i].tag = TAG_DH_PUBLIC; -+ priv.elements[i].length = (unsigned short) pub->ulValueLen; -+ memcpy(bufs[i], pub->pValue, pub->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ -+ priv.nelements = i; -+ result = dst__privstruct_writefile(key, &priv, directory); -+ fail: -+ for (i = 0; i < 4; i++) { -+ if (bufs[i] == NULL) -+ break; -+ memset(bufs[i], 0, prime->ulValueLen); -+ isc_mem_put(key->mctx, bufs[i], prime->ulValueLen); -+ } -+ return (result); -+} -+ -+static isc_result_t -+pkcs11dh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { -+ dst_private_t priv; -+ isc_result_t ret; -+ int i; -+ pk11_object_t *dh = NULL; -+ CK_ATTRIBUTE *attr; -+ isc_mem_t *mctx; -+ -+ UNUSED(pub); -+ mctx = key->mctx; -+ -+ /* read private key file */ -+ ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv); -+ if (ret != ISC_R_SUCCESS) -+ return (ret); -+ -+ if (key->external) -+ DST_RET(DST_R_EXTERNALKEY); -+ -+ dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh)); -+ if (dh == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(dh, 0, sizeof(*dh)); -+ key->keydata.pkey = dh; -+ dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4); -+ if (dh->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(dh->repr, 0, sizeof(*attr) * 4); -+ dh->attrcnt = 4; -+ attr = dh->repr; -+ attr[0].type = CKA_PRIME; -+ attr[1].type = CKA_BASE; -+ attr[2].type = CKA_VALUE; -+ attr[3].type = CKA_VALUE2; -+ -+ for (i = 0; i < priv.nelements; i++) { -+ CK_BYTE *bn; -+ -+ bn = isc_mem_get(key->mctx, priv.elements[i].length); -+ if (bn == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(bn, priv.elements[i].data, priv.elements[i].length); -+ -+ switch (priv.elements[i].tag) { -+ case TAG_DH_PRIME: -+ attr = pk11_attribute_bytype(dh, CKA_PRIME); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_DH_GENERATOR: -+ attr = pk11_attribute_bytype(dh, CKA_BASE); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_DH_PRIVATE: -+ attr = pk11_attribute_bytype(dh, CKA_VALUE2); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_DH_PUBLIC: -+ attr = pk11_attribute_bytype(dh, CKA_VALUE); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ } -+ } -+ dst__privstruct_free(&priv, mctx); -+ -+ attr = pk11_attribute_bytype(dh, CKA_PRIME); -+ INSIST(attr != NULL); -+ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11dh_destroy(key); -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ret); -+} -+ -+static dst_func_t pkcs11dh_functions = { -+ NULL, /*%< createctx */ -+ NULL, /*%< createctx2 */ -+ NULL, /*%< destroyctx */ -+ NULL, /*%< adddata */ -+ NULL, /*%< sign */ -+ NULL, /*%< verify */ -+ NULL, /*%< verify2 */ -+ pkcs11dh_computesecret, -+ pkcs11dh_compare, -+ pkcs11dh_paramcompare, -+ pkcs11dh_generate, -+ pkcs11dh_isprivate, -+ pkcs11dh_destroy, -+ pkcs11dh_todns, -+ pkcs11dh_fromdns, -+ pkcs11dh_tofile, -+ pkcs11dh_parse, -+ NULL, /*%< cleanup */ -+ NULL, /*%< fromlabel */ -+ NULL, /*%< dump */ -+ NULL, /*%< restore */ -+}; -+ -+isc_result_t -+dst__pkcs11dh_init(dst_func_t **funcp) { -+ REQUIRE(funcp != NULL); -+ if (*funcp == NULL) -+ *funcp = &pkcs11dh_functions; -+ return (ISC_R_SUCCESS); -+} -+ -+#else /* PKCS11CRYPTO */ -+ -+#include -+ -+EMPTY_TRANSLATION_UNIT -+ -+#endif /* PKCS11CRYPTO */ -+/*! \file */ -diff --git a/lib/dns/pkcs11dsa_link.c b/lib/dns/pkcs11dsa_link.c -new file mode 100644 -index 0000000..6c8e46c ---- /dev/null -+++ b/lib/dns/pkcs11dsa_link.c -@@ -0,0 +1,1130 @@ -+/* -+ * Portions Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * -+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+#ifdef PKCS11CRYPTO -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "dst_internal.h" -+#include "dst_parse.h" -+#include "dst_pkcs11.h" -+ -+#include -+ -+/* -+ * FIPS 186-2 DSA keys: -+ * mechanisms: -+ * CKM_DSA_SHA1, -+ * CKM_DSA_KEY_PAIR_GEN, -+ * CKM_DSA_PARAMETER_GEN -+ * domain parameters: -+ * object class CKO_DOMAIN_PARAMETERS -+ * key type CKK_DSA -+ * attribute CKA_PRIME (prime p) -+ * attribute CKA_SUBPRIME (subprime q) -+ * attribute CKA_BASE (base g) -+ * optional attribute CKA_PRIME_BITS (p length in bits) -+ * public keys: -+ * object class CKO_PUBLIC_KEY -+ * key type CKK_DSA -+ * attribute CKA_PRIME (prime p) -+ * attribute CKA_SUBPRIME (subprime q) -+ * attribute CKA_BASE (base g) -+ * attribute CKA_VALUE (public value y) -+ * private keys: -+ * object class CKO_PRIVATE_KEY -+ * key type CKK_DSA -+ * attribute CKA_PRIME (prime p) -+ * attribute CKA_SUBPRIME (subprime q) -+ * attribute CKA_BASE (base g) -+ * attribute CKA_VALUE (private value x) -+ * reuse CKA_PRIVATE_EXPONENT for key pair private value -+ */ -+ -+#define CKA_VALUE2 CKA_PRIVATE_EXPONENT -+ -+#define DST_RET(a) {ret = a; goto err;} -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+static isc_result_t pkcs11dsa_todns(const dst_key_t *key, isc_buffer_t *data); -+static void pkcs11dsa_destroy(dst_key_t *key); -+ -+static isc_result_t -+pkcs11dsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_DSA_SHA1, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE keyType = CKK_DSA; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_PRIME, NULL, 0 }, -+ { CKA_SUBPRIME, NULL, 0 }, -+ { CKA_BASE, NULL, 0 }, -+ { CKA_VALUE, NULL, 0 } -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *dsa; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ unsigned int i; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_DSA)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ dsa = key->keydata.pkey; -+ if (dsa->ontoken && (dsa->object != CK_INVALID_HANDLE)) { -+ pk11_ctx->ontoken = dsa->ontoken; -+ pk11_ctx->object = dsa->object; -+ goto token_key; -+ } -+ -+ for (attr = pk11_attribute_first(dsa); -+ attr != NULL; -+ attr = pk11_attribute_next(dsa, attr)) -+ switch (attr->type) { -+ case CKA_PRIME: -+ INSIST(keyTemplate[6].type == attr->type); -+ keyTemplate[6].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[6].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[6].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[6].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_SUBPRIME: -+ INSIST(keyTemplate[7].type == attr->type); -+ keyTemplate[7].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[7].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[7].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[7].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_BASE: -+ INSIST(keyTemplate[8].type == attr->type); -+ keyTemplate[8].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[8].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[8].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[8].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_VALUE2: -+ INSIST(keyTemplate[9].type == CKA_VALUE); -+ keyTemplate[9].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[9].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[9].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[9].ulValueLen = attr->ulValueLen; -+ break; -+ } -+ pk11_ctx->object = CK_INVALID_HANDLE; -+ pk11_ctx->ontoken = ISC_FALSE; -+ PK11_RET(pkcs_C_CreateObject, -+ (pk11_ctx->session, -+ keyTemplate, (CK_ULONG) 10, -+ &pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ token_key: -+ -+ PK11_RET(pkcs_C_SignInit, -+ (pk11_ctx->session, &mech, pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ dctx->ctxdata.pk11_ctx = pk11_ctx; -+ -+ for (i = 6; i <= 9; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object); -+ for (i = 6; i <= 9; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11dsa_createctx_verify(dst_key_t *key, dst_context_t *dctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_DSA_SHA1, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE keyType = CKK_DSA; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_PRIME, NULL, 0 }, -+ { CKA_SUBPRIME, NULL, 0 }, -+ { CKA_BASE, NULL, 0 }, -+ { CKA_VALUE, NULL, 0 } -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *dsa; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ unsigned int i; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_DSA)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ dsa = key->keydata.pkey; -+ if (dsa->ontoken && (dsa->object != CK_INVALID_HANDLE)) { -+ pk11_ctx->ontoken = dsa->ontoken; -+ pk11_ctx->object = dsa->object; -+ goto token_key; -+ } -+ -+ for (attr = pk11_attribute_first(dsa); -+ attr != NULL; -+ attr = pk11_attribute_next(dsa, attr)) -+ switch (attr->type) { -+ case CKA_PRIME: -+ INSIST(keyTemplate[5].type == attr->type); -+ keyTemplate[5].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[5].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[5].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[5].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_SUBPRIME: -+ INSIST(keyTemplate[6].type == attr->type); -+ keyTemplate[6].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[6].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[6].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[6].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_BASE: -+ INSIST(keyTemplate[7].type == attr->type); -+ keyTemplate[7].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[7].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[7].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[7].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_VALUE: -+ INSIST(keyTemplate[8].type == attr->type); -+ keyTemplate[8].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[8].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[8].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[8].ulValueLen = attr->ulValueLen; -+ break; -+ } -+ pk11_ctx->object = CK_INVALID_HANDLE; -+ pk11_ctx->ontoken = ISC_FALSE; -+ PK11_RET(pkcs_C_CreateObject, -+ (pk11_ctx->session, -+ keyTemplate, (CK_ULONG) 9, -+ &pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ token_key: -+ -+ PK11_RET(pkcs_C_VerifyInit, -+ (pk11_ctx->session, &mech, pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ dctx->ctxdata.pk11_ctx = pk11_ctx; -+ -+ for (i = 5; i <= 8; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object); -+ for (i = 5; i <= 8; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11dsa_createctx(dst_key_t *key, dst_context_t *dctx) { -+ if (dctx->use == DO_SIGN) -+ return (pkcs11dsa_createctx_sign(key, dctx)); -+ else -+ return (pkcs11dsa_createctx_verify(key, dctx)); -+} -+ -+static void -+pkcs11dsa_destroyctx(dst_context_t *dctx) { -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ -+ if (pk11_ctx != NULL) { -+ if (!pk11_ctx->ontoken && -+ (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, -+ pk11_ctx->object); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ dctx->ctxdata.pk11_ctx = NULL; -+ } -+} -+ -+static isc_result_t -+pkcs11dsa_adddata(dst_context_t *dctx, const isc_region_t *data) { -+ CK_RV rv; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ if (dctx->use == DO_SIGN) -+ PK11_CALL(pkcs_C_SignUpdate, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) data->base, -+ (CK_ULONG) data->length), -+ ISC_R_FAILURE); -+ else -+ PK11_CALL(pkcs_C_VerifyUpdate, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) data->base, -+ (CK_ULONG) data->length), -+ ISC_R_FAILURE); -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11dsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { -+ CK_RV rv; -+ CK_ULONG siglen = ISC_SHA1_DIGESTLENGTH * 2; -+ isc_region_t r; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ isc_buffer_availableregion(sig, &r); -+ if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1) -+ return (ISC_R_NOSPACE); -+ -+ PK11_RET(pkcs_C_SignFinal, -+ (pk11_ctx->session, (CK_BYTE_PTR) r.base + 1, &siglen), -+ DST_R_SIGNFAILURE); -+ if (siglen != ISC_SHA1_DIGESTLENGTH * 2) -+ return (DST_R_SIGNFAILURE); -+ -+ *r.base = (dctx->key->key_size - 512)/64; -+ isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1); -+ -+ err: -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11dsa_verify(dst_context_t *dctx, const isc_region_t *sig) { -+ CK_RV rv; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ PK11_CALL(pkcs_C_VerifyFinal, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) sig->base + 1, -+ (CK_ULONG) sig->length - 1), -+ DST_R_VERIFYFAILURE); -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11dsa_compare(const dst_key_t *key1, const dst_key_t *key2) { -+ pk11_object_t *dsa1, *dsa2; -+ CK_ATTRIBUTE *attr1, *attr2; -+ -+ dsa1 = key1->keydata.pkey; -+ dsa2 = key2->keydata.pkey; -+ -+ if ((dsa1 == NULL) && (dsa2 == NULL)) -+ return (ISC_TRUE); -+ else if ((dsa1 == NULL) || (dsa2 == NULL)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dsa1, CKA_PRIME); -+ attr2 = pk11_attribute_bytype(dsa2, CKA_PRIME); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dsa1, CKA_SUBPRIME); -+ attr2 = pk11_attribute_bytype(dsa2, CKA_SUBPRIME); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dsa1, CKA_BASE); -+ attr2 = pk11_attribute_bytype(dsa2, CKA_BASE); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dsa1, CKA_VALUE); -+ attr2 = pk11_attribute_bytype(dsa2, CKA_VALUE); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(dsa1, CKA_VALUE2); -+ attr2 = pk11_attribute_bytype(dsa2, CKA_VALUE2); -+ if (((attr1 != NULL) || (attr2 != NULL)) && -+ ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))) -+ return (ISC_FALSE); -+ -+ if (!dsa1->ontoken && !dsa2->ontoken) -+ return (ISC_TRUE); -+ else if (dsa1->ontoken || dsa2->ontoken || -+ (dsa1->object != dsa2->object)) -+ return (ISC_FALSE); -+ -+ return (ISC_TRUE); -+} -+ -+static isc_result_t -+pkcs11dsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_DSA_PARAMETER_GEN, NULL, 0 }; -+ CK_OBJECT_HANDLE dp = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS dpClass = CKO_DOMAIN_PARAMETERS; -+ CK_KEY_TYPE keyType = CKK_DSA; -+ CK_ULONG bits = 0; -+ CK_ATTRIBUTE dpTemplate[] = -+ { -+ { CKA_CLASS, &dpClass, (CK_ULONG) sizeof(dpClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIME_BITS, &bits, (CK_ULONG) sizeof(bits) }, -+ }; -+ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; -+ CK_ATTRIBUTE pubTemplate[] = -+ { -+ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_PRIME, NULL, 0 }, -+ { CKA_SUBPRIME, NULL, 0 }, -+ { CKA_BASE, NULL, 0 } -+ }; -+ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; -+ CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY; -+ CK_ATTRIBUTE privTemplate[] = -+ { -+ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *dsa; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ unsigned int i; -+ -+ UNUSED(unused); -+ UNUSED(callback); -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_DSA)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ bits = key->key_size; -+ PK11_RET(pkcs_C_GenerateKey, -+ (pk11_ctx->session, &mech, dpTemplate, (CK_ULONG) 5, &dp), -+ DST_R_CRYPTOFAILURE); -+ -+ dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa)); -+ if (dsa == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(dsa, 0, sizeof(*dsa)); -+ key->keydata.pkey = dsa; -+ dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5); -+ if (dsa->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(dsa->repr, 0, sizeof(*attr) * 5); -+ dsa->attrcnt = 5; -+ -+ attr = dsa->repr; -+ attr[0].type = CKA_PRIME; -+ attr[1].type = CKA_SUBPRIME; -+ attr[2].type = CKA_BASE; -+ attr[3].type = CKA_VALUE; -+ attr[4].type = CKA_VALUE2; -+ -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, dp, attr, 3), -+ DST_R_CRYPTOFAILURE); -+ -+ for (i = 0; i <= 2; i++) { -+ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen); -+ if (attr[i].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr[i].pValue, 0, attr[i].ulValueLen); -+ } -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, dp, attr, 3), -+ DST_R_CRYPTOFAILURE); -+ pubTemplate[5].pValue = attr[0].pValue; -+ pubTemplate[5].ulValueLen = attr[0].ulValueLen; -+ pubTemplate[6].pValue = attr[1].pValue; -+ pubTemplate[6].ulValueLen = attr[1].ulValueLen; -+ pubTemplate[7].pValue = attr[2].pValue; -+ pubTemplate[7].ulValueLen = attr[2].ulValueLen; -+ -+ mech.mechanism = CKM_DSA_KEY_PAIR_GEN; -+ PK11_RET(pkcs_C_GenerateKeyPair, -+ (pk11_ctx->session, &mech, -+ pubTemplate, (CK_ULONG) 8, -+ privTemplate, (CK_ULONG) 7, -+ &pub, &priv), -+ DST_R_CRYPTOFAILURE); -+ -+ attr = dsa->repr; -+ attr += 3; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ -+ attr++; -+ attr->type = CKA_VALUE; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->type = CKA_VALUE2; -+ -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, dp); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11dsa_destroy(key); -+ if (priv != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ if (pub != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ if (dp != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, dp); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11dsa_isprivate(const dst_key_t *key) { -+ pk11_object_t *dsa = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (dsa == NULL) -+ return (ISC_FALSE); -+ attr = pk11_attribute_bytype(dsa, CKA_VALUE2); -+ return (ISC_TF((attr != NULL) || dsa->ontoken)); -+} -+ -+static void -+pkcs11dsa_destroy(dst_key_t *key) { -+ pk11_object_t *dsa = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (dsa == NULL) -+ return; -+ -+ INSIST((dsa->object == CK_INVALID_HANDLE) || dsa->ontoken); -+ -+ for (attr = pk11_attribute_first(dsa); -+ attr != NULL; -+ attr = pk11_attribute_next(dsa, attr)) -+ switch (attr->type) { -+ case CKA_PRIME: -+ case CKA_SUBPRIME: -+ case CKA_BASE: -+ case CKA_VALUE: -+ case CKA_VALUE2: -+ if (attr->pValue != NULL) { -+ memset(attr->pValue, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, -+ attr->pValue, -+ attr->ulValueLen); -+ } -+ break; -+ } -+ if (dsa->repr != NULL) { -+ memset(dsa->repr, 0, dsa->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, -+ dsa->repr, -+ dsa->attrcnt * sizeof(*attr)); -+ } -+ memset(dsa, 0, sizeof(*dsa)); -+ isc_mem_put(key->mctx, dsa, sizeof(*dsa)); -+ key->keydata.pkey = NULL; -+} -+ -+ -+static isc_result_t -+pkcs11dsa_todns(const dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *dsa; -+ CK_ATTRIBUTE *attr; -+ isc_region_t r; -+ int dnslen; -+ unsigned int t, p_bytes; -+ CK_ATTRIBUTE *prime = NULL, *subprime = NULL; -+ CK_ATTRIBUTE *base = NULL, *pub_key = NULL; -+ CK_BYTE *cp; -+ -+ REQUIRE(key->keydata.pkey != NULL); -+ -+ dsa = key->keydata.pkey; -+ -+ for (attr = pk11_attribute_first(dsa); -+ attr != NULL; -+ attr = pk11_attribute_next(dsa, attr)) -+ switch (attr->type) { -+ case CKA_PRIME: -+ prime = attr; -+ break; -+ case CKA_SUBPRIME: -+ subprime = attr; -+ break; -+ case CKA_BASE: -+ base = attr; -+ break; -+ case CKA_VALUE: -+ pub_key = attr; -+ break; -+ } -+ REQUIRE((prime != NULL) && (subprime != NULL) && -+ (base != NULL) && (pub_key != NULL)); -+ -+ isc_buffer_availableregion(data, &r); -+ -+ t = (prime->ulValueLen - 64) / 8; -+ if (t > 8) -+ return (DST_R_INVALIDPUBLICKEY); -+ p_bytes = 64 + 8 * t; -+ -+ dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH; -+ if (r.length < (unsigned int) dnslen) -+ return (ISC_R_NOSPACE); -+ -+ memset(r.base, 0, dnslen); -+ *r.base++ = t; -+ cp = (CK_BYTE *) subprime->pValue; -+ memcpy(r.base + ISC_SHA1_DIGESTLENGTH - subprime->ulValueLen, -+ cp, subprime->ulValueLen); -+ r.base += ISC_SHA1_DIGESTLENGTH; -+ cp = (CK_BYTE *) prime->pValue; -+ memcpy(r.base + key->key_size/8 - prime->ulValueLen, -+ cp, prime->ulValueLen); -+ r.base += p_bytes; -+ cp = (CK_BYTE *) base->pValue; -+ memcpy(r.base + key->key_size/8 - base->ulValueLen, -+ cp, base->ulValueLen); -+ r.base += p_bytes; -+ cp = (CK_BYTE *) pub_key->pValue; -+ memcpy(r.base + key->key_size/8 - pub_key->ulValueLen, -+ cp, pub_key->ulValueLen); -+ r.base += p_bytes; -+ -+ isc_buffer_add(data, dnslen); -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+pkcs11dsa_fromdns(dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *dsa; -+ isc_region_t r; -+ unsigned int t, p_bytes; -+ CK_BYTE *prime, *subprime, *base, *pub_key; -+ CK_ATTRIBUTE *attr; -+ -+ isc_buffer_remainingregion(data, &r); -+ if (r.length == 0) -+ return (ISC_R_SUCCESS); -+ -+ dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa)); -+ if (dsa == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(dsa, 0, sizeof(*dsa)); -+ -+ t = (unsigned int) *r.base++; -+ if (t > 8) { -+ memset(dsa, 0, sizeof(*dsa)); -+ isc_mem_put(key->mctx, dsa, sizeof(*dsa)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ p_bytes = 64 + 8 * t; -+ -+ if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) { -+ memset(dsa, 0, sizeof(*dsa)); -+ isc_mem_put(key->mctx, dsa, sizeof(*dsa)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ -+ subprime = r.base; -+ r.base += ISC_SHA1_DIGESTLENGTH; -+ -+ prime = r.base; -+ r.base += p_bytes; -+ -+ base = r.base; -+ r.base += p_bytes; -+ -+ pub_key = r.base; -+ r.base += p_bytes; -+ -+ key->key_size = p_bytes * 8; -+ -+ isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes); -+ -+ dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4); -+ if (dsa->repr == NULL) -+ goto nomemory; -+ memset(dsa->repr, 0, sizeof(*attr) * 4); -+ dsa->attrcnt = 4; -+ -+ attr = dsa->repr; -+ attr[0].type = CKA_PRIME; -+ attr[0].pValue = isc_mem_get(key->mctx, p_bytes); -+ if (attr[0].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[0].pValue, prime, p_bytes); -+ attr[0].ulValueLen = p_bytes; -+ -+ attr[1].type = CKA_SUBPRIME; -+ attr[1].pValue = isc_mem_get(key->mctx, ISC_SHA1_DIGESTLENGTH); -+ if (attr[1].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[1].pValue, subprime, ISC_SHA1_DIGESTLENGTH); -+ attr[1].ulValueLen = ISC_SHA1_DIGESTLENGTH; -+ -+ attr[2].type = CKA_BASE; -+ attr[2].pValue = isc_mem_get(key->mctx, p_bytes); -+ if (attr[2].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[2].pValue, base, p_bytes); -+ attr[2].ulValueLen = p_bytes; -+ -+ attr[3].type = CKA_VALUE; -+ attr[3].pValue = isc_mem_get(key->mctx, p_bytes); -+ if (attr[3].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[3].pValue, pub_key, p_bytes); -+ attr[3].ulValueLen = p_bytes; -+ -+ key->keydata.pkey = dsa; -+ -+ return (ISC_R_SUCCESS); -+ -+ nomemory: -+ for (attr = pk11_attribute_first(dsa); -+ attr != NULL; -+ attr = pk11_attribute_next(dsa, attr)) -+ switch (attr->type) { -+ case CKA_PRIME: -+ case CKA_SUBPRIME: -+ case CKA_BASE: -+ case CKA_VALUE: -+ if (attr->pValue != NULL) { -+ memset(attr->pValue, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, -+ attr->pValue, -+ attr->ulValueLen); -+ } -+ break; -+ } -+ if (dsa->repr != NULL) { -+ memset(dsa->repr, 0, dsa->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, -+ dsa->repr, -+ dsa->attrcnt * sizeof(*attr)); -+ } -+ memset(dsa, 0, sizeof(*dsa)); -+ isc_mem_put(key->mctx, dsa, sizeof(*dsa)); -+ return (ISC_R_NOMEMORY); -+} -+ -+static isc_result_t -+pkcs11dsa_tofile(const dst_key_t *key, const char *directory) { -+ int cnt = 0; -+ pk11_object_t *dsa; -+ CK_ATTRIBUTE *attr; -+ CK_ATTRIBUTE *prime = NULL, *subprime = NULL, *base = NULL; -+ CK_ATTRIBUTE *pub_key = NULL, *priv_key = NULL; -+ dst_private_t priv; -+ unsigned char bufs[5][128]; -+ -+ if (key->keydata.pkey == NULL) -+ return (DST_R_NULLKEY); -+ -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } -+ -+ dsa = key->keydata.pkey; -+ -+ for (attr = pk11_attribute_first(dsa); -+ attr != NULL; -+ attr = pk11_attribute_next(dsa, attr)) -+ switch (attr->type) { -+ case CKA_PRIME: -+ prime = attr; -+ break; -+ case CKA_SUBPRIME: -+ subprime = attr; -+ break; -+ case CKA_BASE: -+ base = attr; -+ break; -+ case CKA_VALUE: -+ pub_key = attr; -+ break; -+ case CKA_VALUE2: -+ priv_key = attr; -+ break; -+ } -+ if ((prime == NULL) || (subprime == NULL) || (base == NULL) || -+ (pub_key == NULL) || (priv_key ==NULL)) -+ return (DST_R_NULLKEY); -+ -+ priv.elements[cnt].tag = TAG_DSA_PRIME; -+ priv.elements[cnt].length = (unsigned short) prime->ulValueLen; -+ memcpy(bufs[cnt], prime->pValue, prime->ulValueLen); -+ priv.elements[cnt].data = bufs[cnt]; -+ cnt++; -+ -+ priv.elements[cnt].tag = TAG_DSA_SUBPRIME; -+ priv.elements[cnt].length = (unsigned short) subprime->ulValueLen; -+ memcpy(bufs[cnt], subprime->pValue, subprime->ulValueLen); -+ priv.elements[cnt].data = bufs[cnt]; -+ cnt++; -+ -+ priv.elements[cnt].tag = TAG_DSA_BASE; -+ priv.elements[cnt].length = (unsigned short) base->ulValueLen; -+ memcpy(bufs[cnt], base->pValue, base->ulValueLen); -+ priv.elements[cnt].data = bufs[cnt]; -+ cnt++; -+ -+ priv.elements[cnt].tag = TAG_DSA_PRIVATE; -+ priv.elements[cnt].length = (unsigned short) priv_key->ulValueLen; -+ memcpy(bufs[cnt], priv_key->pValue, priv_key->ulValueLen); -+ priv.elements[cnt].data = bufs[cnt]; -+ cnt++; -+ -+ priv.elements[cnt].tag = TAG_DSA_PUBLIC; -+ priv.elements[cnt].length = (unsigned short) pub_key->ulValueLen; -+ memcpy(bufs[cnt], pub_key->pValue, pub_key->ulValueLen); -+ priv.elements[cnt].data = bufs[cnt]; -+ cnt++; -+ -+ priv.nelements = cnt; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+} -+ -+static isc_result_t -+pkcs11dsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { -+ dst_private_t priv; -+ isc_result_t ret; -+ int i; -+ pk11_object_t *dsa = NULL; -+ CK_ATTRIBUTE *attr; -+ isc_mem_t *mctx = key->mctx; -+ -+ /* read private key file */ -+ ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv); -+ if (ret != ISC_R_SUCCESS) -+ return (ret); -+ -+ if (key->external) { -+ if (priv.nelements != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ if (pub == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ -+ key->keydata.pkey = pub->keydata.pkey; -+ pub->keydata.pkey = NULL; -+ key->key_size = pub->key_size; -+ -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ -+ return (ISC_R_SUCCESS); -+ } -+ -+ dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa)); -+ if (dsa == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(dsa, 0, sizeof(*dsa)); -+ key->keydata.pkey = dsa; -+ -+ dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5); -+ if (dsa->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(dsa->repr, 0, sizeof(*attr) * 5); -+ dsa->attrcnt = 5; -+ attr = dsa->repr; -+ attr[0].type = CKA_PRIME; -+ attr[1].type = CKA_SUBPRIME; -+ attr[2].type = CKA_BASE; -+ attr[3].type = CKA_VALUE; -+ attr[4].type = CKA_VALUE2; -+ -+ for (i = 0; i < priv.nelements; i++) { -+ CK_BYTE *bn; -+ -+ bn = isc_mem_get(key->mctx, priv.elements[i].length); -+ if (bn == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(bn, -+ priv.elements[i].data, -+ priv.elements[i].length); -+ -+ switch (priv.elements[i].tag) { -+ case TAG_DSA_PRIME: -+ attr = pk11_attribute_bytype(dsa, CKA_PRIME); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_DSA_SUBPRIME: -+ attr = pk11_attribute_bytype(dsa, -+ CKA_SUBPRIME); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_DSA_BASE: -+ attr = pk11_attribute_bytype(dsa, CKA_BASE); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_DSA_PRIVATE: -+ attr = pk11_attribute_bytype(dsa, CKA_VALUE2); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_DSA_PUBLIC: -+ attr = pk11_attribute_bytype(dsa, CKA_VALUE); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ } -+ } -+ dst__privstruct_free(&priv, mctx); -+ -+ attr = pk11_attribute_bytype(dsa, CKA_PRIME); -+ INSIST(attr != NULL); -+ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11dsa_destroy(key); -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ret); -+} -+ -+static dst_func_t pkcs11dsa_functions = { -+ pkcs11dsa_createctx, -+ NULL, /*%< createctx2 */ -+ pkcs11dsa_destroyctx, -+ pkcs11dsa_adddata, -+ pkcs11dsa_sign, -+ pkcs11dsa_verify, -+ NULL, /*%< verify2 */ -+ NULL, /*%< computesecret */ -+ pkcs11dsa_compare, -+ NULL, /*%< paramcompare */ -+ pkcs11dsa_generate, -+ pkcs11dsa_isprivate, -+ pkcs11dsa_destroy, -+ pkcs11dsa_todns, -+ pkcs11dsa_fromdns, -+ pkcs11dsa_tofile, -+ pkcs11dsa_parse, -+ NULL, /*%< cleanup */ -+ NULL, /*%< fromlabel */ -+ NULL, /*%< dump */ -+ NULL, /*%< restore */ -+}; -+ -+isc_result_t -+dst__pkcs11dsa_init(dst_func_t **funcp) { -+ REQUIRE(funcp != NULL); -+ if (*funcp == NULL) -+ *funcp = &pkcs11dsa_functions; -+ return (ISC_R_SUCCESS); -+} -+ -+#else /* PKCS11CRYPTO */ -+ -+#include -+ -+EMPTY_TRANSLATION_UNIT -+ -+#endif /* PKCS11CRYPTO */ -+/*! \file */ -diff --git a/lib/dns/pkcs11ecdsa_link.c b/lib/dns/pkcs11ecdsa_link.c -new file mode 100644 -index 0000000..4f56050 ---- /dev/null -+++ b/lib/dns/pkcs11ecdsa_link.c -@@ -0,0 +1,1189 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+#include -+ -+#if defined(PKCS11CRYPTO) && defined(HAVE_PKCS11_ECDSA) -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "dst_internal.h" -+#include "dst_parse.h" -+#include "dst_pkcs11.h" -+ -+#include -+#include -+#define WANT_ECC_CURVES -+#include -+ -+#include -+ -+/* -+ * FIPS 186-3 ECDSA keys: -+ * mechanisms: -+ * CKM_ECDSA, -+ * CKM_EC_KEY_PAIR_GEN -+ * domain parameters: -+ * CKA_EC_PARAMS (choice with OID namedCurve) -+ * public keys: -+ * object class CKO_PUBLIC_KEY -+ * key type CKK_EC -+ * attribute CKA_EC_PARAMS (choice with OID namedCurve) -+ * attribute CKA_EC_POINT (point Q) -+ * private keys: -+ * object class CKO_PRIVATE_KEY -+ * key type CKK_EC -+ * attribute CKA_EC_PARAMS (choice with OID namedCurve) -+ * attribute CKA_VALUE (big int d) -+ * point format: 0x04 (octet-string) <2*size+1> 0x4 (uncompressed) -+ */ -+ -+#define TAG_OCTECT_STRING 0x04 -+#define UNCOMPRESSED 0x04 -+ -+#define DST_RET(a) {ret = a; goto err;} -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+static isc_result_t pkcs11ecdsa_todns(const dst_key_t *key, -+ isc_buffer_t *data); -+static void pkcs11ecdsa_destroy(dst_key_t *key); -+static isc_result_t pkcs11ecdsa_fetch(dst_key_t *key, const char *engine, -+ const char *label, dst_key_t *pub); -+ -+static isc_result_t -+pkcs11ecdsa_createctx(dst_key_t *key, dst_context_t *dctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = {0, NULL, 0 }; -+ CK_SLOT_ID slotid; -+ pk11_context_t *pk11_ctx; -+ pk11_object_t *ec = key->keydata.pkey; -+ isc_result_t ret; -+ -+ UNUSED(key); -+ REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || -+ dctx->key->key_alg == DST_ALG_ECDSA384); -+ -+ if (dctx->key->key_alg == DST_ALG_ECDSA256) -+ mech.mechanism = CKM_SHA256; -+ else -+ mech.mechanism = CKM_SHA384; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ if (ec->ontoken && (dctx->use == DO_SIGN)) -+ slotid = ec->slot; -+ else -+ slotid = pk11_get_best_token(OP_EC); -+ ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE, ISC_FALSE, -+ NULL, slotid); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ PK11_RET(pkcs_C_DigestInit, (pk11_ctx->session, &mech), ISC_R_FAILURE); -+ dctx->ctxdata.pk11_ctx = pk11_ctx; -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static void -+pkcs11ecdsa_destroyctx(dst_context_t *dctx) { -+ CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA384_DIGESTLENGTH; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ -+ REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || -+ dctx->key->key_alg == DST_ALG_ECDSA384); -+ -+ if (pk11_ctx != NULL) { -+ (void) pkcs_C_DigestFinal(pk11_ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ dctx->ctxdata.pk11_ctx = NULL; -+ } -+} -+ -+static isc_result_t -+pkcs11ecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) { -+ CK_RV rv; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 || -+ dctx->key->key_alg == DST_ALG_ECDSA384); -+ -+ PK11_CALL(pkcs_C_DigestUpdate, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) data->base, -+ (CK_ULONG) data->length), -+ ISC_R_FAILURE); -+ -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11ecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 }; -+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE keyType = CKK_EC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_EC_PARAMS, NULL, 0 }, -+ { CKA_VALUE, NULL, 0 } -+ }; -+ CK_ATTRIBUTE *attr; -+ CK_BYTE digest[ISC_SHA384_DIGESTLENGTH]; -+ CK_ULONG dgstlen; -+ CK_ULONG siglen; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ dst_key_t *key = dctx->key; -+ pk11_object_t *ec = key->keydata.pkey; -+ isc_region_t r; -+ isc_result_t ret = ISC_R_SUCCESS; -+ unsigned int i; -+ -+ REQUIRE(key->key_alg == DST_ALG_ECDSA256 || -+ key->key_alg == DST_ALG_ECDSA384); -+ REQUIRE(ec != NULL); -+ -+ if (key->key_alg == DST_ALG_ECDSA256) { -+ dgstlen = ISC_SHA256_DIGESTLENGTH; -+ siglen = DNS_SIG_ECDSA256SIZE; -+ } else { -+ siglen = DNS_SIG_ECDSA384SIZE; -+ dgstlen = ISC_SHA384_DIGESTLENGTH; -+ } -+ -+ PK11_RET(pkcs_C_DigestFinal, -+ (pk11_ctx->session, digest, &dgstlen), -+ ISC_R_FAILURE); -+ -+ isc_buffer_availableregion(sig, &r); -+ if (r.length < siglen) -+ DST_RET(ISC_R_NOSPACE); -+ -+ if (ec->ontoken && (ec->object != CK_INVALID_HANDLE)) { -+ pk11_ctx->ontoken = ec->ontoken; -+ pk11_ctx->object = ec->object; -+ goto token_key; -+ } -+ -+ for (attr = pk11_attribute_first(ec); -+ attr != NULL; -+ attr = pk11_attribute_next(ec, attr)) -+ switch (attr->type) { -+ case CKA_EC_PARAMS: -+ INSIST(keyTemplate[5].type == attr->type); -+ keyTemplate[5].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[5].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[5].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[5].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_VALUE: -+ INSIST(keyTemplate[6].type == attr->type); -+ keyTemplate[6].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[6].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[6].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[6].ulValueLen = attr->ulValueLen; -+ break; -+ } -+ pk11_ctx->object = CK_INVALID_HANDLE; -+ pk11_ctx->ontoken = ISC_FALSE; -+ PK11_RET(pkcs_C_CreateObject, -+ (pk11_ctx->session, -+ keyTemplate, (CK_ULONG) 7, -+ &hKey), -+ ISC_R_FAILURE); -+ -+ token_key: -+ -+ PK11_RET(pkcs_C_SignInit, -+ (pk11_ctx->session, &mech, -+ pk11_ctx->ontoken ? pk11_ctx->object : hKey), -+ ISC_R_FAILURE); -+ -+ PK11_RET(pkcs_C_Sign, -+ (pk11_ctx->session, -+ digest, dgstlen, -+ (CK_BYTE_PTR) r.base, &siglen), -+ DST_R_SIGNFAILURE); -+ -+ isc_buffer_add(sig, (unsigned int) siglen); -+ -+ err: -+ -+ if (hKey != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey); -+ for (i = 5; i <= 6; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ dctx->ctxdata.pk11_ctx = NULL; -+ -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11ecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 }; -+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE keyType = CKK_EC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_EC_PARAMS, NULL, 0 }, -+ { CKA_EC_POINT, NULL, 0 } -+ }; -+ CK_ATTRIBUTE *attr; -+ CK_BYTE digest[ISC_SHA384_DIGESTLENGTH]; -+ CK_ULONG dgstlen; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ dst_key_t *key = dctx->key; -+ pk11_object_t *ec = key->keydata.pkey; -+ isc_result_t ret = ISC_R_SUCCESS; -+ unsigned int i; -+ -+ REQUIRE(key->key_alg == DST_ALG_ECDSA256 || -+ key->key_alg == DST_ALG_ECDSA384); -+ REQUIRE(ec != NULL); -+ -+ if (key->key_alg == DST_ALG_ECDSA256) -+ dgstlen = ISC_SHA256_DIGESTLENGTH; -+ else -+ dgstlen = ISC_SHA384_DIGESTLENGTH; -+ -+ PK11_RET(pkcs_C_DigestFinal, -+ (pk11_ctx->session, digest, &dgstlen), -+ ISC_R_FAILURE); -+ -+ for (attr = pk11_attribute_first(ec); -+ attr != NULL; -+ attr = pk11_attribute_next(ec, attr)) -+ switch (attr->type) { -+ case CKA_EC_PARAMS: -+ INSIST(keyTemplate[5].type == attr->type); -+ keyTemplate[5].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[5].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[5].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[5].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_EC_POINT: -+ INSIST(keyTemplate[6].type == attr->type); -+ keyTemplate[6].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[6].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[6].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[6].ulValueLen = attr->ulValueLen; -+ break; -+ } -+ pk11_ctx->object = CK_INVALID_HANDLE; -+ pk11_ctx->ontoken = ISC_FALSE; -+ PK11_RET(pkcs_C_CreateObject, -+ (pk11_ctx->session, -+ keyTemplate, (CK_ULONG) 7, -+ &hKey), -+ ISC_R_FAILURE); -+ -+ PK11_RET(pkcs_C_VerifyInit, -+ (pk11_ctx->session, &mech, hKey), -+ ISC_R_FAILURE); -+ -+ PK11_RET(pkcs_C_Verify, -+ (pk11_ctx->session, -+ digest, dgstlen, -+ (CK_BYTE_PTR) sig->base, (CK_ULONG) sig->length), -+ DST_R_SIGNFAILURE); -+ -+ err: -+ -+ if (hKey != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey); -+ for (i = 5; i <= 6; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ dctx->ctxdata.pk11_ctx = NULL; -+ -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11ecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) { -+ pk11_object_t *ec1, *ec2; -+ CK_ATTRIBUTE *attr1, *attr2; -+ -+ ec1 = key1->keydata.pkey; -+ ec2 = key2->keydata.pkey; -+ -+ if ((ec1 == NULL) && (ec2 == NULL)) -+ return (ISC_TRUE); -+ else if ((ec1 == NULL) || (ec2 == NULL)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(ec1, CKA_EC_PARAMS); -+ attr2 = pk11_attribute_bytype(ec2, CKA_EC_PARAMS); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(ec1, CKA_EC_POINT); -+ attr2 = pk11_attribute_bytype(ec2, CKA_EC_POINT); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(ec1, CKA_VALUE); -+ attr2 = pk11_attribute_bytype(ec2, CKA_VALUE); -+ if (((attr1 != NULL) || (attr2 != NULL)) && -+ ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))) -+ return (ISC_FALSE); -+ -+ if (!ec1->ontoken && !ec2->ontoken) -+ return (ISC_TRUE); -+ else if (ec1->ontoken || ec2->ontoken || -+ (ec1->object != ec2->object)) -+ return (ISC_FALSE); -+ -+ return (ISC_TRUE); -+} -+ -+#define SETCURVE() \ -+ if (key->key_alg == DST_ALG_ECDSA256) { \ -+ attr->pValue = isc_mem_get(key->mctx, \ -+ sizeof(pk11_ecc_prime256v1)); \ -+ if (attr->pValue == NULL) \ -+ DST_RET(ISC_R_NOMEMORY); \ -+ memcpy(attr->pValue, \ -+ pk11_ecc_prime256v1, sizeof(pk11_ecc_prime256v1)); \ -+ attr->ulValueLen = sizeof(pk11_ecc_prime256v1); \ -+ } else { \ -+ attr->pValue = isc_mem_get(key->mctx, \ -+ sizeof(pk11_ecc_secp384r1)); \ -+ if (attr->pValue == NULL) \ -+ DST_RET(ISC_R_NOMEMORY); \ -+ memcpy(attr->pValue, \ -+ pk11_ecc_secp384r1, sizeof(pk11_ecc_secp384r1)); \ -+ attr->ulValueLen = sizeof(pk11_ecc_secp384r1); \ -+ } -+ -+#define FREECURVE() \ -+ if (attr->pValue != NULL) { \ -+ memset(attr->pValue, 0, attr->ulValueLen); \ -+ isc_mem_put(key->mctx, attr->pValue, attr->ulValueLen); \ -+ attr->pValue = NULL; \ -+ } -+ -+static isc_result_t -+pkcs11ecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_EC_KEY_PAIR_GEN, NULL, 0 }; -+ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE keyType = CKK_EC; -+ CK_ATTRIBUTE pubTemplate[] = -+ { -+ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_EC_PARAMS, NULL, 0 } -+ }; -+ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; -+ CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY; -+ CK_ATTRIBUTE privTemplate[] = -+ { -+ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) } -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *ec; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ -+ REQUIRE(key->key_alg == DST_ALG_ECDSA256 || -+ key->key_alg == DST_ALG_ECDSA384); -+ UNUSED(unused); -+ UNUSED(callback); -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_EC)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec)); -+ if (ec == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(ec, 0, sizeof(*ec)); -+ key->keydata.pkey = ec; -+ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3); -+ if (ec->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(ec->repr, 0, sizeof(*attr) * 3); -+ ec->attrcnt = 3; -+ -+ attr = ec->repr; -+ attr[0].type = CKA_EC_PARAMS; -+ attr[1].type = CKA_EC_POINT; -+ attr[2].type = CKA_VALUE; -+ -+ attr = &pubTemplate[5]; -+ SETCURVE(); -+ -+ PK11_RET(pkcs_C_GenerateKeyPair, -+ (pk11_ctx->session, &mech, -+ pubTemplate, (CK_ULONG) 6, -+ privTemplate, (CK_ULONG) 7, -+ &pub, &priv), -+ DST_R_CRYPTOFAILURE); -+ -+ attr = &pubTemplate[5]; -+ FREECURVE(); -+ -+ attr = ec->repr; -+ SETCURVE(); -+ -+ attr++; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ -+ attr++; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11ecdsa_destroy(key); -+ if (priv != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ if (pub != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11ecdsa_isprivate(const dst_key_t *key) { -+ pk11_object_t *ec = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (ec == NULL) -+ return (ISC_FALSE); -+ attr = pk11_attribute_bytype(ec, CKA_VALUE); -+ return (ISC_TF((attr != NULL) || ec->ontoken)); -+} -+ -+static void -+pkcs11ecdsa_destroy(dst_key_t *key) { -+ pk11_object_t *ec = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (ec == NULL) -+ return; -+ -+ INSIST((ec->object == CK_INVALID_HANDLE) || ec->ontoken); -+ -+ for (attr = pk11_attribute_first(ec); -+ attr != NULL; -+ attr = pk11_attribute_next(ec, attr)) -+ switch (attr->type) { -+ case CKA_LABEL: -+ case CKA_ID: -+ case CKA_EC_PARAMS: -+ case CKA_EC_POINT: -+ case CKA_VALUE: -+ FREECURVE(); -+ break; -+ } -+ if (ec->repr != NULL) { -+ memset(ec->repr, 0, ec->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, -+ ec->repr, -+ ec->attrcnt * sizeof(*attr)); -+ } -+ memset(ec, 0, sizeof(*ec)); -+ isc_mem_put(key->mctx, ec, sizeof(*ec)); -+ key->keydata.pkey = NULL; -+} -+ -+static isc_result_t -+pkcs11ecdsa_todns(const dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *ec; -+ isc_region_t r; -+ unsigned int len; -+ CK_ATTRIBUTE *attr; -+ -+ REQUIRE(key->keydata.pkey != NULL); -+ -+ if (key->key_alg == DST_ALG_ECDSA256) -+ len = DNS_KEY_ECDSA256SIZE; -+ else -+ len = DNS_KEY_ECDSA384SIZE; -+ -+ ec = key->keydata.pkey; -+ attr = pk11_attribute_bytype(ec, CKA_EC_POINT); -+ if ((attr == NULL) || -+ (attr->ulValueLen != len + 3) || -+ (((CK_BYTE_PTR) attr->pValue)[0] != TAG_OCTECT_STRING) || -+ (((CK_BYTE_PTR) attr->pValue)[1] != len + 1) || -+ (((CK_BYTE_PTR) attr->pValue)[2] != UNCOMPRESSED)) -+ return (ISC_R_FAILURE); -+ -+ isc_buffer_availableregion(data, &r); -+ if (r.length < len) -+ return (ISC_R_NOSPACE); -+ memcpy(r.base, (CK_BYTE_PTR) attr->pValue + 3, len); -+ isc_buffer_add(data, len); -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+pkcs11ecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *ec; -+ isc_region_t r; -+ unsigned int len; -+ CK_ATTRIBUTE *attr; -+ -+ REQUIRE(key->key_alg == DST_ALG_ECDSA256 || -+ key->key_alg == DST_ALG_ECDSA384); -+ -+ if (key->key_alg == DST_ALG_ECDSA256) -+ len = DNS_KEY_ECDSA256SIZE; -+ else -+ len = DNS_KEY_ECDSA384SIZE; -+ -+ isc_buffer_remainingregion(data, &r); -+ if (r.length == 0) -+ return (ISC_R_SUCCESS); -+ if (r.length != len) -+ return (DST_R_INVALIDPUBLICKEY); -+ -+ ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec)); -+ if (ec == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(ec, 0, sizeof(*ec)); -+ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); -+ if (ec->repr == NULL) -+ goto nomemory; -+ ec->attrcnt = 2; -+ -+ attr = ec->repr; -+ attr->type = CKA_EC_PARAMS; -+ if (key->key_alg == DST_ALG_ECDSA256) { -+ attr->pValue = -+ isc_mem_get(key->mctx, sizeof(pk11_ecc_prime256v1)); -+ if (attr->pValue == NULL) -+ goto nomemory; -+ memcpy(attr->pValue, -+ pk11_ecc_prime256v1, sizeof(pk11_ecc_prime256v1)); -+ attr->ulValueLen = sizeof(pk11_ecc_prime256v1); -+ } else { -+ attr->pValue = -+ isc_mem_get(key->mctx, sizeof(pk11_ecc_secp384r1)); -+ if (attr->pValue == NULL) -+ goto nomemory; -+ memcpy(attr->pValue, -+ pk11_ecc_secp384r1, sizeof(pk11_ecc_secp384r1)); -+ attr->ulValueLen = sizeof(pk11_ecc_secp384r1); -+ } -+ -+ attr++; -+ attr->type = CKA_EC_POINT; -+ attr->pValue = isc_mem_get(key->mctx, len + 3); -+ if (attr->pValue == NULL) -+ goto nomemory; -+ ((CK_BYTE_PTR) attr->pValue)[0] = TAG_OCTECT_STRING; -+ ((CK_BYTE_PTR) attr->pValue)[1] = len + 1; -+ ((CK_BYTE_PTR) attr->pValue)[2] = UNCOMPRESSED; -+ memcpy((CK_BYTE_PTR) attr->pValue + 3, r.base, len); -+ attr->ulValueLen = len + 3; -+ -+ isc_buffer_forward(data, len); -+ key->keydata.pkey = ec; -+ return (ISC_R_SUCCESS); -+ -+ nomemory: -+ for (attr = pk11_attribute_first(ec); -+ attr != NULL; -+ attr = pk11_attribute_next(ec, attr)) -+ switch (attr->type) { -+ case CKA_EC_PARAMS: -+ case CKA_EC_POINT: -+ FREECURVE(); -+ break; -+ } -+ if (ec->repr != NULL) { -+ memset(ec->repr, 0, ec->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, -+ ec->repr, -+ ec->attrcnt * sizeof(*attr)); -+ } -+ memset(ec, 0, sizeof(*ec)); -+ isc_mem_put(key->mctx, ec, sizeof(*ec)); -+ return (ISC_R_NOMEMORY); -+} -+ -+static isc_result_t -+pkcs11ecdsa_tofile(const dst_key_t *key, const char *directory) { -+ isc_result_t ret; -+ pk11_object_t *ec; -+ dst_private_t priv; -+ unsigned char *buf = NULL; -+ unsigned int i = 0; -+ CK_ATTRIBUTE *attr; -+ -+ if (key->keydata.pkey == NULL) -+ return (DST_R_NULLKEY); -+ -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } -+ -+ ec = key->keydata.pkey; -+ attr = pk11_attribute_bytype(ec, CKA_VALUE); -+ if (attr != NULL) { -+ buf = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (buf == NULL) -+ return (ISC_R_NOMEMORY); -+ priv.elements[i].tag = TAG_ECDSA_PRIVATEKEY; -+ priv.elements[i].length = (unsigned short) attr->ulValueLen; -+ memcpy(buf, attr->pValue, attr->ulValueLen); -+ priv.elements[i].data = buf; -+ i++; -+ } -+ -+ if (key->engine != NULL) { -+ priv.elements[i].tag = TAG_ECDSA_ENGINE; -+ priv.elements[i].length = strlen(key->engine) + 1; -+ priv.elements[i].data = (unsigned char *)key->engine; -+ i++; -+ } -+ -+ if (key->label != NULL) { -+ priv.elements[i].tag = TAG_ECDSA_LABEL; -+ priv.elements[i].length = strlen(key->label) + 1; -+ priv.elements[i].data = (unsigned char *)key->label; -+ i++; -+ } -+ -+ priv.nelements = i; -+ ret = dst__privstruct_writefile(key, &priv, directory); -+ -+ if (buf != NULL) { -+ memset(buf, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, buf, attr->ulValueLen); -+ } -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11ecdsa_fetch(dst_key_t *key, const char *engine, const char *label, -+ dst_key_t *pub) -+{ -+ CK_RV rv; -+ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE keyType = CKK_EC; -+ CK_ATTRIBUTE searchTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_LABEL, NULL, 0 } -+ }; -+ CK_ULONG cnt; -+ CK_ATTRIBUTE *attr; -+ CK_ATTRIBUTE *pubattr; -+ pk11_object_t *ec; -+ pk11_object_t *pubec; -+ pk11_context_t *pk11_ctx = NULL; -+ isc_result_t ret; -+ -+ if (label == NULL) -+ return (DST_R_NOENGINE); -+ -+ ec = key->keydata.pkey; -+ pubec = pub->keydata.pkey; -+ -+ ec->object = CK_INVALID_HANDLE; -+ ec->ontoken = ISC_TRUE; -+ ec->reqlogon = ISC_TRUE; -+ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); -+ if (ec->repr == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(ec->repr, 0, sizeof(*attr) * 2); -+ ec->attrcnt = 2; -+ attr = ec->repr; -+ -+ attr->type = CKA_EC_PARAMS; -+ pubattr = pk11_attribute_bytype(pubec, CKA_EC_PARAMS); -+ attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, pubattr->pValue, pubattr->ulValueLen); -+ attr->ulValueLen = pubattr->ulValueLen; -+ attr++; -+ -+ attr->type = CKA_EC_POINT; -+ pubattr = pk11_attribute_bytype(pubec, CKA_EC_POINT); -+ attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, pubattr->pValue, pubattr->ulValueLen); -+ attr->ulValueLen = pubattr->ulValueLen; -+ -+ ret = pk11_parse_uri(ec, label, key->mctx, OP_EC); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE, -+ ec->reqlogon, NULL, ec->slot); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ attr = pk11_attribute_bytype(ec, CKA_LABEL); -+ if (attr == NULL) { -+ attr = pk11_attribute_bytype(ec, CKA_ID); -+ INSIST(attr != NULL); -+ searchTemplate[3].type = CKA_ID; -+ } -+ searchTemplate[3].pValue = attr->pValue; -+ searchTemplate[3].ulValueLen = attr->ulValueLen; -+ -+ PK11_RET(pkcs_C_FindObjectsInit, -+ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), -+ DST_R_CRYPTOFAILURE); -+ PK11_RET(pkcs_C_FindObjects, -+ (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt), -+ DST_R_CRYPTOFAILURE); -+ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); -+ if (cnt == 0) -+ DST_RET(ISC_R_NOTFOUND); -+ if (cnt > 1) -+ DST_RET(ISC_R_EXISTS); -+ -+ if (engine != NULL) { -+ key->engine = isc_mem_strdup(key->mctx, engine); -+ if (key->engine == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ } -+ -+ key->label = isc_mem_strdup(key->mctx, label); -+ if (key->label == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ return (ISC_R_SUCCESS); -+ -+ err: -+ if (pk11_ctx != NULL) { -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ } -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11ecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { -+ dst_private_t priv; -+ isc_result_t ret; -+ pk11_object_t *ec = NULL; -+ CK_ATTRIBUTE *attr, *pattr; -+ isc_mem_t *mctx = key->mctx; -+ unsigned int i; -+ const char *engine = NULL, *label = NULL; -+ -+ REQUIRE(key->key_alg == DST_ALG_ECDSA256 || -+ key->key_alg == DST_ALG_ECDSA384); -+ -+ if ((pub == NULL) || (pub->keydata.pkey == NULL)) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ -+ /* read private key file */ -+ ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv); -+ if (ret != ISC_R_SUCCESS) -+ return (ret); -+ -+ if (key->external) { -+ if (priv.nelements != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ -+ key->keydata.pkey = pub->keydata.pkey; -+ pub->keydata.pkey = NULL; -+ key->key_size = pub->key_size; -+ -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ -+ return (ISC_R_SUCCESS); -+ } -+ -+ for (i = 0; i < priv.nelements; i++) { -+ switch (priv.elements[i].tag) { -+ case TAG_ECDSA_ENGINE: -+ engine = (char *)priv.elements[i].data; -+ break; -+ case TAG_ECDSA_LABEL: -+ label = (char *)priv.elements[i].data; -+ break; -+ default: -+ break; -+ } -+ } -+ ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec)); -+ if (ec == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(ec, 0, sizeof(*ec)); -+ key->keydata.pkey = ec; -+ -+ /* Is this key is stored in a HSM? See if we can fetch it. */ -+ if ((label != NULL) || (engine != NULL)) { -+ ret = pkcs11ecdsa_fetch(key, engine, label, pub); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ret); -+ } -+ -+ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3); -+ if (ec->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(ec->repr, 0, sizeof(*attr) * 3); -+ ec->attrcnt = 3; -+ -+ attr = ec->repr; -+ attr->type = CKA_EC_PARAMS; -+ pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_PARAMS); -+ INSIST(pattr != NULL); -+ attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, pattr->pValue, pattr->ulValueLen); -+ attr->ulValueLen = pattr->ulValueLen; -+ -+ attr++; -+ attr->type = CKA_EC_POINT; -+ pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_POINT); -+ INSIST(pattr != NULL); -+ attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, pattr->pValue, pattr->ulValueLen); -+ attr->ulValueLen = pattr->ulValueLen; -+ -+ attr++; -+ attr->type = CKA_VALUE; -+ attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, priv.elements[0].data, priv.elements[0].length); -+ attr->ulValueLen = priv.elements[0].length; -+ -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11ecdsa_destroy(key); -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11ecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label, -+ const char *pin) -+{ -+ CK_RV rv; -+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE keyType = CKK_EC; -+ CK_ATTRIBUTE searchTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_LABEL, NULL, 0 } -+ }; -+ CK_ULONG cnt; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *ec; -+ pk11_context_t *pk11_ctx = NULL; -+ isc_result_t ret; -+ unsigned int i; -+ -+ UNUSED(pin); -+ -+ ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec)); -+ if (ec == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(ec, 0, sizeof(*ec)); -+ ec->object = CK_INVALID_HANDLE; -+ ec->ontoken = ISC_TRUE; -+ ec->reqlogon = ISC_TRUE; -+ key->keydata.pkey = ec; -+ -+ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); -+ if (ec->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(ec->repr, 0, sizeof(*attr) * 2); -+ ec->attrcnt = 2; -+ attr = ec->repr; -+ attr[0].type = CKA_EC_PARAMS; -+ attr[1].type = CKA_EC_POINT; -+ -+ ret = pk11_parse_uri(ec, label, key->mctx, OP_EC); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE, -+ ec->reqlogon, NULL, ec->slot); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ attr = pk11_attribute_bytype(ec, CKA_LABEL); -+ if (attr == NULL) { -+ attr = pk11_attribute_bytype(ec, CKA_ID); -+ INSIST(attr != NULL); -+ searchTemplate[3].type = CKA_ID; -+ } -+ searchTemplate[3].pValue = attr->pValue; -+ searchTemplate[3].ulValueLen = attr->ulValueLen; -+ -+ PK11_RET(pkcs_C_FindObjectsInit, -+ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), -+ DST_R_CRYPTOFAILURE); -+ PK11_RET(pkcs_C_FindObjects, -+ (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt), -+ DST_R_CRYPTOFAILURE); -+ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); -+ if (cnt == 0) -+ DST_RET(ISC_R_NOTFOUND); -+ if (cnt > 1) -+ DST_RET(ISC_R_EXISTS); -+ -+ attr = ec->repr; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, hKey, attr, 2), -+ DST_R_CRYPTOFAILURE); -+ for (i = 0; i <= 1; i++) { -+ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen); -+ if (attr[i].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr[i].pValue, 0, attr[i].ulValueLen); -+ } -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, hKey, attr, 2), -+ DST_R_CRYPTOFAILURE); -+ -+ keyClass = CKO_PRIVATE_KEY; -+ PK11_RET(pkcs_C_FindObjectsInit, -+ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), -+ DST_R_CRYPTOFAILURE); -+ PK11_RET(pkcs_C_FindObjects, -+ (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt), -+ DST_R_CRYPTOFAILURE); -+ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); -+ if (cnt == 0) -+ DST_RET(ISC_R_NOTFOUND); -+ if (cnt > 1) -+ DST_RET(ISC_R_EXISTS); -+ -+ if (engine != NULL) { -+ key->engine = isc_mem_strdup(key->mctx, engine); -+ if (key->engine == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ } -+ -+ key->label = isc_mem_strdup(key->mctx, label); -+ if (key->label == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11ecdsa_destroy(key); -+ if (pk11_ctx != NULL) { -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ } -+ return (ret); -+} -+ -+static dst_func_t pkcs11ecdsa_functions = { -+ pkcs11ecdsa_createctx, -+ NULL, /*%< createctx2 */ -+ pkcs11ecdsa_destroyctx, -+ pkcs11ecdsa_adddata, -+ pkcs11ecdsa_sign, -+ pkcs11ecdsa_verify, -+ NULL, /*%< verify2 */ -+ NULL, /*%< computesecret */ -+ pkcs11ecdsa_compare, -+ NULL, /*%< paramcompare */ -+ pkcs11ecdsa_generate, -+ pkcs11ecdsa_isprivate, -+ pkcs11ecdsa_destroy, -+ pkcs11ecdsa_todns, -+ pkcs11ecdsa_fromdns, -+ pkcs11ecdsa_tofile, -+ pkcs11ecdsa_parse, -+ NULL, /*%< cleanup */ -+ pkcs11ecdsa_fromlabel, -+ NULL, /*%< dump */ -+ NULL, /*%< restore */ -+}; -+ -+isc_result_t -+dst__pkcs11ecdsa_init(dst_func_t **funcp) { -+ REQUIRE(funcp != NULL); -+ if (*funcp == NULL) -+ *funcp = &pkcs11ecdsa_functions; -+ return (ISC_R_SUCCESS); -+} -+ -+#else /* PKCS11CRYPTO && HAVE_PKCS11_ECDSA */ -+ -+#include -+ -+EMPTY_TRANSLATION_UNIT -+ -+#endif /* PKCS11CRYPTO && HAVE_PKCS11_ECDSA */ -+/*! \file */ -diff --git a/lib/dns/pkcs11gost_link.c b/lib/dns/pkcs11gost_link.c -new file mode 100644 -index 0000000..c03b285 ---- /dev/null -+++ b/lib/dns/pkcs11gost_link.c -@@ -0,0 +1,949 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+#include -+ -+#if defined(PKCS11CRYPTO) && defined(HAVE_PKCS11_GOST) -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "dst_internal.h" -+#include "dst_parse.h" -+#include "dst_pkcs11.h" -+#include "dst_gost.h" -+ -+#include -+#include -+#define WANT_GOST_PARAMS -+#include -+ -+#include -+ -+/* -+ * RU CryptoPro GOST keys: -+ * mechanisms: -+ * CKM_GOSTR3411 -+ * CKM_GOSTR3410_WITH_GOSTR3411 -+ * CKM_GOSTR3410_KEY_PAIR_GEN -+ * domain parameters: -+ * CKA_GOSTR3410_PARAMS (fixed BER OID 1.2.643.2.2.35.1) -+ * CKA_GOSTR3411_PARAMS (fixed BER OID 1.2.643.2.2.30.1) -+ * CKA_GOST28147_PARAMS (optional, don't use) -+ * public keys: -+ * object class CKO_PUBLIC_KEY -+ * key type CKK_GOSTR3410 -+ * attribute CKA_VALUE (point Q) -+ * attribute CKA_GOSTR3410_PARAMS -+ * attribute CKA_GOSTR3411_PARAMS -+ * attribute CKA_GOST28147_PARAMS -+ * private keys: -+ * object class CKO_PRIVATE_KEY -+ * key type CKK_GOSTR3410 -+ * attribute CKA_VALUE (big int d) -+ * attribute CKA_GOSTR3410_PARAMS -+ * attribute CKA_GOSTR3411_PARAMS -+ * attribute CKA_GOST28147_PARAMS -+ * point format: (little endian) -+ */ -+ -+#define CKA_VALUE2 CKA_PRIVATE_EXPONENT -+ -+#define ISC_GOST_SIGNATURELENGTH 64 -+#define ISC_GOST_PUBKEYLENGTH 64 -+ -+/* HASH methods */ -+ -+isc_result_t -+isc_gost_init(isc_gost_t *ctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_GOSTR3411, NULL, 0 }; -+ int ret = ISC_R_SUCCESS; -+ -+ ret = pk11_get_session(ctx, OP_GOST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0); -+ if (ret != ISC_R_SUCCESS) -+ return (ret); -+ PK11_CALL(pkcs_C_DigestInit, (ctx->session, &mech), ISC_R_FAILURE); -+ return (ret); -+} -+ -+void -+isc_gost_invalidate(isc_gost_t *ctx) { -+ CK_BYTE garbage[ISC_GOST_DIGESTLENGTH]; -+ CK_ULONG len = ISC_GOST_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_DigestFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ pk11_return_session(ctx); -+} -+ -+isc_result_t -+isc_gost_update(isc_gost_t *ctx, const unsigned char *buf, unsigned int len) { -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ int ret = ISC_R_SUCCESS; -+ -+ DE_CONST(buf, pPart); -+ PK11_CALL(pkcs_C_DigestUpdate, -+ (ctx->session, pPart, (CK_ULONG) len), -+ ISC_R_FAILURE); -+ return (ret); -+} -+ -+isc_result_t -+isc_gost_final(isc_gost_t *ctx, unsigned char *digest) { -+ CK_RV rv; -+ CK_ULONG len = ISC_GOST_DIGESTLENGTH; -+ int ret = ISC_R_SUCCESS; -+ -+ PK11_CALL(pkcs_C_DigestFinal, -+ (ctx->session, (CK_BYTE_PTR) digest, &len), -+ ISC_R_FAILURE); -+ pk11_return_session(ctx); -+ return (ret); -+} -+ -+/* DST methods */ -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+#define DST_RET(a) {ret = a; goto err;} -+ -+static isc_result_t pkcs11gost_todns(const dst_key_t *key, isc_buffer_t *data); -+static void pkcs11gost_destroy(dst_key_t *key); -+ -+static isc_result_t -+pkcs11gost_createctx_sign(dst_key_t *key, dst_context_t *dctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_GOSTR3410_WITH_GOSTR3411, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE keyType = CKK_GOSTR3410; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, 0 }, -+ { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset, -+ (CK_ULONG) sizeof(pk11_gost_a_paramset) }, -+ { CKA_GOSTR3411_PARAMS, pk11_gost_paramset, -+ (CK_ULONG) sizeof(pk11_gost_paramset) } -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *gost; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ unsigned int i; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_GOST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_GOST)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ gost = key->keydata.pkey; -+ if (gost->ontoken && (gost->object != CK_INVALID_HANDLE)) { -+ pk11_ctx->ontoken = gost->ontoken; -+ pk11_ctx->object = gost->object; -+ goto token_key; -+ } -+ -+ for (attr = pk11_attribute_first(gost); -+ attr != NULL; -+ attr = pk11_attribute_next(gost, attr)) -+ switch (attr->type) { -+ case CKA_VALUE2: -+ INSIST(keyTemplate[6].type == CKA_VALUE); -+ keyTemplate[6].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[6].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[6].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[6].ulValueLen = attr->ulValueLen; -+ break; -+ } -+ pk11_ctx->object = CK_INVALID_HANDLE; -+ pk11_ctx->ontoken = ISC_FALSE; -+ PK11_RET(pkcs_C_CreateObject, -+ (pk11_ctx->session, -+ keyTemplate, (CK_ULONG) 9, -+ &pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ token_key: -+ -+ PK11_RET(pkcs_C_SignInit, -+ (pk11_ctx->session, &mech, pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ dctx->ctxdata.pk11_ctx = pk11_ctx; -+ -+ for (i = 6; i <= 6; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object); -+ for (i = 6; i <= 6; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11gost_createctx_verify(dst_key_t *key, dst_context_t *dctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_GOSTR3410_WITH_GOSTR3411, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE keyType = CKK_GOSTR3410; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, 0 }, -+ { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset, -+ (CK_ULONG) sizeof(pk11_gost_a_paramset) }, -+ { CKA_GOSTR3411_PARAMS, pk11_gost_paramset, -+ (CK_ULONG) sizeof(pk11_gost_paramset) } -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *gost; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ unsigned int i; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_GOST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_GOST)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ gost = key->keydata.pkey; -+ if (gost->ontoken && (gost->object != CK_INVALID_HANDLE)) { -+ pk11_ctx->ontoken = gost->ontoken; -+ pk11_ctx->object = gost->object; -+ goto token_key; -+ } -+ -+ for (attr = pk11_attribute_first(gost); -+ attr != NULL; -+ attr = pk11_attribute_next(gost, attr)) -+ switch (attr->type) { -+ case CKA_VALUE: -+ INSIST(keyTemplate[5].type == attr->type); -+ keyTemplate[5].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[5].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[5].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[5].ulValueLen = attr->ulValueLen; -+ break; -+ } -+ pk11_ctx->object = CK_INVALID_HANDLE; -+ pk11_ctx->ontoken = ISC_FALSE; -+ PK11_RET(pkcs_C_CreateObject, -+ (pk11_ctx->session, -+ keyTemplate, (CK_ULONG) 8, -+ &pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ token_key: -+ -+ PK11_RET(pkcs_C_VerifyInit, -+ (pk11_ctx->session, &mech, pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ dctx->ctxdata.pk11_ctx = pk11_ctx; -+ -+ for (i = 5; i <= 5; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object); -+ for (i = 5; i <= 5; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11gost_createctx(dst_key_t *key, dst_context_t *dctx) { -+ if (dctx->use == DO_SIGN) -+ return (pkcs11gost_createctx_sign(key, dctx)); -+ else -+ return (pkcs11gost_createctx_verify(key, dctx)); -+} -+ -+static void -+pkcs11gost_destroyctx(dst_context_t *dctx) { -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ -+ if (pk11_ctx != NULL) { -+ if (!pk11_ctx->ontoken && -+ (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, -+ pk11_ctx->object); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ dctx->ctxdata.pk11_ctx = NULL; -+ } -+} -+ -+static isc_result_t -+pkcs11gost_adddata(dst_context_t *dctx, const isc_region_t *data) { -+ CK_RV rv; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ if (dctx->use == DO_SIGN) -+ PK11_CALL(pkcs_C_SignUpdate, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) data->base, -+ (CK_ULONG) data->length), -+ ISC_R_FAILURE); -+ else -+ PK11_CALL(pkcs_C_VerifyUpdate, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) data->base, -+ (CK_ULONG) data->length), -+ ISC_R_FAILURE); -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11gost_sign(dst_context_t *dctx, isc_buffer_t *sig) { -+ CK_RV rv; -+ CK_ULONG siglen = ISC_GOST_SIGNATURELENGTH; -+ isc_region_t r; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ isc_buffer_availableregion(sig, &r); -+ if (r.length < ISC_GOST_SIGNATURELENGTH) -+ return (ISC_R_NOSPACE); -+ -+ PK11_RET(pkcs_C_SignFinal, -+ (pk11_ctx->session, (CK_BYTE_PTR) r.base, &siglen), -+ DST_R_SIGNFAILURE); -+ if (siglen != ISC_GOST_SIGNATURELENGTH) -+ return (DST_R_SIGNFAILURE); -+ -+ isc_buffer_add(sig, ISC_GOST_SIGNATURELENGTH); -+ -+ err: -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11gost_verify(dst_context_t *dctx, const isc_region_t *sig) { -+ CK_RV rv; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ PK11_CALL(pkcs_C_VerifyFinal, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) sig->base, -+ (CK_ULONG) sig->length), -+ DST_R_VERIFYFAILURE); -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11gost_compare(const dst_key_t *key1, const dst_key_t *key2) { -+ pk11_object_t *gost1, *gost2; -+ CK_ATTRIBUTE *attr1, *attr2; -+ -+ gost1 = key1->keydata.pkey; -+ gost2 = key2->keydata.pkey; -+ -+ if ((gost1 == NULL) && (gost2 == NULL)) -+ return (ISC_TRUE); -+ else if ((gost1 == NULL) || (gost2 == NULL)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(gost1, CKA_VALUE); -+ attr2 = pk11_attribute_bytype(gost2, CKA_VALUE); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(gost1, CKA_VALUE2); -+ attr2 = pk11_attribute_bytype(gost2, CKA_VALUE2); -+ if (((attr1 != NULL) || (attr2 != NULL)) && -+ ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))) -+ return (ISC_FALSE); -+ -+ if (!gost1->ontoken && !gost2->ontoken) -+ return (ISC_TRUE); -+ else if (gost1->ontoken || gost2->ontoken || -+ (gost1->object != gost2->object)) -+ return (ISC_FALSE); -+ -+ return (ISC_TRUE); -+} -+ -+static isc_result_t -+pkcs11gost_generate(dst_key_t *key, int unused, void (*callback)(int)) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_GOSTR3410_KEY_PAIR_GEN, NULL, 0 }; -+ CK_KEY_TYPE keyType = CKK_GOSTR3410; -+ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; -+ CK_ATTRIBUTE pubTemplate[] = -+ { -+ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset, -+ (CK_ULONG) sizeof(pk11_gost_a_paramset) }, -+ { CKA_GOSTR3411_PARAMS, pk11_gost_paramset, -+ (CK_ULONG) sizeof(pk11_gost_paramset) } -+ }; -+ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; -+ CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY; -+ CK_ATTRIBUTE privTemplate[] = -+ { -+ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *gost; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ -+ UNUSED(unused); -+ UNUSED(callback); -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_GOST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_GOST)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ PK11_RET(pkcs_C_GenerateKeyPair, -+ (pk11_ctx->session, &mech, -+ pubTemplate, (CK_ULONG) 7, -+ privTemplate, (CK_ULONG) 7, -+ &pub, &priv), -+ DST_R_CRYPTOFAILURE); -+ -+ gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost)); -+ if (gost == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(gost, 0, sizeof(*gost)); -+ key->keydata.pkey = gost; -+ gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, -+ sizeof(*attr) * 2); -+ if (gost->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(gost->repr, 0, sizeof(*attr) * 2); -+ gost->attrcnt = 2; -+ -+ attr = gost->repr; -+ attr[0].type = CKA_VALUE; -+ attr[1].type = CKA_VALUE2; -+ -+ attr = gost->repr; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ -+ attr++; -+ attr->type = CKA_VALUE; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr->pValue, 0, attr->ulValueLen); -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 1), -+ DST_R_CRYPTOFAILURE); -+ attr->type = CKA_VALUE2; -+ -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11gost_destroy(key); -+ if (priv != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ if (pub != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11gost_isprivate(const dst_key_t *key) { -+ pk11_object_t *gost = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (gost == NULL) -+ return (ISC_FALSE); -+ attr = pk11_attribute_bytype(gost, CKA_VALUE2); -+ return (ISC_TF((attr != NULL) || gost->ontoken)); -+} -+ -+static void -+pkcs11gost_destroy(dst_key_t *key) { -+ pk11_object_t *gost = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (gost == NULL) -+ return; -+ -+ INSIST((gost->object == CK_INVALID_HANDLE) || gost->ontoken); -+ -+ for (attr = pk11_attribute_first(gost); -+ attr != NULL; -+ attr = pk11_attribute_next(gost, attr)) -+ switch (attr->type) { -+ case CKA_VALUE: -+ case CKA_VALUE2: -+ if (attr->pValue != NULL) { -+ memset(attr->pValue, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, -+ attr->pValue, -+ attr->ulValueLen); -+ } -+ break; -+ } -+ if (gost->repr != NULL) { -+ memset(gost->repr, 0, gost->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, -+ gost->repr, -+ gost->attrcnt * sizeof(*attr)); -+ } -+ memset(gost, 0, sizeof(*gost)); -+ isc_mem_put(key->mctx, gost, sizeof(*gost)); -+ key->keydata.pkey = NULL; -+} -+ -+static isc_result_t -+pkcs11gost_todns(const dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *gost; -+ isc_region_t r; -+ CK_ATTRIBUTE *attr; -+ -+ REQUIRE(key->keydata.pkey != NULL); -+ -+ gost = key->keydata.pkey; -+ attr = pk11_attribute_bytype(gost, CKA_VALUE); -+ if ((attr == NULL) || (attr->ulValueLen != ISC_GOST_PUBKEYLENGTH)) -+ return (ISC_R_FAILURE); -+ -+ isc_buffer_availableregion(data, &r); -+ if (r.length < ISC_GOST_PUBKEYLENGTH) -+ return (ISC_R_NOSPACE); -+ memcpy(r.base, (CK_BYTE_PTR) attr->pValue, ISC_GOST_PUBKEYLENGTH); -+ isc_buffer_add(data, ISC_GOST_PUBKEYLENGTH); -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+pkcs11gost_fromdns(dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *gost; -+ isc_region_t r; -+ CK_ATTRIBUTE *attr; -+ -+ isc_buffer_remainingregion(data, &r); -+ if (r.length == 0) -+ return (ISC_R_SUCCESS); -+ if (r.length != ISC_GOST_PUBKEYLENGTH) -+ return (DST_R_INVALIDPUBLICKEY); -+ -+ gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost)); -+ if (gost == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(gost, 0, sizeof(*gost)); -+ gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr)); -+ if (gost->repr == NULL) -+ goto nomemory; -+ gost->attrcnt = 1; -+ -+ attr = gost->repr; -+ attr->type = CKA_VALUE; -+ attr->pValue = isc_mem_get(key->mctx, ISC_GOST_PUBKEYLENGTH); -+ if (attr->pValue == NULL) -+ goto nomemory; -+ memcpy((CK_BYTE_PTR) attr->pValue, r.base, ISC_GOST_PUBKEYLENGTH); -+ attr->ulValueLen = ISC_GOST_PUBKEYLENGTH; -+ -+ isc_buffer_forward(data, ISC_GOST_PUBKEYLENGTH); -+ key->keydata.pkey = gost; -+ return (ISC_R_SUCCESS); -+ -+ nomemory: -+ for (attr = pk11_attribute_first(gost); -+ attr != NULL; -+ attr = pk11_attribute_next(gost, attr)) -+ switch (attr->type) { -+ case CKA_VALUE: -+ if (attr->pValue != NULL) { -+ memset(attr->pValue, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, -+ attr->pValue, -+ attr->ulValueLen); -+ } -+ break; -+ } -+ if (gost->repr != NULL) { -+ memset(gost->repr, 0, gost->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, -+ gost->repr, -+ gost->attrcnt * sizeof(*attr)); -+ } -+ memset(gost, 0, sizeof(*gost)); -+ isc_mem_put(key->mctx, gost, sizeof(*gost)); -+ return (ISC_R_NOMEMORY); -+} -+ -+static unsigned char gost_private_der[39] = { -+ 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06, -+ 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30, -+ 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, -+ 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, -+ 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20 -+}; -+ -+#ifdef PREFER_GOSTASN1 -+ -+static isc_result_t -+pkcs11gost_tofile(const dst_key_t *key, const char *directory) { -+ isc_result_t ret; -+ pk11_object_t *gost; -+ dst_private_t priv; -+ unsigned char *buf = NULL; -+ unsigned int i = 0; -+ CK_ATTRIBUTE *attr; -+ int adj; -+ -+ if (key->keydata.pkey == NULL) -+ return (DST_R_NULLKEY); -+ -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } -+ -+ gost = key->keydata.pkey; -+ attr = pk11_attribute_bytype(gost, CKA_VALUE2); -+ if (attr != NULL) { -+ buf = isc_mem_get(key->mctx, attr->ulValueLen + 39); -+ if (buf == NULL) -+ return (ISC_R_NOMEMORY); -+ priv.elements[i].tag = TAG_GOST_PRIVASN1; -+ priv.elements[i].length = -+ (unsigned short) attr->ulValueLen + 39; -+ memcpy(buf, gost_private_der, 39); -+ memcpy(buf +39, attr->pValue, attr->ulValueLen); -+ adj = (int) attr->ulValueLen - 32; -+ if (adj != 0) { -+ buf[1] += adj; -+ buf[36] += adj; -+ buf[38] += adj; -+ } -+ priv.elements[i].data = buf; -+ i++; -+ } else -+ return (DST_R_CRYPTOFAILURE); -+ -+ priv.nelements = i; -+ ret = dst__privstruct_writefile(key, &priv, directory); -+ -+ if (buf != NULL) { -+ memset(buf, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, buf, attr->ulValueLen); -+ } -+ return (ret); -+} -+ -+#else -+ -+static isc_result_t -+pkcs11gost_tofile(const dst_key_t *key, const char *directory) { -+ isc_result_t ret; -+ pk11_object_t *gost; -+ dst_private_t priv; -+ unsigned char *buf = NULL; -+ unsigned int i = 0; -+ CK_ATTRIBUTE *attr; -+ -+ if (key->keydata.pkey == NULL) -+ return (DST_R_NULLKEY); -+ -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } -+ -+ gost = key->keydata.pkey; -+ attr = pk11_attribute_bytype(gost, CKA_VALUE2); -+ if (attr != NULL) { -+ buf = isc_mem_get(key->mctx, attr->ulValueLen); -+ if (buf == NULL) -+ return (ISC_R_NOMEMORY); -+ priv.elements[i].tag = TAG_GOST_PRIVRAW; -+ priv.elements[i].length = (unsigned short) attr->ulValueLen; -+ memcpy(buf, attr->pValue, attr->ulValueLen); -+ priv.elements[i].data = buf; -+ i++; -+ } else -+ return (DST_R_CRYPTOFAILURE); -+ -+ priv.nelements = i; -+ ret = dst__privstruct_writefile(key, &priv, directory); -+ -+ if (buf != NULL) { -+ memset(buf, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, buf, attr->ulValueLen); -+ } -+ return (ret); -+} -+#endif -+ -+static isc_result_t -+pkcs11gost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { -+ dst_private_t priv; -+ isc_result_t ret; -+ pk11_object_t *gost = NULL; -+ CK_ATTRIBUTE *attr, *pattr; -+ isc_mem_t *mctx = key->mctx; -+ -+ if ((pub == NULL) || (pub->keydata.pkey == NULL)) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ -+ /* read private key file */ -+ ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv); -+ if (ret != ISC_R_SUCCESS) -+ return (ret); -+ -+ if (key->external) { -+ if (priv.nelements != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ -+ key->keydata.pkey = pub->keydata.pkey; -+ pub->keydata.pkey = NULL; -+ key->key_size = pub->key_size; -+ -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ -+ return (ISC_R_SUCCESS); -+ } -+ -+ if (priv.elements[0].tag == TAG_GOST_PRIVASN1) { -+ int adj = (int) priv.elements[0].length - (39 + 32); -+ unsigned char buf[39]; -+ -+ if ((adj > 0) || (adj < -31)) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ memcpy(buf, gost_private_der, 39); -+ if (adj != 0) { -+ buf[1] += adj; -+ buf[36] += adj; -+ buf[38] += adj; -+ } -+ if (memcmp(priv.elements[0].data, buf, 39) != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ priv.elements[0].tag = TAG_GOST_PRIVRAW; -+ priv.elements[0].length -= 39; -+ memmove(priv.elements[0].data, -+ priv.elements[0].data + 39, -+ 32 + adj); -+ } -+ -+ gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost)); -+ if (gost == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(gost, 0, sizeof(*gost)); -+ key->keydata.pkey = gost; -+ -+ gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, -+ sizeof(*attr) * 2); -+ if (gost->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(gost->repr, 0, sizeof(*attr) * 2); -+ gost->attrcnt = 2; -+ -+ attr = gost->repr; -+ attr->type = CKA_VALUE; -+ pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE); -+ INSIST(pattr != NULL); -+ attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, pattr->pValue, pattr->ulValueLen); -+ attr->ulValueLen = pattr->ulValueLen; -+ -+ attr++; -+ attr->type = CKA_VALUE2; -+ attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, priv.elements[0].data, priv.elements[0].length); -+ attr->ulValueLen = priv.elements[0].length; -+ -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11gost_destroy(key); -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ret); -+} -+ -+static dst_func_t pkcs11gost_functions = { -+ pkcs11gost_createctx, -+ NULL, /*%< createctx2 */ -+ pkcs11gost_destroyctx, -+ pkcs11gost_adddata, -+ pkcs11gost_sign, -+ pkcs11gost_verify, -+ NULL, /*%< verify2 */ -+ NULL, /*%< computesecret */ -+ pkcs11gost_compare, -+ NULL, /*%< paramcompare */ -+ pkcs11gost_generate, -+ pkcs11gost_isprivate, -+ pkcs11gost_destroy, -+ pkcs11gost_todns, -+ pkcs11gost_fromdns, -+ pkcs11gost_tofile, -+ pkcs11gost_parse, -+ NULL, /*%< cleanup */ -+ NULL, /*%< fromlabel */ -+ NULL, /*%< dump */ -+ NULL, /*%< restore */ -+}; -+ -+isc_result_t -+dst__pkcs11gost_init(dst_func_t **funcp) { -+ REQUIRE(funcp != NULL); -+ if (*funcp == NULL) -+ *funcp = &pkcs11gost_functions; -+ return (ISC_R_SUCCESS); -+} -+ -+#else /* PKCS11CRYPTO && HAVE_PKCS11_GOST */ -+ -+#include -+ -+EMPTY_TRANSLATION_UNIT -+ -+#endif /* PKCS11CRYPTO && HAVE_PKCS11_GOST */ -+/*! \file */ -diff --git a/lib/dns/pkcs11rsa_link.c b/lib/dns/pkcs11rsa_link.c -new file mode 100644 -index 0000000..010d4b6 ---- /dev/null -+++ b/lib/dns/pkcs11rsa_link.c -@@ -0,0 +1,1583 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+#ifdef PKCS11CRYPTO -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "dst_internal.h" -+#include "dst_parse.h" -+#include "dst_pkcs11.h" -+ -+#include -+ -+/* -+ * Limit the size of public exponents. -+ */ -+#ifndef RSA_MAX_PUBEXP_BITS -+#define RSA_MAX_PUBEXP_BITS 35 -+#endif -+ -+#define DST_RET(a) {ret = a; goto err;} -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+static isc_result_t pkcs11rsa_todns(const dst_key_t *key, isc_buffer_t *data); -+static void pkcs11rsa_destroy(dst_key_t *key); -+static isc_result_t pkcs11rsa_fetch(dst_key_t *key, const char *engine, -+ const char *label, dst_key_t *pub); -+ -+static isc_result_t -+pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { 0, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE keyType = CKK_RSA; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_MODULUS, NULL, 0 }, -+ { CKA_PUBLIC_EXPONENT, NULL, 0 }, -+ { CKA_PRIVATE_EXPONENT, NULL, 0 }, -+ { CKA_PRIME_1, NULL, 0 }, -+ { CKA_PRIME_2, NULL, 0 }, -+ { CKA_EXPONENT_1, NULL, 0 }, -+ { CKA_EXPONENT_2, NULL, 0 }, -+ { CKA_COEFFICIENT, NULL, 0 } -+ }; -+ CK_ATTRIBUTE *attr; -+ CK_SLOT_ID slotid; -+ pk11_object_t *rsa; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ unsigned int i; -+ -+ REQUIRE(key->key_alg == DST_ALG_RSAMD5 || -+ key->key_alg == DST_ALG_RSASHA1 || -+ key->key_alg == DST_ALG_NSEC3RSASHA1 || -+ key->key_alg == DST_ALG_RSASHA256 || -+ key->key_alg == DST_ALG_RSASHA512); -+ -+ rsa = key->keydata.pkey; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ if (rsa->ontoken) -+ slotid = rsa->slot; -+ else -+ slotid = pk11_get_best_token(OP_RSA); -+ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, -+ rsa->reqlogon, NULL, slotid); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ if (rsa->ontoken && (rsa->object != CK_INVALID_HANDLE)) { -+ pk11_ctx->ontoken = rsa->ontoken; -+ pk11_ctx->object = rsa->object; -+ goto token_key; -+ } -+ -+ for (attr = pk11_attribute_first(rsa); -+ attr != NULL; -+ attr = pk11_attribute_next(rsa, attr)) -+ switch (attr->type) { -+ case CKA_MODULUS: -+ INSIST(keyTemplate[6].type == attr->type); -+ keyTemplate[6].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[6].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[6].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[6].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_PUBLIC_EXPONENT: -+ INSIST(keyTemplate[7].type == attr->type); -+ keyTemplate[7].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[7].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[7].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[7].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_PRIVATE_EXPONENT: -+ INSIST(keyTemplate[8].type == attr->type); -+ keyTemplate[8].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[8].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[8].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[8].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_PRIME_1: -+ INSIST(keyTemplate[9].type == attr->type); -+ keyTemplate[9].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[9].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[9].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[9].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_PRIME_2: -+ INSIST(keyTemplate[10].type == attr->type); -+ keyTemplate[10].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[10].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[10].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[10].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_EXPONENT_1: -+ INSIST(keyTemplate[11].type == attr->type); -+ keyTemplate[11].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[11].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[11].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[11].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_EXPONENT_2: -+ INSIST(keyTemplate[12].type == attr->type); -+ keyTemplate[12].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[12].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[12].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[12].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_COEFFICIENT: -+ INSIST(keyTemplate[13].type == attr->type); -+ keyTemplate[13].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[13].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[13].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[13].ulValueLen = attr->ulValueLen; -+ break; -+ } -+ pk11_ctx->object = CK_INVALID_HANDLE; -+ pk11_ctx->ontoken = ISC_FALSE; -+ PK11_RET(pkcs_C_CreateObject, -+ (pk11_ctx->session, -+ keyTemplate, (CK_ULONG) 14, -+ &pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ token_key: -+ -+ switch (dctx->key->key_alg) { -+ case DST_ALG_RSAMD5: -+ mech.mechanism = CKM_MD5_RSA_PKCS; -+ break; -+ case DST_ALG_RSASHA1: -+ case DST_ALG_NSEC3RSASHA1: -+ mech.mechanism = CKM_SHA1_RSA_PKCS; -+ break; -+ case DST_ALG_RSASHA256: -+ mech.mechanism = CKM_SHA256_RSA_PKCS; -+ break; -+ case DST_ALG_RSASHA512: -+ mech.mechanism = CKM_SHA512_RSA_PKCS; -+ break; -+ default: -+ INSIST(0); -+ } -+ -+ PK11_RET(pkcs_C_SignInit, -+ (pk11_ctx->session, &mech, pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ dctx->ctxdata.pk11_ctx = pk11_ctx; -+ -+ for (i = 6; i <= 13; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, -+ pk11_ctx->object); -+ for (i = 6; i <= 13; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits, -+ dst_context_t *dctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { 0, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE keyType = CKK_RSA; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_MODULUS, NULL, 0 }, -+ { CKA_PUBLIC_EXPONENT, NULL, 0 }, -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *rsa; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ unsigned int i; -+ -+ REQUIRE(key->key_alg == DST_ALG_RSAMD5 || -+ key->key_alg == DST_ALG_RSASHA1 || -+ key->key_alg == DST_ALG_NSEC3RSASHA1 || -+ key->key_alg == DST_ALG_RSASHA256 || -+ key->key_alg == DST_ALG_RSASHA512); -+ -+ rsa = key->keydata.pkey; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, -+ rsa->reqlogon, NULL, -+ pk11_get_best_token(OP_RSA)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ for (attr = pk11_attribute_first(rsa); -+ attr != NULL; -+ attr = pk11_attribute_next(rsa, attr)) -+ switch (attr->type) { -+ case CKA_MODULUS: -+ INSIST(keyTemplate[5].type == attr->type); -+ keyTemplate[5].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[5].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[5].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[5].ulValueLen = attr->ulValueLen; -+ break; -+ case CKA_PUBLIC_EXPONENT: -+ INSIST(keyTemplate[6].type == attr->type); -+ keyTemplate[6].pValue = isc_mem_get(dctx->mctx, -+ attr->ulValueLen); -+ if (keyTemplate[6].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(keyTemplate[6].pValue, -+ attr->pValue, -+ attr->ulValueLen); -+ keyTemplate[6].ulValueLen = attr->ulValueLen; -+ if (pk11_numbits(attr->pValue, -+ attr->ulValueLen) > maxbits && -+ maxbits != 0) -+ DST_RET(DST_R_VERIFYFAILURE); -+ break; -+ } -+ pk11_ctx->object = CK_INVALID_HANDLE; -+ pk11_ctx->ontoken = ISC_FALSE; -+ PK11_RET(pkcs_C_CreateObject, -+ (pk11_ctx->session, -+ keyTemplate, (CK_ULONG) 7, -+ &pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ switch (dctx->key->key_alg) { -+ case DST_ALG_RSAMD5: -+ mech.mechanism = CKM_MD5_RSA_PKCS; -+ break; -+ case DST_ALG_RSASHA1: -+ case DST_ALG_NSEC3RSASHA1: -+ mech.mechanism = CKM_SHA1_RSA_PKCS; -+ break; -+ case DST_ALG_RSASHA256: -+ mech.mechanism = CKM_SHA256_RSA_PKCS; -+ break; -+ case DST_ALG_RSASHA512: -+ mech.mechanism = CKM_SHA512_RSA_PKCS; -+ break; -+ default: -+ INSIST(0); -+ } -+ -+ PK11_RET(pkcs_C_VerifyInit, -+ (pk11_ctx->session, &mech, pk11_ctx->object), -+ ISC_R_FAILURE); -+ -+ dctx->ctxdata.pk11_ctx = pk11_ctx; -+ -+ for (i = 5; i <= 6; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, -+ pk11_ctx->object); -+ for (i = 5; i <= 6; i++) -+ if (keyTemplate[i].pValue != NULL) { -+ memset(keyTemplate[i].pValue, 0, -+ keyTemplate[i].ulValueLen); -+ isc_mem_put(dctx->mctx, -+ keyTemplate[i].pValue, -+ keyTemplate[i].ulValueLen); -+ } -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11rsa_createctx(dst_key_t *key, dst_context_t *dctx) { -+ if (dctx->use == DO_SIGN) -+ return (pkcs11rsa_createctx_sign(key, dctx)); -+ else -+ return (pkcs11rsa_createctx_verify(key, 0U, dctx)); -+} -+ -+static isc_result_t -+pkcs11rsa_createctx2(dst_key_t *key, int maxbits, dst_context_t *dctx) { -+ if (dctx->use == DO_SIGN) -+ return (pkcs11rsa_createctx_sign(key, dctx)); -+ else -+ return (pkcs11rsa_createctx_verify(key, -+ (unsigned) maxbits, dctx)); -+} -+ -+static void -+pkcs11rsa_destroyctx(dst_context_t *dctx) { -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ -+ if (pk11_ctx != NULL) { -+ if (!pk11_ctx->ontoken && -+ (pk11_ctx->object != CK_INVALID_HANDLE)) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, -+ pk11_ctx->object); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ dctx->ctxdata.pk11_ctx = NULL; -+ } -+} -+ -+static isc_result_t -+pkcs11rsa_adddata(dst_context_t *dctx, const isc_region_t *data) { -+ CK_RV rv; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ if (dctx->use == DO_SIGN) -+ PK11_CALL(pkcs_C_SignUpdate, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) data->base, -+ (CK_ULONG) data->length), -+ ISC_R_FAILURE); -+ else -+ PK11_CALL(pkcs_C_VerifyUpdate, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) data->base, -+ (CK_ULONG) data->length), -+ ISC_R_FAILURE); -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11rsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { -+ CK_RV rv; -+ CK_ULONG siglen = 0; -+ isc_region_t r; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ PK11_RET(pkcs_C_SignFinal, -+ (pk11_ctx->session, NULL, &siglen), -+ DST_R_SIGNFAILURE); -+ -+ isc_buffer_availableregion(sig, &r); -+ -+ if (r.length < (unsigned int) siglen) -+ return (ISC_R_NOSPACE); -+ -+ PK11_RET(pkcs_C_SignFinal, -+ (pk11_ctx->session, (CK_BYTE_PTR) r.base, &siglen), -+ DST_R_SIGNFAILURE); -+ -+ isc_buffer_add(sig, (unsigned int) siglen); -+ -+ err: -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11rsa_verify(dst_context_t *dctx, const isc_region_t *sig) { -+ CK_RV rv; -+ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ PK11_CALL(pkcs_C_VerifyFinal, -+ (pk11_ctx->session, -+ (CK_BYTE_PTR) sig->base, -+ (CK_ULONG) sig->length), -+ DST_R_VERIFYFAILURE); -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11rsa_compare(const dst_key_t *key1, const dst_key_t *key2) { -+ pk11_object_t *rsa1, *rsa2; -+ CK_ATTRIBUTE *attr1, *attr2; -+ -+ rsa1 = key1->keydata.pkey; -+ rsa2 = key2->keydata.pkey; -+ -+ if ((rsa1 == NULL) && (rsa2 == NULL)) -+ return (ISC_TRUE); -+ else if ((rsa1 == NULL) || (rsa2 == NULL)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(rsa1, CKA_MODULUS); -+ attr2 = pk11_attribute_bytype(rsa2, CKA_MODULUS); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(rsa1, CKA_PUBLIC_EXPONENT); -+ attr2 = pk11_attribute_bytype(rsa2, CKA_PUBLIC_EXPONENT); -+ if ((attr1 == NULL) && (attr2 == NULL)) -+ return (ISC_TRUE); -+ else if ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)) -+ return (ISC_FALSE); -+ -+ attr1 = pk11_attribute_bytype(rsa1, CKA_PRIVATE_EXPONENT); -+ attr2 = pk11_attribute_bytype(rsa2, CKA_PRIVATE_EXPONENT); -+ if (((attr1 != NULL) || (attr2 != NULL)) && -+ ((attr1 == NULL) || (attr2 == NULL) || -+ (attr1->ulValueLen != attr2->ulValueLen) || -+ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))) -+ return (ISC_FALSE); -+ -+ if (!rsa1->ontoken && !rsa2->ontoken) -+ return (ISC_TRUE); -+ else if (rsa1->ontoken || rsa2->ontoken || -+ (rsa1->object != rsa2->object)) -+ return (ISC_FALSE); -+ -+ return (ISC_TRUE); -+} -+ -+static isc_result_t -+pkcs11rsa_generate(dst_key_t *key, int exp, void (*callback)(int)) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 }; -+ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; -+ CK_ULONG bits = 0; -+ CK_BYTE pubexp[5]; -+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE keyType = CKK_RSA; -+ CK_ATTRIBUTE pubTemplate[] = -+ { -+ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_MODULUS_BITS, &bits, (CK_ULONG) sizeof(bits) }, -+ { CKA_PUBLIC_EXPONENT, &pubexp, (CK_ULONG) sizeof(pubexp) } -+ }; -+ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; -+ CK_ATTRIBUTE privTemplate[] = -+ { -+ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ }; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *rsa; -+ pk11_context_t *pk11_ctx; -+ isc_result_t ret; -+ unsigned int i; -+ -+ UNUSED(callback); -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ return (ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, pk11_get_best_token(OP_RSA)); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ bits = key->key_size; -+ if (exp == 0) { -+ /* RSA_F4 0x10001 */ -+ pubexp[0] = 1; -+ pubexp[1] = 0; -+ pubexp[2] = 1; -+ pubTemplate[6].ulValueLen = 3; -+ } else { -+ /* F5 0x100000001 */ -+ pubexp[0] = 1; -+ pubexp[1] = 0; -+ pubexp[2] = 0; -+ pubexp[3] = 0; -+ pubexp[4] = 1; -+ pubTemplate[6].ulValueLen = 5; -+ } -+ -+ PK11_RET(pkcs_C_GenerateKeyPair, -+ (pk11_ctx->session, &mech, -+ pubTemplate, (CK_ULONG) 7, -+ privTemplate, (CK_ULONG) 7, -+ &pub, &priv), -+ DST_R_CRYPTOFAILURE); -+ -+ rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa)); -+ if (rsa == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(rsa, 0, sizeof(*rsa)); -+ key->keydata.pkey = rsa; -+ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8); -+ if (rsa->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(rsa->repr, 0, sizeof(*attr) * 8); -+ rsa->attrcnt = 8; -+ -+ attr = rsa->repr; -+ attr[0].type = CKA_MODULUS; -+ attr[1].type = CKA_PUBLIC_EXPONENT; -+ attr[2].type = CKA_PRIVATE_EXPONENT; -+ attr[3].type = CKA_PRIME_1; -+ attr[4].type = CKA_PRIME_2; -+ attr[5].type = CKA_EXPONENT_1; -+ attr[6].type = CKA_EXPONENT_2; -+ attr[7].type = CKA_COEFFICIENT; -+ -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 2), -+ DST_R_CRYPTOFAILURE); -+ for (i = 0; i <= 1; i++) { -+ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen); -+ if (attr[i].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr[i].pValue, 0, attr[i].ulValueLen); -+ } -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, pub, attr, 2), -+ DST_R_CRYPTOFAILURE); -+ -+ attr += 2; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 6), -+ DST_R_CRYPTOFAILURE); -+ for (i = 0; i <= 5; i++) { -+ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen); -+ if (attr[i].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr[i].pValue, 0, attr[i].ulValueLen); -+ } -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, priv, attr, 6), -+ DST_R_CRYPTOFAILURE); -+ -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11rsa_destroy(key); -+ if (priv != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); -+ if (pub != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ret); -+} -+ -+static isc_boolean_t -+pkcs11rsa_isprivate(const dst_key_t *key) { -+ pk11_object_t *rsa = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (rsa == NULL) -+ return (ISC_FALSE); -+ attr = pk11_attribute_bytype(rsa, CKA_PRIVATE_EXPONENT); -+ return (ISC_TF((attr != NULL) || rsa->ontoken)); -+} -+ -+static void -+pkcs11rsa_destroy(dst_key_t *key) { -+ pk11_object_t *rsa = key->keydata.pkey; -+ CK_ATTRIBUTE *attr; -+ -+ if (rsa == NULL) -+ return; -+ -+ INSIST((rsa->object == CK_INVALID_HANDLE) || rsa->ontoken); -+ -+ for (attr = pk11_attribute_first(rsa); -+ attr != NULL; -+ attr = pk11_attribute_next(rsa, attr)) -+ switch (attr->type) { -+ case CKA_LABEL: -+ case CKA_ID: -+ case CKA_MODULUS: -+ case CKA_PUBLIC_EXPONENT: -+ case CKA_PRIVATE_EXPONENT: -+ case CKA_PRIME_1: -+ case CKA_PRIME_2: -+ case CKA_EXPONENT_1: -+ case CKA_EXPONENT_2: -+ case CKA_COEFFICIENT: -+ if (attr->pValue != NULL) { -+ memset(attr->pValue, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, -+ attr->pValue, -+ attr->ulValueLen); -+ } -+ break; -+ } -+ if (rsa->repr != NULL) { -+ memset(rsa->repr, 0, rsa->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, -+ rsa->repr, -+ rsa->attrcnt * sizeof(*attr)); -+ } -+ memset(rsa, 0, sizeof(*rsa)); -+ isc_mem_put(key->mctx, rsa, sizeof(*rsa)); -+ key->keydata.pkey = NULL; -+} -+ -+static isc_result_t -+pkcs11rsa_todns(const dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *rsa; -+ CK_ATTRIBUTE *attr; -+ isc_region_t r; -+ unsigned int e_bytes = 0, mod_bytes = 0; -+ CK_BYTE *exponent = NULL, *modulus = NULL; -+ -+ REQUIRE(key->keydata.pkey != NULL); -+ -+ rsa = key->keydata.pkey; -+ -+ for (attr = pk11_attribute_first(rsa); -+ attr != NULL; -+ attr = pk11_attribute_next(rsa, attr)) -+ switch (attr->type) { -+ case CKA_PUBLIC_EXPONENT: -+ exponent = (CK_BYTE *) attr->pValue; -+ e_bytes = (unsigned int) attr->ulValueLen; -+ break; -+ case CKA_MODULUS: -+ modulus = (CK_BYTE *) attr->pValue; -+ mod_bytes = (unsigned int) attr->ulValueLen; -+ break; -+ } -+ REQUIRE((exponent != NULL) && (modulus != NULL)); -+ -+ isc_buffer_availableregion(data, &r); -+ -+ if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */ -+ if (r.length < 1) -+ return (ISC_R_NOSPACE); -+ isc_buffer_putuint8(data, (isc_uint8_t) e_bytes); -+ isc_region_consume(&r, 1); -+ } else { -+ if (r.length < 3) -+ return (ISC_R_NOSPACE); -+ isc_buffer_putuint8(data, 0); -+ isc_buffer_putuint16(data, (isc_uint16_t) e_bytes); -+ isc_region_consume(&r, 3); -+ } -+ -+ if (r.length < e_bytes + mod_bytes) -+ return (ISC_R_NOSPACE); -+ -+ memcpy(r.base, exponent, e_bytes); -+ isc_region_consume(&r, e_bytes); -+ memcpy(r.base, modulus, mod_bytes); -+ -+ isc_buffer_add(data, e_bytes + mod_bytes); -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) { -+ pk11_object_t *rsa; -+ isc_region_t r; -+ unsigned int e_bytes, mod_bytes; -+ CK_BYTE *exponent = NULL, *modulus = NULL; -+ CK_ATTRIBUTE *attr; -+ -+ isc_buffer_remainingregion(data, &r); -+ if (r.length == 0) -+ return (ISC_R_SUCCESS); -+ -+ rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa)); -+ if (rsa == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(rsa, 0, sizeof(*rsa)); -+ -+ if (r.length < 1) { -+ memset(rsa, 0, sizeof(*rsa)); -+ isc_mem_put(key->mctx, rsa, sizeof(*rsa)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ e_bytes = *r.base++; -+ r.length--; -+ -+ if (e_bytes == 0) { -+ if (r.length < 2) { -+ memset(rsa, 0, sizeof(*rsa)); -+ isc_mem_put(key->mctx, rsa, sizeof(*rsa)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ e_bytes = ((*r.base++) << 8); -+ e_bytes += *r.base++; -+ r.length -= 2; -+ } -+ -+ if (r.length < e_bytes) { -+ memset(rsa, 0, sizeof(*rsa)); -+ isc_mem_put(key->mctx, rsa, sizeof(*rsa)); -+ return (DST_R_INVALIDPUBLICKEY); -+ } -+ exponent = r.base; -+ r.base += e_bytes; -+ r.length -= e_bytes; -+ modulus = r.base; -+ mod_bytes = r.length; -+ -+ key->key_size = pk11_numbits(modulus, mod_bytes); -+ -+ isc_buffer_forward(data, r.length); -+ -+ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); -+ if (rsa->repr == NULL) -+ goto nomemory; -+ memset(rsa->repr, 0, sizeof(*attr) * 2); -+ rsa->attrcnt = 2; -+ attr = rsa->repr; -+ attr[0].type = CKA_MODULUS; -+ attr[0].pValue = isc_mem_get(key->mctx, mod_bytes); -+ if (attr[0].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[0].pValue, modulus, mod_bytes); -+ attr[0].ulValueLen = (CK_ULONG) mod_bytes; -+ attr[1].type = CKA_PUBLIC_EXPONENT; -+ attr[1].pValue = isc_mem_get(key->mctx, e_bytes); -+ if (attr[1].pValue == NULL) -+ goto nomemory; -+ memcpy(attr[1].pValue, exponent, e_bytes); -+ attr[1].ulValueLen = (CK_ULONG) e_bytes; -+ -+ key->keydata.pkey = rsa; -+ -+ return (ISC_R_SUCCESS); -+ -+ nomemory: -+ for (attr = pk11_attribute_first(rsa); -+ attr != NULL; -+ attr = pk11_attribute_next(rsa, attr)) -+ switch (attr->type) { -+ case CKA_MODULUS: -+ case CKA_PUBLIC_EXPONENT: -+ if (attr->pValue != NULL) { -+ memset(attr->pValue, 0, attr->ulValueLen); -+ isc_mem_put(key->mctx, -+ attr->pValue, -+ attr->ulValueLen); -+ } -+ break; -+ } -+ if (rsa->repr != NULL) { -+ memset(rsa->repr, 0, rsa->attrcnt * sizeof(*attr)); -+ isc_mem_put(key->mctx, -+ rsa->repr, -+ rsa->attrcnt * sizeof(*attr)); -+ } -+ memset(rsa, 0, sizeof(*rsa)); -+ isc_mem_put(key->mctx, rsa, sizeof(*rsa)); -+ return (ISC_R_NOMEMORY); -+} -+ -+static isc_result_t -+pkcs11rsa_tofile(const dst_key_t *key, const char *directory) { -+ int i; -+ pk11_object_t *rsa; -+ CK_ATTRIBUTE *attr; -+ CK_ATTRIBUTE *modulus = NULL, *exponent = NULL; -+ CK_ATTRIBUTE *d = NULL, *p = NULL, *q = NULL; -+ CK_ATTRIBUTE *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; -+ dst_private_t priv; -+ unsigned char *bufs[10]; -+ isc_result_t result; -+ -+ if (key->keydata.pkey == NULL) -+ return (DST_R_NULLKEY); -+ -+ if (key->external) { -+ priv.nelements = 0; -+ return (dst__privstruct_writefile(key, &priv, directory)); -+ } -+ -+ rsa = key->keydata.pkey; -+ -+ for (attr = pk11_attribute_first(rsa); -+ attr != NULL; -+ attr = pk11_attribute_next(rsa, attr)) -+ switch (attr->type) { -+ case CKA_MODULUS: -+ modulus = attr; -+ break; -+ case CKA_PUBLIC_EXPONENT: -+ exponent = attr; -+ break; -+ case CKA_PRIVATE_EXPONENT: -+ d = attr; -+ break; -+ case CKA_PRIME_1: -+ p = attr; -+ break; -+ case CKA_PRIME_2: -+ q = attr; -+ break; -+ case CKA_EXPONENT_1: -+ dmp1 = attr; -+ break; -+ case CKA_EXPONENT_2: -+ dmq1 = attr; -+ break; -+ case CKA_COEFFICIENT: -+ iqmp = attr; -+ break; -+ } -+ if ((modulus == NULL) || (exponent == NULL)) -+ return (DST_R_NULLKEY); -+ -+ memset(bufs, 0, sizeof(bufs)); -+ -+ for (i = 0; i < 10; i++) { -+ bufs[i] = isc_mem_get(key->mctx, modulus->ulValueLen); -+ if (bufs[i] == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto fail; -+ } -+ memset(bufs[i], 0, modulus->ulValueLen); -+ } -+ -+ i = 0; -+ -+ priv.elements[i].tag = TAG_RSA_MODULUS; -+ priv.elements[i].length = (unsigned short) modulus->ulValueLen; -+ memcpy(bufs[i], modulus->pValue, modulus->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ -+ priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT; -+ priv.elements[i].length = (unsigned short) exponent->ulValueLen; -+ memcpy(bufs[i], exponent->pValue, exponent->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ -+ if (d != NULL) { -+ priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT; -+ priv.elements[i].length = (unsigned short) d->ulValueLen; -+ memcpy(bufs[i], d->pValue, d->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ } -+ -+ if (p != NULL) { -+ priv.elements[i].tag = TAG_RSA_PRIME1; -+ priv.elements[i].length = (unsigned short) p->ulValueLen; -+ memcpy(bufs[i], p->pValue, p->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ } -+ -+ if (q != NULL) { -+ priv.elements[i].tag = TAG_RSA_PRIME2; -+ priv.elements[i].length = (unsigned short) q->ulValueLen; -+ memcpy(bufs[i], q->pValue, q->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ } -+ -+ if (dmp1 != NULL) { -+ priv.elements[i].tag = TAG_RSA_EXPONENT1; -+ priv.elements[i].length = (unsigned short) dmp1->ulValueLen; -+ memcpy(bufs[i], dmp1->pValue, dmp1->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ } -+ -+ if (dmq1 != NULL) { -+ priv.elements[i].tag = TAG_RSA_EXPONENT2; -+ priv.elements[i].length = (unsigned short) dmq1->ulValueLen; -+ memcpy(bufs[i], dmq1->pValue, dmq1->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ } -+ -+ if (iqmp != NULL) { -+ priv.elements[i].tag = TAG_RSA_COEFFICIENT; -+ priv.elements[i].length = (unsigned short) iqmp->ulValueLen; -+ memcpy(bufs[i], iqmp->pValue, iqmp->ulValueLen); -+ priv.elements[i].data = bufs[i]; -+ i++; -+ } -+ -+ if (key->engine != NULL) { -+ priv.elements[i].tag = TAG_RSA_ENGINE; -+ priv.elements[i].length = strlen(key->engine) + 1; -+ priv.elements[i].data = (unsigned char *)key->engine; -+ i++; -+ } -+ -+ if (key->label != NULL) { -+ priv.elements[i].tag = TAG_RSA_LABEL; -+ priv.elements[i].length = strlen(key->label) + 1; -+ priv.elements[i].data = (unsigned char *)key->label; -+ i++; -+ } -+ -+ priv.nelements = i; -+ result = dst__privstruct_writefile(key, &priv, directory); -+ fail: -+ for (i = 0; i < 10; i++) { -+ if (bufs[i] == NULL) -+ break; -+ memset(bufs[i], 0, modulus->ulValueLen); -+ isc_mem_put(key->mctx, bufs[i], modulus->ulValueLen); -+ } -+ return (result); -+} -+ -+static isc_result_t -+pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label, -+ dst_key_t *pub) -+{ -+ CK_RV rv; -+ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; -+ CK_KEY_TYPE keyType = CKK_RSA; -+ CK_ATTRIBUTE searchTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_LABEL, NULL, 0 } -+ }; -+ CK_ULONG cnt; -+ CK_ATTRIBUTE *attr; -+ CK_ATTRIBUTE *pubattr; -+ pk11_object_t *rsa; -+ pk11_object_t *pubrsa; -+ pk11_context_t *pk11_ctx = NULL; -+ isc_result_t ret; -+ -+ if (label == NULL) -+ return (DST_R_NOENGINE); -+ -+ rsa = key->keydata.pkey; -+ pubrsa = pub->keydata.pkey; -+ -+ rsa->object = CK_INVALID_HANDLE; -+ rsa->ontoken = ISC_TRUE; -+ rsa->reqlogon = ISC_TRUE; -+ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); -+ if (rsa->repr == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(rsa->repr, 0, sizeof(*attr) * 2); -+ rsa->attrcnt = 2; -+ attr = rsa->repr; -+ -+ attr->type = CKA_MODULUS; -+ pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS); -+ attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, pubattr->pValue, pubattr->ulValueLen); -+ attr->ulValueLen = pubattr->ulValueLen; -+ attr++; -+ -+ attr->type = CKA_PUBLIC_EXPONENT; -+ pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT); -+ attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen); -+ if (attr->pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(attr->pValue, pubattr->pValue, pubattr->ulValueLen); -+ attr->ulValueLen = pubattr->ulValueLen; -+ -+ ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, -+ rsa->reqlogon, NULL, rsa->slot); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ attr = pk11_attribute_bytype(rsa, CKA_LABEL); -+ if (attr == NULL) { -+ attr = pk11_attribute_bytype(rsa, CKA_ID); -+ INSIST(attr != NULL); -+ searchTemplate[3].type = CKA_ID; -+ } -+ searchTemplate[3].pValue = attr->pValue; -+ searchTemplate[3].ulValueLen = attr->ulValueLen; -+ -+ PK11_RET(pkcs_C_FindObjectsInit, -+ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), -+ DST_R_CRYPTOFAILURE); -+ PK11_RET(pkcs_C_FindObjects, -+ (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt), -+ DST_R_CRYPTOFAILURE); -+ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); -+ if (cnt == 0) -+ DST_RET(ISC_R_NOTFOUND); -+ if (cnt > 1) -+ DST_RET(ISC_R_EXISTS); -+ -+ if (engine != NULL) { -+ key->engine = isc_mem_strdup(key->mctx, engine); -+ if (key->engine == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ } -+ -+ key->label = isc_mem_strdup(key->mctx, label); -+ if (key->label == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ attr = pk11_attribute_bytype(rsa, CKA_MODULUS); -+ INSIST(attr != NULL); -+ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ if (pk11_ctx != NULL) { -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ } -+ -+ return (ret); -+} -+ -+static isc_result_t -+rsa_check(pk11_object_t *rsa, pk11_object_t *pubrsa) { -+ CK_ATTRIBUTE *pubattr, *privattr; -+ CK_BYTE *priv_exp = NULL, *priv_mod = NULL; -+ CK_BYTE *pub_exp = NULL, *pub_mod = NULL; -+ unsigned int priv_explen = 0, priv_modlen = 0; -+ unsigned int pub_explen = 0, pub_modlen = 0; -+ -+ REQUIRE(rsa != NULL && pubrsa != NULL); -+ -+ privattr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT); -+ INSIST(privattr != NULL); -+ priv_exp = privattr->pValue; -+ priv_explen = privattr->ulValueLen; -+ -+ pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT); -+ INSIST(pubattr != NULL); -+ pub_exp = pubattr->pValue; -+ pub_explen = pubattr->ulValueLen; -+ -+ if (priv_exp != NULL) { -+ if (priv_explen != pub_explen) -+ return (DST_R_INVALIDPRIVATEKEY); -+ if (memcmp(priv_exp, pub_exp, pub_explen) != 0) -+ return (DST_R_INVALIDPRIVATEKEY); -+ } else { -+ privattr->pValue = pub_exp; -+ privattr->ulValueLen = pub_explen; -+ pubattr->pValue = NULL; -+ pubattr->ulValueLen = 0; -+ } -+ -+ if (privattr->pValue == NULL) -+ return (DST_R_INVALIDPRIVATEKEY); -+ -+ privattr = pk11_attribute_bytype(rsa, CKA_MODULUS); -+ INSIST(privattr != NULL); -+ priv_mod = privattr->pValue; -+ priv_modlen = privattr->ulValueLen; -+ -+ pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS); -+ INSIST(pubattr != NULL); -+ pub_mod = pubattr->pValue; -+ pub_modlen = pubattr->ulValueLen; -+ -+ if (priv_mod != NULL) { -+ if (priv_modlen != pub_modlen) -+ return (DST_R_INVALIDPRIVATEKEY); -+ if (memcmp(priv_mod, pub_mod, pub_modlen) != 0) -+ return (DST_R_INVALIDPRIVATEKEY); -+ } else { -+ privattr->pValue = pub_mod; -+ privattr->ulValueLen = pub_modlen; -+ pubattr->pValue = NULL; -+ pubattr->ulValueLen = 0; -+ } -+ -+ if (privattr->pValue == NULL) -+ return (DST_R_INVALIDPRIVATEKEY); -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { -+ dst_private_t priv; -+ isc_result_t ret; -+ int i; -+ pk11_object_t *rsa; -+ CK_ATTRIBUTE *attr; -+ isc_mem_t *mctx = key->mctx; -+ const char *engine = NULL, *label = NULL; -+ -+ /* read private key file */ -+ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); -+ if (ret != ISC_R_SUCCESS) -+ return (ret); -+ -+ if (key->external) { -+ if (priv.nelements != 0) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ if (pub == NULL) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ -+ key->keydata.pkey = pub->keydata.pkey; -+ pub->keydata.pkey = NULL; -+ key->key_size = pub->key_size; -+ -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ -+ return (ISC_R_SUCCESS); -+ } -+ -+ for (i = 0; i < priv.nelements; i++) { -+ switch (priv.elements[i].tag) { -+ case TAG_RSA_ENGINE: -+ engine = (char *)priv.elements[i].data; -+ break; -+ case TAG_RSA_LABEL: -+ label = (char *)priv.elements[i].data; -+ break; -+ default: -+ break; -+ } -+ } -+ rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa)); -+ if (rsa == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(rsa, 0, sizeof(*rsa)); -+ key->keydata.pkey = rsa; -+ -+ /* Is this key is stored in a HSM? See if we can fetch it. */ -+ if ((label != NULL) || (engine != NULL)) { -+ ret = pkcs11rsa_fetch(key, engine, label, pub); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ret); -+ } -+ -+ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8); -+ if (rsa->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(rsa->repr, 0, sizeof(*attr) * 8); -+ rsa->attrcnt = 8; -+ attr = rsa->repr; -+ attr[0].type = CKA_MODULUS; -+ attr[1].type = CKA_PUBLIC_EXPONENT; -+ attr[2].type = CKA_PRIVATE_EXPONENT; -+ attr[3].type = CKA_PRIME_1; -+ attr[4].type = CKA_PRIME_2; -+ attr[5].type = CKA_EXPONENT_1; -+ attr[6].type = CKA_EXPONENT_2; -+ attr[7].type = CKA_COEFFICIENT; -+ -+ for (i = 0; i < priv.nelements; i++) { -+ CK_BYTE *bn; -+ -+ switch (priv.elements[i].tag) { -+ case TAG_RSA_ENGINE: -+ continue; -+ case TAG_RSA_LABEL: -+ continue; -+ default: -+ bn = isc_mem_get(key->mctx, priv.elements[i].length); -+ if (bn == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memcpy(bn, -+ priv.elements[i].data, -+ priv.elements[i].length); -+ } -+ -+ switch (priv.elements[i].tag) { -+ case TAG_RSA_MODULUS: -+ attr = pk11_attribute_bytype(rsa, CKA_MODULUS); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_RSA_PUBLICEXPONENT: -+ attr = pk11_attribute_bytype(rsa, -+ CKA_PUBLIC_EXPONENT); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_RSA_PRIVATEEXPONENT: -+ attr = pk11_attribute_bytype(rsa, -+ CKA_PRIVATE_EXPONENT); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_RSA_PRIME1: -+ attr = pk11_attribute_bytype(rsa, CKA_PRIME_1); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_RSA_PRIME2: -+ attr = pk11_attribute_bytype(rsa, CKA_PRIME_2); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_RSA_EXPONENT1: -+ attr = pk11_attribute_bytype(rsa, -+ CKA_EXPONENT_1); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_RSA_EXPONENT2: -+ attr = pk11_attribute_bytype(rsa, -+ CKA_EXPONENT_2); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ case TAG_RSA_COEFFICIENT: -+ attr = pk11_attribute_bytype(rsa, -+ CKA_COEFFICIENT); -+ INSIST(attr != NULL); -+ attr->pValue = bn; -+ attr->ulValueLen = priv.elements[i].length; -+ break; -+ } -+ } -+ -+ if (rsa_check(rsa, pub->keydata.pkey) != ISC_R_SUCCESS) -+ DST_RET(DST_R_INVALIDPRIVATEKEY); -+ -+ attr = pk11_attribute_bytype(rsa, CKA_MODULUS); -+ INSIST(attr != NULL); -+ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ -+ attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT); -+ INSIST(attr != NULL); -+ if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS) -+ DST_RET(ISC_R_RANGE); -+ -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11rsa_destroy(key); -+ dst__privstruct_free(&priv, mctx); -+ memset(&priv, 0, sizeof(priv)); -+ return (ret); -+} -+ -+static isc_result_t -+pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label, -+ const char *pin) -+{ -+ CK_RV rv; -+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; -+ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; -+ CK_KEY_TYPE keyType = CKK_RSA; -+ CK_ATTRIBUTE searchTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_LABEL, NULL, 0 } -+ }; -+ CK_ULONG cnt; -+ CK_ATTRIBUTE *attr; -+ pk11_object_t *rsa; -+ pk11_context_t *pk11_ctx = NULL; -+ isc_result_t ret; -+ unsigned int i; -+ -+ UNUSED(pin); -+ -+ rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa)); -+ if (rsa == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(rsa, 0, sizeof(*rsa)); -+ rsa->object = CK_INVALID_HANDLE; -+ rsa->ontoken = ISC_TRUE; -+ rsa->reqlogon = ISC_TRUE; -+ key->keydata.pkey = rsa; -+ -+ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); -+ if (rsa->repr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(rsa->repr, 0, sizeof(*attr) * 2); -+ rsa->attrcnt = 2; -+ attr = rsa->repr; -+ attr[0].type = CKA_MODULUS; -+ attr[1].type = CKA_PUBLIC_EXPONENT; -+ -+ ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, -+ sizeof(*pk11_ctx)); -+ if (pk11_ctx == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, -+ rsa->reqlogon, NULL, rsa->slot); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ -+ attr = pk11_attribute_bytype(rsa, CKA_LABEL); -+ if (attr == NULL) { -+ attr = pk11_attribute_bytype(rsa, CKA_ID); -+ INSIST(attr != NULL); -+ searchTemplate[3].type = CKA_ID; -+ } -+ searchTemplate[3].pValue = attr->pValue; -+ searchTemplate[3].ulValueLen = attr->ulValueLen; -+ -+ PK11_RET(pkcs_C_FindObjectsInit, -+ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), -+ DST_R_CRYPTOFAILURE); -+ PK11_RET(pkcs_C_FindObjects, -+ (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt), -+ DST_R_CRYPTOFAILURE); -+ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); -+ if (cnt == 0) -+ DST_RET(ISC_R_NOTFOUND); -+ if (cnt > 1) -+ DST_RET(ISC_R_EXISTS); -+ -+ attr = rsa->repr; -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, hKey, attr, 2), -+ DST_R_CRYPTOFAILURE); -+ for (i = 0; i <= 1; i++) { -+ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen); -+ if (attr[i].pValue == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ memset(attr[i].pValue, 0, attr[i].ulValueLen); -+ } -+ PK11_RET(pkcs_C_GetAttributeValue, -+ (pk11_ctx->session, hKey, attr, 2), -+ DST_R_CRYPTOFAILURE); -+ -+ keyClass = CKO_PRIVATE_KEY; -+ PK11_RET(pkcs_C_FindObjectsInit, -+ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), -+ DST_R_CRYPTOFAILURE); -+ PK11_RET(pkcs_C_FindObjects, -+ (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt), -+ DST_R_CRYPTOFAILURE); -+ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); -+ if (cnt == 0) -+ DST_RET(ISC_R_NOTFOUND); -+ if (cnt > 1) -+ DST_RET(ISC_R_EXISTS); -+ -+ if (engine != NULL) { -+ key->engine = isc_mem_strdup(key->mctx, engine); -+ if (key->engine == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ } -+ -+ key->label = isc_mem_strdup(key->mctx, label); -+ if (key->label == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ -+ attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT); -+ INSIST(attr != NULL); -+ if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS) -+ DST_RET(ISC_R_RANGE); -+ -+ attr = pk11_attribute_bytype(rsa, CKA_MODULUS); -+ INSIST(attr != NULL); -+ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); -+ -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ -+ return (ISC_R_SUCCESS); -+ -+ err: -+ pkcs11rsa_destroy(key); -+ if (pk11_ctx != NULL) { -+ pk11_return_session(pk11_ctx); -+ memset(pk11_ctx, 0, sizeof(*pk11_ctx)); -+ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); -+ } -+ -+ return (ret); -+} -+ -+static dst_func_t pkcs11rsa_functions = { -+ pkcs11rsa_createctx, -+ pkcs11rsa_createctx2, -+ pkcs11rsa_destroyctx, -+ pkcs11rsa_adddata, -+ pkcs11rsa_sign, -+ pkcs11rsa_verify, -+ NULL, /*%< verify2 */ -+ NULL, /*%< computesecret */ -+ pkcs11rsa_compare, -+ NULL, /*%< paramcompare */ -+ pkcs11rsa_generate, -+ pkcs11rsa_isprivate, -+ pkcs11rsa_destroy, -+ pkcs11rsa_todns, -+ pkcs11rsa_fromdns, -+ pkcs11rsa_tofile, -+ pkcs11rsa_parse, -+ NULL, /*%< cleanup */ -+ pkcs11rsa_fromlabel, -+ NULL, /*%< dump */ -+ NULL, /*%< restore */ -+}; -+ -+isc_result_t -+dst__pkcs11rsa_init(dst_func_t **funcp) { -+ REQUIRE(funcp != NULL); -+ -+ if (*funcp == NULL) -+ *funcp = &pkcs11rsa_functions; -+ return (ISC_R_SUCCESS); -+} -+ -+#else /* PKCS11CRYPTO */ -+ -+#include -+ -+EMPTY_TRANSLATION_UNIT -+ -+#endif /* PKCS11CRYPTO */ -+/*! \file */ -diff --git a/lib/dns/rdata/generic/dlv_32769.c b/lib/dns/rdata/generic/dlv_32769.c -index 5751ad8..732abdb 100644 ---- a/lib/dns/rdata/generic/dlv_32769.c -+++ b/lib/dns/rdata/generic/dlv_32769.c -@@ -28,6 +28,7 @@ - - #include - -+#include "dst_gost.h" - - static inline isc_result_t - fromtext_dlv(ARGS_FROMTEXT) { -@@ -81,9 +82,11 @@ fromtext_dlv(ARGS_FROMTEXT) { - case DNS_DSDIGEST_SHA256: - length = ISC_SHA256_DIGESTLENGTH; - break; -+#ifdef ISC_GOST_DIGESTLENGTH - case DNS_DSDIGEST_GOST: - length = ISC_GOST_DIGESTLENGTH; - break; -+#endif - case DNS_DSDIGEST_SHA384: - length = ISC_SHA384_DIGESTLENGTH; - break; -@@ -168,8 +171,10 @@ fromwire_dlv(ARGS_FROMWIRE) { - sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || - (sr.base[3] == DNS_DSDIGEST_SHA256 && - sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || -+#ifdef ISC_GOST_DIGESTLENGTH - (sr.base[3] == DNS_DSDIGEST_GOST && - sr.length < 4 + ISC_GOST_DIGESTLENGTH) || -+#endif - (sr.base[3] == DNS_DSDIGEST_SHA384 && - sr.length < 4 + ISC_SHA384_DIGESTLENGTH)) - return (ISC_R_UNEXPECTEDEND); -@@ -183,8 +188,10 @@ fromwire_dlv(ARGS_FROMWIRE) { - sr.length = 4 + ISC_SHA1_DIGESTLENGTH; - else if (sr.base[3] == DNS_DSDIGEST_SHA256) - sr.length = 4 + ISC_SHA256_DIGESTLENGTH; -+#ifdef ISC_GOST_DIGESTLENGTH - else if (sr.base[3] == DNS_DSDIGEST_GOST) - sr.length = 4 + ISC_GOST_DIGESTLENGTH; -+#endif - else if (sr.base[3] == DNS_DSDIGEST_SHA384) - sr.length = 4 + ISC_SHA384_DIGESTLENGTH; - -@@ -236,9 +243,11 @@ fromstruct_dlv(ARGS_FROMSTRUCT) { - case DNS_DSDIGEST_SHA256: - REQUIRE(dlv->length == ISC_SHA256_DIGESTLENGTH); - break; -+#ifdef ISC_GOST_DIGESTLENGTH - case DNS_DSDIGEST_GOST: - REQUIRE(dlv->length == ISC_GOST_DIGESTLENGTH); - break; -+#endif - case DNS_DSDIGEST_SHA384: - REQUIRE(dlv->length == ISC_SHA384_DIGESTLENGTH); - break; -diff --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c -index dd47c8d..fc7f126 100644 ---- a/lib/dns/rdata/generic/ds_43.c -+++ b/lib/dns/rdata/generic/ds_43.c -@@ -30,6 +30,8 @@ - - #include - -+#include "dst_gost.h" -+ - static inline isc_result_t - fromtext_ds(ARGS_FROMTEXT) { - isc_token_t token; -@@ -81,9 +83,11 @@ fromtext_ds(ARGS_FROMTEXT) { - case DNS_DSDIGEST_SHA256: - length = ISC_SHA256_DIGESTLENGTH; - break; -+#ifdef ISC_GOST_DIGESTLENGTH - case DNS_DSDIGEST_GOST: - length = ISC_GOST_DIGESTLENGTH; - break; -+#endif - case DNS_DSDIGEST_SHA384: - length = ISC_SHA384_DIGESTLENGTH; - break; -@@ -168,8 +172,10 @@ fromwire_ds(ARGS_FROMWIRE) { - sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || - (sr.base[3] == DNS_DSDIGEST_SHA256 && - sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || -+#ifdef ISC_GOST_DIGESTLENGTH - (sr.base[3] == DNS_DSDIGEST_GOST && - sr.length < 4 + ISC_GOST_DIGESTLENGTH) || -+#endif - (sr.base[3] == DNS_DSDIGEST_SHA384 && - sr.length < 4 + ISC_SHA384_DIGESTLENGTH)) - return (ISC_R_UNEXPECTEDEND); -@@ -183,8 +189,10 @@ fromwire_ds(ARGS_FROMWIRE) { - sr.length = 4 + ISC_SHA1_DIGESTLENGTH; - else if (sr.base[3] == DNS_DSDIGEST_SHA256) - sr.length = 4 + ISC_SHA256_DIGESTLENGTH; -+#ifdef ISC_GOST_DIGESTLENGTH - else if (sr.base[3] == DNS_DSDIGEST_GOST) - sr.length = 4 + ISC_GOST_DIGESTLENGTH; -+#endif - else if (sr.base[3] == DNS_DSDIGEST_SHA384) - sr.length = 4 + ISC_SHA384_DIGESTLENGTH; - -@@ -236,9 +244,11 @@ fromstruct_ds(ARGS_FROMSTRUCT) { - case DNS_DSDIGEST_SHA256: - REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH); - break; -+#ifdef ISC_GOST_DIGESTLENGTH - case DNS_DSDIGEST_GOST: - REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH); - break; -+#endif - case DNS_DSDIGEST_SHA384: - REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH); - break; -diff --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in -index db47476..3b19784 100644 ---- a/lib/dns/tests/Makefile.in -+++ b/lib/dns/tests/Makefile.in -@@ -26,8 +26,9 @@ top_srcdir = @top_srcdir@ - - @BIND9_MAKE_INCLUDES@ - --CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@ --CDEFINES = @USE_OPENSSL@ -DTESTS="\"${top_builddir}/lib/dns/tests/\"" -+CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} \ -+ @DST_OPENSSL_INC@ -+CDEFINES = @CRYPTO@ -DTESTS="\"${top_builddir}/lib/dns/tests/\"" - - ISCLIBS = ../../isc/libisc.@A@ - ISCDEPLIBS = ../../isc/libisc.@A@ -@@ -37,13 +38,13 @@ DNSDEPLIBS = ../libdns.@A@ - LIBS = @LIBS@ @ATFLIBS@ - - OBJS = dnstest.@O@ --SRCS = dnstest.c master_test.c dbiterator_test.c time_test.c \ -+SRCS = dnstest.c gost_test.c master_test.c dbiterator_test.c time_test.c \ - private_test.c update_test.c zonemgr_test.c zt_test.c \ - dbdiff_test.c dispatch_test.c nsec3_test.c \ - rdataset_test.c rdata_test.c - - SUBDIRS = --TARGETS = master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \ -+TARGETS = gost_test@EXEEXT@ master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \ - private_test@EXEEXT@ update_test@EXEEXT@ zonemgr_test@EXEEXT@ \ - zt_test@EXEEXT@ dbversion_test@EXEEXT@ dbdiff_test@EXEEXT@ \ - dispatch_test@EXEEXT@ nsec3_test@EXEEXT@ \ -@@ -123,6 +124,11 @@ dispatch_test@EXEEXT@: dispatch_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - dispatch_test.@O@ dnstest.@O@ ${DNSLIBS} \ - ${ISCLIBS} ${LIBS} - -+gost_test@EXEEXT@: gost_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ -+ gost_test.@O@ dnstest.@O@ ${DNSLIBS} \ -+ ${ISCLIBS} ${LIBS} -+ - unit:: - sh ${top_srcdir}/unit/unittest.sh - -diff --git a/lib/dns/tests/gost_test.c b/lib/dns/tests/gost_test.c -new file mode 100644 -index 0000000..0dd9e55 ---- /dev/null -+++ b/lib/dns/tests/gost_test.c -@@ -0,0 +1,232 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+/* ! \file */ -+ -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+#include "dnstest.h" -+ -+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) -+ -+#include "../dst_gost.h" -+ -+/* -+ * Test data from Wikipedia GOST (hash function) -+ */ -+ -+unsigned char digest[ISC_GOST_DIGESTLENGTH]; -+unsigned char buffer[1024]; -+const char *s; -+char str[ISC_GOST_DIGESTLENGTH]; -+int i = 0; -+ -+isc_result_t -+tohexstr(unsigned char *d, unsigned int len, char *out); -+/* -+ * Precondition: a hexadecimal number in *d, the length of that number in len, -+ * and a pointer to a character array to put the output (*out). -+ * Postcondition: A String representation of the given hexadecimal number is -+ * placed into the array *out -+ * -+ * 'out' MUST point to an array of at least len / 2 + 1 -+ * -+ * Return values: ISC_R_SUCCESS if the operation is sucessful -+ */ -+ -+isc_result_t -+tohexstr(unsigned char *d, unsigned int len, char *out) { -+ -+ out[0]='\0'; -+ char c_ret[] = "AA"; -+ unsigned int i; -+ strcat(out, "0x"); -+ for (i = 0; i < len; i++) { -+ sprintf(c_ret, "%02X", d[i]); -+ strcat(out, c_ret); -+ } -+ strcat(out, "\0"); -+ return (ISC_R_SUCCESS); -+} -+ -+ -+#define TEST_INPUT(x) (x), sizeof(x)-1 -+ -+typedef struct hash_testcase { -+ const char *input; -+ size_t input_len; -+ const char *result; -+ int repeats; -+} hash_testcase_t; -+ -+ATF_TC(isc_gost); -+ATF_TC_HEAD(isc_gost, tc) { -+ atf_tc_set_md_var(tc, "descr", -+ "GOST R 34.11-94 examples from Wikipedia"); -+} -+ATF_TC_BODY(isc_gost, tc) { -+ isc_gost_t gost; -+ isc_result_t result; -+ -+ UNUSED(tc); -+ -+ /* -+ * These are the various test vectors. All of these are passed -+ * through the hash function and the results are compared to the -+ * result specified here. -+ */ -+ hash_testcase_t testcases[] = { -+ /* Test 1 */ -+ { -+ TEST_INPUT(""), -+ "0x981E5F3CA30C841487830F84FB433E1" -+ "3AC1101569B9C13584AC483234CD656C0", -+ 1 -+ }, -+ /* Test 2 */ -+ { -+ TEST_INPUT("a"), -+ "0xE74C52DD282183BF37AF0079C9F7805" -+ "5715A103F17E3133CEFF1AACF2F403011", -+ 1 -+ }, -+ /* Test 3 */ -+ { -+ TEST_INPUT("abc"), -+ "0xB285056DBF18D7392D7677369524DD1" -+ "4747459ED8143997E163B2986F92FD42C", -+ 1 -+ }, -+ /* Test 4 */ -+ { -+ TEST_INPUT("message digest"), -+ "0xBC6041DD2AA401EBFA6E9886734174F" -+ "EBDB4729AA972D60F549AC39B29721BA0", -+ 1 -+ }, -+ /* Test 5 */ -+ { -+ TEST_INPUT("The quick brown fox jumps " -+ "over the lazy dog"), -+ "0x9004294A361A508C586FE53D1F1B027" -+ "46765E71B765472786E4770D565830A76", -+ 1 -+ }, -+ /* Test 6 */ -+ { -+ TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" -+ "fghijklmnopqrstuvwxyz0123456789"), -+ "0x73B70A39497DE53A6E08C67B6D4DB85" -+ "3540F03E9389299D9B0156EF7E85D0F61", -+ 1 -+ }, -+ /* Test 7 */ -+ { -+ TEST_INPUT("1234567890123456789012345678901" -+ "2345678901234567890123456789012" -+ "345678901234567890"), -+ "0x6BC7B38989B28CF93AE8842BF9D7529" -+ "05910A7528A61E5BCE0782DE43E610C90", -+ 1 -+ }, -+ /* Test 8 */ -+ { -+ TEST_INPUT("This is message, length=32 bytes"), -+ "0x2CEFC2F7B7BDC514E18EA57FA74FF35" -+ "7E7FA17D652C75F69CB1BE7893EDE48EB", -+ 1 -+ }, -+ /* Test 9 */ -+ { -+ TEST_INPUT("Suppose the original message " -+ "has length = 50 bytes"), -+ "0xC3730C5CBCCACF915AC292676F21E8B" -+ "D4EF75331D9405E5F1A61DC3130A65011", -+ 1 -+ }, -+ /* Test 10 */ -+ { -+ TEST_INPUT("U") /* times 128 */, -+ "0x1C4AC7614691BBF427FA2316216BE8F" -+ "10D92EDFD37CD1027514C1008F649C4E8", -+ 128 -+ }, -+ /* Test 11 */ -+ { -+ TEST_INPUT("a") /* times 1000000 */, -+ "0x8693287AA62F9478F7CB312EC0866B6" -+ "C4E4A0F11160441E8F4FFCD2715DD554F", -+ 1000000 -+ }, -+ { NULL, 0, NULL, 1 } -+ }; -+ -+ result = dns_test_begin(NULL, ISC_FALSE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ hash_testcase_t *testcase = testcases; -+ -+ while (testcase->input != NULL && testcase->result != NULL) { -+ result = isc_gost_init(&gost); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ for(i = 0; i < testcase->repeats; i++) { -+ result = isc_gost_update(&gost, -+ (const isc_uint8_t *) testcase->input, -+ testcase->input_len); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ } -+ result = isc_gost_final(&gost, digest); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ tohexstr(digest, ISC_GOST_DIGESTLENGTH, str); -+ ATF_CHECK_STREQ(str, testcase->result); -+ -+ testcase++; -+ } -+ -+ dns_test_end(); -+} -+#else -+ATF_TC(untested); -+ATF_TC_HEAD(untested, tc) { -+ atf_tc_set_md_var(tc, "descr", "skipping gost test"); -+} -+ATF_TC_BODY(untested, tc) { -+ UNUSED(tc); -+ atf_tc_skip("GOST hash not available"); -+} -+#endif -+/* -+ * Main -+ */ -+ATF_TP_ADD_TCS(tp) { -+#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) -+ ATF_TP_ADD_TC(tp, isc_gost); -+#else -+ ATF_TP_ADD_TC(tp, untested); -+#endif -+ return (atf_no_error()); -+} -+ -diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c -index 161c188..20c98e5 100644 ---- a/lib/dns/tkey.c -+++ b/lib/dns/tkey.c -@@ -45,8 +45,14 @@ - #include - #include - -+#include "dst_internal.h" -+ - #define TKEY_RANDOM_AMOUNT 16 - -+#ifdef PKCS11CRYPTO -+#include -+#endif -+ - #define RETERR(x) do { \ - result = (x); \ - if (result != ISC_R_SUCCESS) \ -@@ -382,8 +388,8 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, - if (randomdata == NULL) - goto failure; - -- result = isc_entropy_getdata(tctx->ectx, randomdata, -- TKEY_RANDOM_AMOUNT, NULL, 0); -+ result = dst__entropy_getdata(randomdata, TKEY_RANDOM_AMOUNT, -+ ISC_FALSE); - if (result != ISC_R_SUCCESS) { - tkey_log("process_dhtkey: failed to obtain entropy: %s", - isc_result_totext(result)); -diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c -index c7768f4..3239bff 100644 ---- a/lib/dns/tsig.c -+++ b/lib/dns/tsig.c -@@ -946,8 +946,9 @@ dns_tsig_sign(dns_message_t *msg) { - isc_buffer_t headerbuf; - isc_uint16_t digestbits; - -- ret = dst_context_create2(key->key, mctx, -- DNS_LOGCATEGORY_DNSSEC, &ctx); -+ ret = dst_context_create3(key->key, mctx, -+ DNS_LOGCATEGORY_DNSSEC, -+ ISC_TRUE, &ctx); - if (ret != ISC_R_SUCCESS) - return (ret); - -@@ -1345,8 +1346,9 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - sig_r.base = tsig.signature; - sig_r.length = tsig.siglen; - -- ret = dst_context_create2(key, mctx, -- DNS_LOGCATEGORY_DNSSEC, &ctx); -+ ret = dst_context_create3(key, mctx, -+ DNS_LOGCATEGORY_DNSSEC, -+ ISC_FALSE, &ctx); - if (ret != ISC_R_SUCCESS) - return (ret); - -@@ -1577,9 +1579,9 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - key = tsigkey->key; - - if (msg->tsigctx == NULL) { -- ret = dst_context_create2(key, mctx, -+ ret = dst_context_create3(key, mctx, - DNS_LOGCATEGORY_DNSSEC, -- &msg->tsigctx); -+ ISC_FALSE, &msg->tsigctx); - if (ret != ISC_R_SUCCESS) - goto cleanup_querystruct; - -diff --git a/lib/export/dns/Makefile.in b/lib/export/dns/Makefile.in -index 1e4540f..e10bf59 100644 ---- a/lib/export/dns/Makefile.in -+++ b/lib/export/dns/Makefile.in -@@ -28,10 +28,10 @@ export_srcdir = @top_srcdir@/lib/export - - @BIND9_MAKE_INCLUDES@ - --CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} -I${export_srcdir}/isc/include \ -+CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} -I${export_srcdir}/isc/include \ - ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@ - --CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@ -+CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@ - - CWARNINGS = - -diff --git a/lib/export/isc/Makefile.in b/lib/export/isc/Makefile.in -index 62e5acd..a5f8bd0 100644 ---- a/lib/export/isc/Makefile.in -+++ b/lib/export/isc/Makefile.in -@@ -27,7 +27,7 @@ CINCLUDES = -I${srcdir}/unix/include \ - -I${srcdir}/@ISC_ARCH_DIR@/include \ - -I${export_srcdir}/isc/include -I${srcdir}/include \ - @ISC_OPENSSL_INC@ --CDEFINES = @USE_OPENSSL@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \ -+CDEFINES = @CRYPTO@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \ - -DUSE_SOCKETIMPREGISTER -DUSE_TASKIMPREGISTER \ - -DUSE_TIMERIMPREGISTER - CWARNINGS = -@@ -48,7 +48,8 @@ UNIXOBJS = @ISC_ISCIPV6_O@ \ - unix/file.@O@ \ - unix/fsaccess.@O@ \ - unix/stdio.@O@ \ -- unix/stdtime.@O@ unix/strerror.@O@ unix/time.@O@ -+ unix/stdtime.@O@ unix/strerror.@O@ unix/time.@O@ unix/entropy.@O@ \ -+ unix/keyboard.@O@ - - NLSOBJS = nls/msgcat.@O@ - -diff --git a/lib/export/isc/unix/Makefile.in b/lib/export/isc/unix/Makefile.in -index 1873202..a904615 100644 ---- a/lib/export/isc/unix/Makefile.in -+++ b/lib/export/isc/unix/Makefile.in -@@ -40,6 +40,8 @@ OBJS = @ISC_IPV6_O@ \ - file.@O@ fsaccess.@O@ \ - stdio.@O@ stdtime.@O@ strerror.@O@ \ - time.@O@ \ -+ entropy.@O@ \ -+ keyboard.@O@ \ - ${ISCDRIVEROBJS} - - # Alphabetically -@@ -51,6 +53,8 @@ SRCS = @ISC_IPV6_C@ \ - file.c fsaccess.c \ - stdio.c stdtime.c strerror.c \ - time.c \ -+ entropy.c \ -+ keyboard.c \ - ${ISCDRIVERSRCS} - - SUBDIRS = include -diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in -index eb718fd..df62ec9 100644 ---- a/lib/isc/Makefile.in -+++ b/lib/isc/Makefile.in -@@ -23,16 +23,20 @@ top_srcdir = @top_srcdir@ - - @LIBISC_API@ - -+@BIND9_MAKE_INCLUDES@ -+ -+PROVIDER = @PKCS11_PROVIDER@ -+ - CINCLUDES = -I${srcdir}/unix/include \ - -I${srcdir}/@ISC_THREAD_DIR@/include \ - -I${srcdir}/@ISC_ARCH_DIR@/include \ - -I./include \ -- -I${srcdir}/include @ISC_OPENSSL_INC@ --CDEFINES = @USE_OPENSSL@ -+ -I${srcdir}/include @ISC_OPENSSL_INC@ ${DNS_INCLUDES} -+CDEFINES = @CRYPTO@ -DPK11_LIB_LOCATION=\"${PROVIDER}\" - CWARNINGS = - - # Alphabetically --UNIXOBJS = @ISC_ISCIPV6_O@ \ -+UNIXOBJS = @ISC_ISCIPV6_O@ @ISC_ISCPK11_API_O@ \ - unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ \ - unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \ - unix/interfaceiter.@O@ unix/keyboard.@O@ unix/net.@O@ \ -@@ -50,7 +54,7 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ - win32/thread.@O@ win32/time.@O@ - - # Alphabetically --OBJS = @ISC_EXTRA_OBJS@ \ -+OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \ - assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ - bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ - counter.@O@ error.@O@ event.@O@ \ -@@ -68,7 +72,7 @@ OBJS = @ISC_EXTRA_OBJS@ \ - SYMTBLOBJS = backtrace-emptytbl.@O@ - - # Alphabetically --SRCS = @ISC_EXTRA_SRCS@ \ -+SRCS = @ISC_EXTRA_SRCS@ @ISC_PK11_C@ @ISC_PK11_RESULT_C@ \ - assertions.c backtrace.c base32.c base64.c bitstring.c \ - buffer.c bufferlist.c commandline.c counter.c \ - error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \ -diff --git a/lib/isc/entropy.c b/lib/isc/entropy.c -index da9e81f..ae882d8 100644 ---- a/lib/isc/entropy.c -+++ b/lib/isc/entropy.c -@@ -46,6 +46,9 @@ - #include - #include - -+#ifdef PKCS11CRYPTO -+#include -+#endif - - #define ENTROPY_MAGIC ISC_MAGIC('E', 'n', 't', 'e') - #define SOURCE_MAGIC ISC_MAGIC('E', 'n', 't', 's') -@@ -1236,6 +1239,11 @@ isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source, - use_keyboard == ISC_ENTROPY_KEYBOARDNO || - use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE); - -+#ifdef PKCS11CRYPTO -+ if (randomfile != NULL) -+ pk11_rand_seed_fromfile(randomfile); -+#endif -+ - #ifdef PATH_RANDOMDEV - if (randomfile == NULL) { - randomfile = PATH_RANDOMDEV; -diff --git a/lib/isc/hmacmd5.c b/lib/isc/hmacmd5.c -index 4c4046d..79ec24a 100644 ---- a/lib/isc/hmacmd5.c -+++ b/lib/isc/hmacmd5.c -@@ -33,6 +33,11 @@ - #include - #include - -+#if PKCS11CRYPTO || PKCS11CRYPTOWITHHMAC -+#include -+#include -+#endif -+ - #ifdef ISC_PLATFORM_OPENSSLHASH - - void -@@ -60,6 +65,167 @@ isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { - HMAC_CTX_cleanup(ctx); - } - -+#elif PKCS11CRYPTOWITHHMAC -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+void -+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_MD5_HMAC, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; -+ CK_KEY_TYPE keyType = CKK_MD5_HMAC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, (CK_ULONG) len } -+ }; -+ -+ DE_CONST(key, keyTemplate[5].pValue); -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ ctx->object = CK_INVALID_HANDLE; -+ PK11_FATALCHECK(pkcs_C_CreateObject, -+ (ctx->session, keyTemplate, -+ (CK_ULONG) 6, &ctx->object)); -+ INSIST(ctx->object != CK_INVALID_HANDLE); -+ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object)); -+} -+ -+void -+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { -+ CK_BYTE garbage[ISC_MD5_DIGESTLENGTH]; -+ CK_ULONG len = ISC_MD5_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_SignFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+} -+ -+void -+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_SignUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { -+ CK_RV rv; -+ CK_ULONG len = ISC_MD5_DIGESTLENGTH; -+ -+ PK11_FATALCHECK(pkcs_C_SignFinal, -+ (ctx->session, (CK_BYTE_PTR) digest, &len)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+} -+ -+#elif PKCS11CRYPTO -+ -+#define PADLEN 64 -+#define IPAD 0x36 -+#define OPAD 0x5C -+ -+void -+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_MD5, NULL, 0 }; -+ unsigned char ipad[PADLEN]; -+ unsigned int i; -+ -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ RUNTIME_CHECK((ctx->key = pk11_mem_get(PADLEN)) != NULL); -+ if (len > PADLEN) { -+ CK_BYTE_PTR kPart; -+ CK_ULONG kl; -+ -+ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech)); -+ DE_CONST(key, kPart); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (ctx->session, kPart, (CK_ULONG) len)); -+ kl = ISC_MD5_DIGESTLENGTH; -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (ctx->session, (CK_BYTE_PTR) ctx->key, &kl)); -+ } else -+ memcpy(ctx->key, key, len); -+ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech)); -+ memset(ipad, IPAD, PADLEN); -+ for (i = 0; i < PADLEN; i++) -+ ipad[i] ^= ctx->key[i]; -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (ctx->session, ipad, (CK_ULONG) PADLEN)); -+} -+ -+void -+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) { -+ if (ctx->key != NULL) -+ pk11_mem_put(ctx->key, PADLEN); -+ ctx->key = NULL; -+ isc_md5_invalidate(ctx); -+} -+ -+void -+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_MD5, NULL, 0 }; -+ CK_ULONG len = ISC_MD5_DIGESTLENGTH; -+ CK_BYTE opad[PADLEN]; -+ unsigned int i; -+ -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (ctx->session, (CK_BYTE_PTR) digest, -+ (CK_ULONG_PTR) &len)); -+ memset(opad, OPAD, PADLEN); -+ for (i = 0; i < PADLEN; i++) -+ opad[i] ^= ctx->key[i]; -+ pk11_mem_put(ctx->key, PADLEN); -+ ctx->key = NULL; -+ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech)); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (ctx->session, opad, (CK_ULONG) PADLEN)); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (ctx->session, (CK_BYTE_PTR) digest, len)); -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (ctx->session, -+ (CK_BYTE_PTR) digest, -+ (CK_ULONG_PTR) &len)); -+ pk11_return_session(ctx); -+} -+ - #else - - #define PADLEN 64 -diff --git a/lib/isc/hmacsha.c b/lib/isc/hmacsha.c -index 3870963..9b79bc7 100644 ---- a/lib/isc/hmacsha.c -+++ b/lib/isc/hmacsha.c -@@ -34,6 +34,11 @@ - #include - #include - -+#if PKCS11CRYPTO -+#include -+#include -+#endif -+ - #ifdef ISC_PLATFORM_OPENSSLHASH - - void -@@ -191,6 +196,376 @@ isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) { - memset(newdigest, 0, sizeof(newdigest)); - } - -+#elif PKCS11CRYPTO -+ -+static CK_BBOOL truevalue = TRUE; -+static CK_BBOOL falsevalue = FALSE; -+ -+void -+isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA_1_HMAC, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; -+ CK_KEY_TYPE keyType = CKK_SHA_1_HMAC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, (CK_ULONG) len } -+ }; -+ -+ DE_CONST(key, keyTemplate[5].pValue); -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ ctx->object = CK_INVALID_HANDLE; -+ PK11_FATALCHECK(pkcs_C_CreateObject, -+ (ctx->session, keyTemplate, -+ (CK_ULONG) 6, &ctx->object)); -+ INSIST(ctx->object != CK_INVALID_HANDLE); -+ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object)); -+} -+ -+void -+isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) { -+ CK_BYTE garbage[ISC_SHA1_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA1_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_SignFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+} -+ -+void -+isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_SignUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { -+ CK_RV rv; -+ CK_BYTE newdigest[ISC_SHA1_DIGESTLENGTH]; -+ CK_ULONG psl = ISC_SHA1_DIGESTLENGTH; -+ -+ REQUIRE(len <= ISC_SHA1_DIGESTLENGTH); -+ -+ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+ memcpy(digest, newdigest, len); -+ memset(newdigest, 0, sizeof(newdigest)); -+} -+ -+void -+isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA224_HMAC, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; -+ CK_KEY_TYPE keyType = CKK_SHA224_HMAC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, (CK_ULONG) len } -+ }; -+ -+ DE_CONST(key, keyTemplate[5].pValue); -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ ctx->object = CK_INVALID_HANDLE; -+ PK11_FATALCHECK(pkcs_C_CreateObject, -+ (ctx->session, keyTemplate, -+ (CK_ULONG) 6, &ctx->object)); -+ INSIST(ctx->object != CK_INVALID_HANDLE); -+ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object)); -+} -+ -+void -+isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) { -+ CK_BYTE garbage[ISC_SHA224_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA224_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_SignFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+} -+ -+void -+isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_SignUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { -+ CK_RV rv; -+ CK_BYTE newdigest[ISC_SHA224_DIGESTLENGTH]; -+ CK_ULONG psl = ISC_SHA224_DIGESTLENGTH; -+ -+ REQUIRE(len <= ISC_SHA224_DIGESTLENGTH); -+ -+ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+ memcpy(digest, newdigest, len); -+ memset(newdigest, 0, sizeof(newdigest)); -+} -+ -+void -+isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA256_HMAC, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; -+ CK_KEY_TYPE keyType = CKK_SHA256_HMAC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, (CK_ULONG) len } -+ }; -+ -+ DE_CONST(key, keyTemplate[5].pValue); -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ ctx->object = CK_INVALID_HANDLE; -+ PK11_FATALCHECK(pkcs_C_CreateObject, -+ (ctx->session, keyTemplate, -+ (CK_ULONG) 6, &ctx->object)); -+ INSIST(ctx->object != CK_INVALID_HANDLE); -+ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object)); -+} -+ -+void -+isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) { -+ CK_BYTE garbage[ISC_SHA256_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA256_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_SignFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+} -+ -+void -+isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_SignUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { -+ CK_RV rv; -+ CK_BYTE newdigest[ISC_SHA256_DIGESTLENGTH]; -+ CK_ULONG psl = ISC_SHA256_DIGESTLENGTH; -+ -+ REQUIRE(len <= ISC_SHA256_DIGESTLENGTH); -+ -+ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+ memcpy(digest, newdigest, len); -+ memset(newdigest, 0, sizeof(newdigest)); -+} -+ -+void -+isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA384_HMAC, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; -+ CK_KEY_TYPE keyType = CKK_SHA384_HMAC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, (CK_ULONG) len } -+ }; -+ -+ DE_CONST(key, keyTemplate[5].pValue); -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ ctx->object = CK_INVALID_HANDLE; -+ PK11_FATALCHECK(pkcs_C_CreateObject, -+ (ctx->session, keyTemplate, -+ (CK_ULONG) 6, &ctx->object)); -+ INSIST(ctx->object != CK_INVALID_HANDLE); -+ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object)); -+} -+ -+void -+isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) { -+ CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA384_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_SignFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+} -+ -+void -+isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_SignUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { -+ CK_RV rv; -+ CK_BYTE newdigest[ISC_SHA384_DIGESTLENGTH]; -+ CK_ULONG psl = ISC_SHA384_DIGESTLENGTH; -+ -+ REQUIRE(len <= ISC_SHA384_DIGESTLENGTH); -+ -+ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+ memcpy(digest, newdigest, len); -+ memset(newdigest, 0, sizeof(newdigest)); -+} -+ -+void -+isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA512_HMAC, NULL, 0 }; -+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; -+ CK_KEY_TYPE keyType = CKK_SHA512_HMAC; -+ CK_ATTRIBUTE keyTemplate[] = -+ { -+ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, -+ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, -+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, -+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, -+ { CKA_VALUE, NULL, (CK_ULONG) len } -+ }; -+ -+ DE_CONST(key, keyTemplate[5].pValue); -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ ctx->object = CK_INVALID_HANDLE; -+ PK11_FATALCHECK(pkcs_C_CreateObject, -+ (ctx->session, keyTemplate, -+ (CK_ULONG) 6, &ctx->object)); -+ INSIST(ctx->object != CK_INVALID_HANDLE); -+ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object)); -+} -+ -+void -+isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) { -+ CK_BYTE garbage[ISC_SHA512_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA512_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_SignFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+} -+ -+void -+isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf, -+ unsigned int len) -+{ -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_SignUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) { -+ CK_RV rv; -+ CK_BYTE newdigest[ISC_SHA512_DIGESTLENGTH]; -+ CK_ULONG psl = ISC_SHA512_DIGESTLENGTH; -+ -+ REQUIRE(len <= ISC_SHA512_DIGESTLENGTH); -+ -+ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl)); -+ if (ctx->object != CK_INVALID_HANDLE) -+ (void) pkcs_C_DestroyObject(ctx->session, ctx->object); -+ ctx->object = CK_INVALID_HANDLE; -+ pk11_return_session(ctx); -+ memcpy(digest, newdigest, len); -+ memset(newdigest, 0, sizeof(newdigest)); -+} -+ - #else - - #define IPAD 0x36 -diff --git a/lib/isc/include/Makefile.in b/lib/isc/include/Makefile.in -index 70c165e..c92ad45 100644 ---- a/lib/isc/include/Makefile.in -+++ b/lib/isc/include/Makefile.in -@@ -19,7 +19,7 @@ srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ - --SUBDIRS = isc -+SUBDIRS = isc pk11 pkcs11 - TARGETS = - - @BIND9_MAKE_RULES@ -diff --git a/lib/isc/include/isc/hmacmd5.h b/lib/isc/include/isc/hmacmd5.h -index 9ecad45..e008328 100644 ---- a/lib/isc/include/isc/hmacmd5.h -+++ b/lib/isc/include/isc/hmacmd5.h -@@ -37,6 +37,11 @@ - - typedef HMAC_CTX isc_hmacmd5_t; - -+#elif PKCS11CRYPTO -+#include -+ -+typedef pk11_context_t isc_hmacmd5_t; -+ - #else - - typedef struct { -diff --git a/lib/isc/include/isc/hmacsha.h b/lib/isc/include/isc/hmacsha.h -index 1d0e184..c223897 100644 ---- a/lib/isc/include/isc/hmacsha.h -+++ b/lib/isc/include/isc/hmacsha.h -@@ -45,6 +45,15 @@ typedef HMAC_CTX isc_hmacsha256_t; - typedef HMAC_CTX isc_hmacsha384_t; - typedef HMAC_CTX isc_hmacsha512_t; - -+#elif PKCS11CRYPTO -+#include -+ -+typedef pk11_context_t isc_hmacsha1_t; -+typedef pk11_context_t isc_hmacsha224_t; -+typedef pk11_context_t isc_hmacsha256_t; -+typedef pk11_context_t isc_hmacsha384_t; -+typedef pk11_context_t isc_hmacsha512_t; -+ - #else - - typedef struct { -diff --git a/lib/isc/include/isc/md5.h b/lib/isc/include/isc/md5.h -index dfa586d..a2e00b3 100644 ---- a/lib/isc/include/isc/md5.h -+++ b/lib/isc/include/isc/md5.h -@@ -55,6 +55,11 @@ - - typedef EVP_MD_CTX isc_md5_t; - -+#elif PKCS11CRYPTO -+#include -+ -+typedef pk11_context_t isc_md5_t; -+ - #else - - typedef struct { -diff --git a/lib/isc/include/isc/resultclass.h b/lib/isc/include/isc/resultclass.h -index d91e800..44b0eb4 100644 ---- a/lib/isc/include/isc/resultclass.h -+++ b/lib/isc/include/isc/resultclass.h -@@ -46,6 +46,6 @@ - #define ISC_RESULTCLASS_OMAPI ISC_RESULTCLASS_FROMNUM(4) - #define ISC_RESULTCLASS_ISCCC ISC_RESULTCLASS_FROMNUM(5) - #define ISC_RESULTCLASS_DHCP ISC_RESULTCLASS_FROMNUM(6) -- -+#define ISC_RESULTCLASS_PK11 ISC_RESULTCLASS_FROMNUM(7) - - #endif /* ISC_RESULTCLASS_H */ -diff --git a/lib/isc/include/isc/sha1.h b/lib/isc/include/isc/sha1.h -index 313ff96..f11a783 100644 ---- a/lib/isc/include/isc/sha1.h -+++ b/lib/isc/include/isc/sha1.h -@@ -40,6 +40,11 @@ - - typedef EVP_MD_CTX isc_sha1_t; - -+#elif PKCS11CRYPTO -+#include -+ -+typedef pk11_context_t isc_sha1_t; -+ - #else - - typedef struct { -diff --git a/lib/isc/include/isc/sha2.h b/lib/isc/include/isc/sha2.h -index 439bbb9..14faa6e 100644 ---- a/lib/isc/include/isc/sha2.h -+++ b/lib/isc/include/isc/sha2.h -@@ -84,6 +84,12 @@ - typedef EVP_MD_CTX isc_sha256_t; - typedef EVP_MD_CTX isc_sha512_t; - -+#elif PKCS11CRYPTO -+#include -+ -+typedef pk11_context_t isc_sha256_t; -+typedef pk11_context_t isc_sha512_t; -+ - #else - - /* -diff --git a/lib/isc/include/pk11/Makefile.in b/lib/isc/include/pk11/Makefile.in -new file mode 100644 -index 0000000..744c40e ---- /dev/null -+++ b/lib/isc/include/pk11/Makefile.in -@@ -0,0 +1,38 @@ -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_VERSION@ -+ -+# -+# Only list headers that are to be installed and are not -+# machine generated. The latter are handled specially in the -+# install target below. -+# -+HEADERS = constants.h internal.h pk11.h result.h -+SUBDIRS = -+TARGETS = -+ -+@BIND9_MAKE_RULES@ -+ -+installdirs: -+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pk11 -+ -+install:: installdirs -+ for i in ${HEADERS}; do \ -+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/pk11 ; \ -+ done -diff --git a/lib/isc/include/pk11/constants.h b/lib/isc/include/pk11/constants.h -new file mode 100644 -index 0000000..e1e0581 ---- /dev/null -+++ b/lib/isc/include/pk11/constants.h -@@ -0,0 +1,107 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+#ifndef PK11_CONSTANTS_H -+#define PK11_CONSTANTS_H 1 -+ -+/*! \file pk11/constants.h */ -+ -+/*% -+ * Static arrays of data used for key template initalization -+ */ -+#ifdef WANT_ECC_CURVES -+static CK_BYTE pk11_ecc_prime256v1[] = { -+ 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 -+}; -+static CK_BYTE pk11_ecc_secp384r1[] = { -+ 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 -+}; -+#endif -+ -+#ifdef WANT_DH_PRIMES -+static CK_BYTE pk11_dh_bn2[] = { 2 }; -+static CK_BYTE pk11_dh_bn768[] = { -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, -+ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, -+ 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, -+ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, -+ 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd, -+ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, -+ 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37, -+ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, -+ 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, -+ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -+}; -+static CK_BYTE pk11_dh_bn1024[] = { -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, -+ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, -+ 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, -+ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, -+ 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd, -+ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, -+ 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37, -+ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, -+ 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, -+ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b, -+ 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed, -+ 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, -+ 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6, -+ 0x49, 0x28, 0x66, 0x51, 0xec, 0xe6, 0x53, 0x81, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -+}; -+static CK_BYTE pk11_dh_bn1536[] = { -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34, -+ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, -+ 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, -+ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, -+ 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd, -+ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, -+ 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37, -+ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, -+ 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, -+ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b, -+ 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed, -+ 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, -+ 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6, -+ 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d, -+ 0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, -+ 0x98, 0xda, 0x48, 0x36, 0x1c, 0x55, 0xd3, 0x9a, -+ 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f, -+ 0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, -+ 0x1c, 0x62, 0xf3, 0x56, 0x20, 0x85, 0x52, 0xbb, -+ 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d, -+ 0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, -+ 0xf1, 0x74, 0x6c, 0x08, 0xca, 0x23, 0x73, 0x27, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -+}; -+#endif -+ -+#ifdef WANT_GOST_PARAMS -+static CK_BYTE pk11_gost_a_paramset[] = { -+ 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 -+}; -+static CK_BYTE pk11_gost_paramset[] = { -+ 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01 -+}; -+#endif -+ -+#endif /* PK11_CONSTANTS_H */ -diff --git a/lib/isc/include/pk11/internal.h b/lib/isc/include/pk11/internal.h -new file mode 100644 -index 0000000..14bef3c ---- /dev/null -+++ b/lib/isc/include/pk11/internal.h -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+#ifndef PK11_INTERNAL_H -+#define PK11_INTERNAL_H 1 -+ -+/*! \file pk11/internal.h */ -+ -+ISC_LANG_BEGINDECLS -+ -+const char *pk11_get_lib_name(void); -+ -+void *pk11_mem_get(size_t size); -+ -+void pk11_mem_put(void *ptr, size_t size); -+ -+CK_SLOT_ID pk11_get_best_token(pk11_optype_t optype); -+ -+unsigned int pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt); -+ -+CK_ATTRIBUTE *pk11_attribute_first(const pk11_object_t *obj); -+ -+CK_ATTRIBUTE *pk11_attribute_next(const pk11_object_t *obj, -+ CK_ATTRIBUTE *attr); -+ -+CK_ATTRIBUTE *pk11_attribute_bytype(const pk11_object_t *obj, -+ CK_ATTRIBUTE_TYPE type); -+ -+ISC_LANG_ENDDECLS -+ -+#endif /* PK11_INTERNAL_H */ -diff --git a/lib/isc/include/pk11/pk11.h b/lib/isc/include/pk11/pk11.h -new file mode 100644 -index 0000000..964a2a7 ---- /dev/null -+++ b/lib/isc/include/pk11/pk11.h -@@ -0,0 +1,295 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef PK11_PK11_H -+#define PK11_PK11_H 1 -+ -+/*! \file pk11/pk11.h */ -+ -+#include -+#include -+#include -+ -+#define PK11_FATALCHECK(func, args) \ -+ ((void) (((rv = (func) args) == CKR_OK) || \ -+ ((pk11_error_fatalcheck)(__FILE__, __LINE__, #func, rv), 0))) -+ -+#include -+ -+ISC_LANG_BEGINDECLS -+ -+#define SES_MAGIC ISC_MAGIC('P','K','S','S') -+#define TOK_MAGIC ISC_MAGIC('P','K','T','K') -+ -+#define VALID_SES(x) ISC_MAGIC_VALID(x, SES_MAGIC) -+#define VALID_TOK(x) ISC_MAGIC_VALID(x, TOK_MAGIC) -+ -+typedef struct pk11_context pk11_context_t; -+ -+struct pk11_object { -+ CK_OBJECT_HANDLE object; -+ CK_SLOT_ID slot; -+ CK_BBOOL ontoken; -+ CK_BBOOL reqlogon; -+ CK_BYTE attrcnt; -+ CK_ATTRIBUTE *repr; -+}; -+ -+struct pk11_context { -+ void *handle; -+ CK_SESSION_HANDLE session; -+ CK_BBOOL ontoken; -+ CK_OBJECT_HANDLE object; -+#ifndef PKCS11CRYPTOWITHHMAC -+ unsigned char *key; -+#endif -+}; -+ -+typedef struct pk11_object pk11_object_t; -+ -+typedef enum { -+ OP_ANY = 0, -+ OP_RAND = 1, -+ OP_RSA = 2, -+ OP_DSA = 3, -+ OP_DH = 4, -+ OP_DIGEST = 5, -+ OP_EC = 6, -+ OP_GOST = 7, -+ OP_AES = 8, -+ OP_MAX = 9 -+} pk11_optype_t; -+ -+/*% -+ * Function prototypes -+ */ -+ -+void pk11_set_lib_name(const char *lib_name); -+/*%< -+ * Set the PKCS#11 provider (aka library) path/name. -+ */ -+ -+isc_result_t pk11_initialize(isc_mem_t *mctx, const char *engine); -+/*%< -+ * Initialize PKCS#11 device -+ * -+ * mctx: memory context to attach to pk11_mctx. -+ * engine: PKCS#11 provider (aka library) path/name. -+ * -+ * returns: -+ * ISC_R_SUCCESS -+ * PK11_R_NOPROVIDER: can't load the provider -+ * PK11_R_INITFAILED: C_Initialize() failed -+ * PK11_R_NORANDOMSERVICE: can't find required random service -+ * PK11_R_NODIGESTSERVICE: can't find required digest service -+ * PK11_R_NOAESSERVICE: can't find required AES service -+ */ -+ -+isc_result_t pk11_get_session(pk11_context_t *ctx, -+ pk11_optype_t optype, -+ isc_boolean_t need_services, -+ isc_boolean_t rw, -+ isc_boolean_t logon, -+ const char *pin, -+ CK_SLOT_ID slot); -+/*%< -+ * Initialize PKCS#11 device and acquire a session. -+ * -+ * need_services: -+ * if ISC_TRUE, this session requires full PKCS#11 API -+ * support including random and digest services, and -+ * the lack of these services will cause the session not -+ * to be initialized. If ISC_FALSE, the function will return -+ * an error code indicating the missing service, but the -+ * session will be usable for other purposes. -+ * rw: if ISC_TRUE, session will be read/write (useful for -+ * generating or destroying keys); otherwise read-only. -+ * login: indicates whether to log in to the device -+ * pin: optional PIN, overriding any PIN currently associated -+ * with the -+ * slot: device slot ID -+ */ -+ -+void pk11_return_session(pk11_context_t *ctx); -+/*%< -+ * Release an active PKCS#11 session for reuse. -+ */ -+ -+isc_result_t pk11_finalize(void); -+/*%< -+ * Shut down PKCS#11 device and free all sessions. -+ */ -+ -+isc_result_t pk11_rand_bytes(unsigned char *buf, int num); -+ -+void pk11_rand_seed_fromfile(const char *randomfile); -+ -+isc_result_t pk11_parse_uri(pk11_object_t *obj, const char *label, -+ isc_mem_t *mctx, pk11_optype_t optype); -+ -+ISC_PLATFORM_NORETURN_PRE void -+pk11_error_fatalcheck(const char *file, int line, -+ const char *funcname, CK_RV rv) -+ISC_PLATFORM_NORETURN_POST; -+ -+void pk11_dump_tokens(void); -+ -+CK_RV -+pkcs_C_Initialize(CK_VOID_PTR pReserved); -+ -+CK_RV -+pkcs_C_Finalize(CK_VOID_PTR pReserved); -+ -+CK_RV -+pkcs_C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, -+ CK_ULONG_PTR pulCount); -+ -+CK_RV -+pkcs_C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); -+ -+CK_RV -+pkcs_C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, -+ CK_MECHANISM_INFO_PTR pInfo); -+ -+CK_RV -+pkcs_C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, -+ CK_VOID_PTR pApplication, -+ CK_RV (*Notify) (CK_SESSION_HANDLE hSession, -+ CK_NOTIFICATION event, -+ CK_VOID_PTR pApplication), -+ CK_SESSION_HANDLE_PTR phSession); -+ -+CK_RV -+pkcs_C_CloseSession(CK_SESSION_HANDLE hSession); -+ -+CK_RV -+pkcs_C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, -+ CK_CHAR_PTR pPin, CK_ULONG usPinLen); -+ -+CK_RV -+pkcs_C_Logout(CK_SESSION_HANDLE hSession); -+ -+CK_RV -+pkcs_C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, -+ CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phObject); -+ -+CK_RV -+pkcs_C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject); -+ -+CK_RV -+pkcs_C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, -+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); -+ -+CK_RV -+pkcs_C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, -+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount); -+ -+CK_RV -+pkcs_C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, -+ CK_ULONG usCount); -+ -+CK_RV -+pkcs_C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, -+ CK_ULONG usMaxObjectCount, CK_ULONG_PTR pusObjectCount); -+ -+CK_RV -+pkcs_C_FindObjectsFinal(CK_SESSION_HANDLE hSession); -+ -+CK_RV -+pkcs_C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey); -+ -+CK_RV -+pkcs_C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, -+ CK_ULONG_PTR pulEncryptedDataLen); -+ -+CK_RV -+pkcs_C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism); -+ -+CK_RV -+pkcs_C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen); -+ -+CK_RV -+pkcs_C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, -+ CK_ULONG_PTR pulDigestLen); -+ -+CK_RV -+pkcs_C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey); -+ -+CK_RV -+pkcs_C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, -+ CK_ULONG_PTR pulSignatureLen); -+ -+CK_RV -+pkcs_C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen); -+ -+CK_RV -+pkcs_C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, -+ CK_ULONG_PTR pulSignatureLen); -+ -+CK_RV -+pkcs_C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey); -+ -+CK_RV -+pkcs_C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, -+ CK_ULONG ulSignatureLen); -+ -+CK_RV -+pkcs_C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen); -+ -+CK_RV -+pkcs_C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, -+ CK_ULONG ulSignatureLen); -+ -+CK_RV -+pkcs_C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, -+ CK_OBJECT_HANDLE_PTR phKey); -+ -+CK_RV -+pkcs_C_GenerateKeyPair(CK_SESSION_HANDLE hSession, -+ CK_MECHANISM_PTR pMechanism, -+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, -+ CK_ULONG usPublicKeyAttributeCount, -+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, -+ CK_ULONG usPrivateKeyAttributeCount, -+ CK_OBJECT_HANDLE_PTR phPrivateKey, -+ CK_OBJECT_HANDLE_PTR phPublicKey); -+ -+CK_RV -+pkcs_C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, -+ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey); -+ -+CK_RV -+pkcs_C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, -+ CK_ULONG ulSeedLen); -+ -+CK_RV -+pkcs_C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData, -+ CK_ULONG ulRandomLen); -+ -+ISC_LANG_ENDDECLS -+ -+#endif /* PK11_PK11_H */ -diff --git a/lib/isc/include/pk11/result.h b/lib/isc/include/pk11/result.h -new file mode 100644 -index 0000000..f624140 ---- /dev/null -+++ b/lib/isc/include/pk11/result.h -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef PK11_RESULT_H -+#define PK11_RESULT_H 1 -+ -+/*! \file pk11/result.h */ -+ -+#include -+#include -+ -+/* -+ * Nothing in this file truly depends on , but the -+ * PK11 result codes are considered to be publicly derived from -+ * the ISC result codes, so including this file buys you the ISC_R_ -+ * namespace too. -+ */ -+#include /* Contractual promise. */ -+ -+#define PK11_R_INITFAILED (ISC_RESULTCLASS_PK11 + 0) -+#define PK11_R_NOPROVIDER (ISC_RESULTCLASS_PK11 + 1) -+#define PK11_R_NORANDOMSERVICE (ISC_RESULTCLASS_PK11 + 2) -+#define PK11_R_NODIGESTSERVICE (ISC_RESULTCLASS_PK11 + 3) -+#define PK11_R_NOAESSERVICE (ISC_RESULTCLASS_PK11 + 4) -+ -+#define PK11_R_NRESULTS 5 /* Number of results */ -+ -+ISC_LANG_BEGINDECLS -+ -+LIBISC_EXTERNAL_DATA extern isc_msgcat_t *pk11_msgcat; -+ -+void -+pk11_initmsgcat(void); -+ -+const char * -+pk11_result_totext(isc_result_t); -+ -+void -+pk11_result_register(void); -+ -+ISC_LANG_ENDDECLS -+ -+#endif /* PK11_RESULT_H */ -diff --git a/lib/isc/include/pkcs11/Makefile.in b/lib/isc/include/pkcs11/Makefile.in -new file mode 100644 -index 0000000..6e98688 ---- /dev/null -+++ b/lib/isc/include/pkcs11/Makefile.in -@@ -0,0 +1,40 @@ -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id: Makefile.in,v 1.7 2007/06/19 23:47:22 tbox Exp $ -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_VERSION@ -+ -+# -+# Only list headers that are to be installed and are not -+# machine generated. The latter are handled specially in the -+# install target below. -+# -+HEADERS = pkcs11f.h pkcs11.h pkcs11t.h -+SUBDIRS = -+TARGETS = -+ -+@BIND9_MAKE_RULES@ -+ -+installdirs: -+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pkcs11 -+ -+install:: installdirs -+ for i in ${HEADERS}; do \ -+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/pkcs11 ; \ -+ done -diff --git a/lib/isc/include/pkcs11/pkcs11.h b/lib/isc/include/pkcs11/pkcs11.h -new file mode 100644 -index 0000000..9261e1e ---- /dev/null -+++ b/lib/isc/include/pkcs11/pkcs11.h -@@ -0,0 +1,299 @@ -+/* pkcs11.h include file for PKCS #11. */ -+/* $Revision: 1.2 $ */ -+ -+/* License to copy and use this software is granted provided that it is -+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface -+ * (Cryptoki)" in all material mentioning or referencing this software. -+ -+ * License is also granted to make and use derivative works provided that -+ * such works are identified as "derived from the RSA Security Inc. PKCS #11 -+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or -+ * referencing the derived work. -+ -+ * RSA Security Inc. makes no representations concerning either the -+ * merchantability of this software or the suitability of this software for -+ * any particular purpose. It is provided "as is" without express or implied -+ * warranty of any kind. -+ */ -+ -+#ifndef _PKCS11_H_ -+#define _PKCS11_H_ 1 -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* Before including this file (pkcs11.h) (or pkcs11t.h by -+ * itself), 6 platform-specific macros must be defined. These -+ * macros are described below, and typical definitions for them -+ * are also given. Be advised that these definitions can depend -+ * on both the platform and the compiler used (and possibly also -+ * on whether a Cryptoki library is linked statically or -+ * dynamically). -+ * -+ * In addition to defining these 6 macros, the packing convention -+ * for Cryptoki structures should be set. The Cryptoki -+ * convention on packing is that structures should be 1-byte -+ * aligned. -+ * -+ * If you're using Microsoft Developer Studio 5.0 to produce -+ * Win32 stuff, this might be done by using the following -+ * preprocessor directive before including pkcs11.h or pkcs11t.h: -+ * -+ * #pragma pack(push, cryptoki, 1) -+ * -+ * and using the following preprocessor directive after including -+ * pkcs11.h or pkcs11t.h: -+ * -+ * #pragma pack(pop, cryptoki) -+ * -+ * If you're using an earlier version of Microsoft Developer -+ * Studio to produce Win16 stuff, this might be done by using -+ * the following preprocessor directive before including -+ * pkcs11.h or pkcs11t.h: -+ * -+ * #pragma pack(1) -+ * -+ * In a UNIX environment, you're on your own for this. You might -+ * not need to do (or be able to do!) anything. -+ * -+ * -+ * Now for the macros: -+ * -+ * -+ * 1. CK_PTR: The indirection string for making a pointer to an -+ * object. It can be used like this: -+ * -+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR; -+ * -+ * If you're using Microsoft Developer Studio 5.0 to produce -+ * Win32 stuff, it might be defined by: -+ * -+ * #define CK_PTR * -+ * -+ * If you're using an earlier version of Microsoft Developer -+ * Studio to produce Win16 stuff, it might be defined by: -+ * -+ * #define CK_PTR far * -+ * -+ * In a typical UNIX environment, it might be defined by: -+ * -+ * #define CK_PTR * -+ * -+ * -+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes -+ * an exportable Cryptoki library function definition out of a -+ * return type and a function name. It should be used in the -+ * following fashion to define the exposed Cryptoki functions in -+ * a Cryptoki library: -+ * -+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)( -+ * CK_VOID_PTR pReserved -+ * ) -+ * { -+ * ... -+ * } -+ * -+ * If you're using Microsoft Developer Studio 5.0 to define a -+ * function in a Win32 Cryptoki .dll, it might be defined by: -+ * -+ * #define CK_DEFINE_FUNCTION(returnType, name) \ -+ * returnType __declspec(dllexport) name -+ * -+ * If you're using an earlier version of Microsoft Developer -+ * Studio to define a function in a Win16 Cryptoki .dll, it -+ * might be defined by: -+ * -+ * #define CK_DEFINE_FUNCTION(returnType, name) \ -+ * returnType __export _far _pascal name -+ * -+ * In a UNIX environment, it might be defined by: -+ * -+ * #define CK_DEFINE_FUNCTION(returnType, name) \ -+ * returnType name -+ * -+ * -+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes -+ * an importable Cryptoki library function declaration out of a -+ * return type and a function name. It should be used in the -+ * following fashion: -+ * -+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)( -+ * CK_VOID_PTR pReserved -+ * ); -+ * -+ * If you're using Microsoft Developer Studio 5.0 to declare a -+ * function in a Win32 Cryptoki .dll, it might be defined by: -+ * -+ * #define CK_DECLARE_FUNCTION(returnType, name) \ -+ * returnType __declspec(dllimport) name -+ * -+ * If you're using an earlier version of Microsoft Developer -+ * Studio to declare a function in a Win16 Cryptoki .dll, it -+ * might be defined by: -+ * -+ * #define CK_DECLARE_FUNCTION(returnType, name) \ -+ * returnType __export _far _pascal name -+ * -+ * In a UNIX environment, it might be defined by: -+ * -+ * #define CK_DECLARE_FUNCTION(returnType, name) \ -+ * returnType name -+ * -+ * -+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro -+ * which makes a Cryptoki API function pointer declaration or -+ * function pointer type declaration out of a return type and a -+ * function name. It should be used in the following fashion: -+ * -+ * // Define funcPtr to be a pointer to a Cryptoki API function -+ * // taking arguments args and returning CK_RV. -+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args); -+ * -+ * or -+ * -+ * // Define funcPtrType to be the type of a pointer to a -+ * // Cryptoki API function taking arguments args and returning -+ * // CK_RV, and then define funcPtr to be a variable of type -+ * // funcPtrType. -+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args); -+ * funcPtrType funcPtr; -+ * -+ * If you're using Microsoft Developer Studio 5.0 to access -+ * functions in a Win32 Cryptoki .dll, in might be defined by: -+ * -+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ -+ * returnType __declspec(dllimport) (* name) -+ * -+ * If you're using an earlier version of Microsoft Developer -+ * Studio to access functions in a Win16 Cryptoki .dll, it might -+ * be defined by: -+ * -+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ -+ * returnType __export _far _pascal (* name) -+ * -+ * In a UNIX environment, it might be defined by: -+ * -+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ -+ * returnType (* name) -+ * -+ * -+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes -+ * a function pointer type for an application callback out of -+ * a return type for the callback and a name for the callback. -+ * It should be used in the following fashion: -+ * -+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args); -+ * -+ * to declare a function pointer, myCallback, to a callback -+ * which takes arguments args and returns a CK_RV. It can also -+ * be used like this: -+ * -+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args); -+ * myCallbackType myCallback; -+ * -+ * If you're using Microsoft Developer Studio 5.0 to do Win32 -+ * Cryptoki development, it might be defined by: -+ * -+ * #define CK_CALLBACK_FUNCTION(returnType, name) \ -+ * returnType (* name) -+ * -+ * If you're using an earlier version of Microsoft Developer -+ * Studio to do Win16 development, it might be defined by: -+ * -+ * #define CK_CALLBACK_FUNCTION(returnType, name) \ -+ * returnType _far _pascal (* name) -+ * -+ * In a UNIX environment, it might be defined by: -+ * -+ * #define CK_CALLBACK_FUNCTION(returnType, name) \ -+ * returnType (* name) -+ * -+ * -+ * 6. NULL_PTR: This macro is the value of a NULL pointer. -+ * -+ * In any ANSI/ISO C environment (and in many others as well), -+ * this should best be defined by -+ * -+ * #ifndef NULL_PTR -+ * #define NULL_PTR 0 -+ * #endif -+ */ -+ -+ -+/* All the various Cryptoki types and #define'd values are in the -+ * file pkcs11t.h. */ -+#include "pkcs11t.h" -+ -+#define __PASTE(x,y) x##y -+ -+ -+/* ============================================================== -+ * Define the "extern" form of all the entry points. -+ * ============================================================== -+ */ -+ -+#define CK_NEED_ARG_LIST 1 -+#define CK_PKCS11_FUNCTION_INFO(name) \ -+ extern CK_DECLARE_FUNCTION(CK_RV, name) -+ -+/* pkcs11f.h has all the information about the Cryptoki -+ * function prototypes. */ -+#include "pkcs11f.h" -+ -+#undef CK_NEED_ARG_LIST -+#undef CK_PKCS11_FUNCTION_INFO -+ -+ -+/* ============================================================== -+ * Define the typedef form of all the entry points. That is, for -+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is -+ * a pointer to that kind of function. -+ * ============================================================== -+ */ -+ -+#define CK_NEED_ARG_LIST 1 -+#define CK_PKCS11_FUNCTION_INFO(name) \ -+ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name)) -+ -+/* pkcs11f.h has all the information about the Cryptoki -+ * function prototypes. */ -+#include "pkcs11f.h" -+ -+#undef CK_NEED_ARG_LIST -+#undef CK_PKCS11_FUNCTION_INFO -+ -+ -+/* ============================================================== -+ * Define structed vector of entry points. A CK_FUNCTION_LIST -+ * contains a CK_VERSION indicating a library's Cryptoki version -+ * and then a whole slew of function pointers to the routines in -+ * the library. This type was declared, but not defined, in -+ * pkcs11t.h. -+ * ============================================================== -+ */ -+ -+#define CK_PKCS11_FUNCTION_INFO(name) \ -+ __PASTE(CK_,name) name; -+ -+struct CK_FUNCTION_LIST { -+ -+ CK_VERSION version; /* Cryptoki version */ -+ -+/* Pile all the function pointers into the CK_FUNCTION_LIST. */ -+/* pkcs11f.h has all the information about the Cryptoki -+ * function prototypes. */ -+#include "pkcs11f.h" -+ -+}; -+ -+#undef CK_PKCS11_FUNCTION_INFO -+ -+ -+#undef __PASTE -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -diff --git a/lib/isc/include/pkcs11/pkcs11f.h b/lib/isc/include/pkcs11/pkcs11f.h -new file mode 100644 -index 0000000..dec6315 ---- /dev/null -+++ b/lib/isc/include/pkcs11/pkcs11f.h -@@ -0,0 +1,912 @@ -+/* pkcs11f.h include file for PKCS #11. */ -+/* $Revision: 1.2 $ */ -+ -+/* License to copy and use this software is granted provided that it is -+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface -+ * (Cryptoki)" in all material mentioning or referencing this software. -+ -+ * License is also granted to make and use derivative works provided that -+ * such works are identified as "derived from the RSA Security Inc. PKCS #11 -+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or -+ * referencing the derived work. -+ -+ * RSA Security Inc. makes no representations concerning either the -+ * merchantability of this software or the suitability of this software for -+ * any particular purpose. It is provided "as is" without express or implied -+ * warranty of any kind. -+ */ -+ -+/* This header file contains pretty much everything about all the */ -+/* Cryptoki function prototypes. Because this information is */ -+/* used for more than just declaring function prototypes, the */ -+/* order of the functions appearing herein is important, and */ -+/* should not be altered. */ -+ -+/* General-purpose */ -+ -+/* C_Initialize initializes the Cryptoki library. */ -+CK_PKCS11_FUNCTION_INFO(C_Initialize) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets -+ * cast to CK_C_INITIALIZE_ARGS_PTR -+ * and dereferenced */ -+); -+#endif -+ -+ -+/* C_Finalize indicates that an application is done with the -+ * Cryptoki library. */ -+CK_PKCS11_FUNCTION_INFO(C_Finalize) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */ -+); -+#endif -+ -+ -+/* C_GetInfo returns general information about Cryptoki. */ -+CK_PKCS11_FUNCTION_INFO(C_GetInfo) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_INFO_PTR pInfo /* location that receives information */ -+); -+#endif -+ -+ -+/* C_GetFunctionList returns the function list. */ -+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to -+ * function list */ -+); -+#endif -+ -+ -+ -+/* Slot and token management */ -+ -+/* C_GetSlotList obtains a list of slots in the system. */ -+CK_PKCS11_FUNCTION_INFO(C_GetSlotList) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_BBOOL tokenPresent, /* only slots with tokens? */ -+ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */ -+ CK_ULONG_PTR pulCount /* receives number of slots */ -+); -+#endif -+ -+ -+/* C_GetSlotInfo obtains information about a particular slot in -+ * the system. */ -+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SLOT_ID slotID, /* the ID of the slot */ -+ CK_SLOT_INFO_PTR pInfo /* receives the slot information */ -+); -+#endif -+ -+ -+/* C_GetTokenInfo obtains information about a particular token -+ * in the system. */ -+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SLOT_ID slotID, /* ID of the token's slot */ -+ CK_TOKEN_INFO_PTR pInfo /* receives the token information */ -+); -+#endif -+ -+ -+/* C_GetMechanismList obtains a list of mechanism types -+ * supported by a token. */ -+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SLOT_ID slotID, /* ID of token's slot */ -+ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */ -+ CK_ULONG_PTR pulCount /* gets # of mechs. */ -+); -+#endif -+ -+ -+/* C_GetMechanismInfo obtains information about a particular -+ * mechanism possibly supported by a token. */ -+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SLOT_ID slotID, /* ID of the token's slot */ -+ CK_MECHANISM_TYPE type, /* type of mechanism */ -+ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */ -+); -+#endif -+ -+ -+/* C_InitToken initializes a token. */ -+CK_PKCS11_FUNCTION_INFO(C_InitToken) -+#ifdef CK_NEED_ARG_LIST -+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ -+( -+ CK_SLOT_ID slotID, /* ID of the token's slot */ -+ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */ -+ CK_ULONG ulPinLen, /* length in bytes of the PIN */ -+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ -+); -+#endif -+ -+ -+/* C_InitPIN initializes the normal user's PIN. */ -+CK_PKCS11_FUNCTION_INFO(C_InitPIN) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */ -+ CK_ULONG ulPinLen /* length in bytes of the PIN */ -+); -+#endif -+ -+ -+/* C_SetPIN modifies the PIN of the user who is logged in. */ -+CK_PKCS11_FUNCTION_INFO(C_SetPIN) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */ -+ CK_ULONG ulOldLen, /* length of the old PIN */ -+ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */ -+ CK_ULONG ulNewLen /* length of the new PIN */ -+); -+#endif -+ -+ -+ -+/* Session management */ -+ -+/* C_OpenSession opens a session between an application and a -+ * token. */ -+CK_PKCS11_FUNCTION_INFO(C_OpenSession) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SLOT_ID slotID, /* the slot's ID */ -+ CK_FLAGS flags, /* from CK_SESSION_INFO */ -+ CK_VOID_PTR pApplication, /* passed to callback */ -+ CK_NOTIFY Notify, /* callback function */ -+ CK_SESSION_HANDLE_PTR phSession /* gets session handle */ -+); -+#endif -+ -+ -+/* C_CloseSession closes a session between an application and a -+ * token. */ -+CK_PKCS11_FUNCTION_INFO(C_CloseSession) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession /* the session's handle */ -+); -+#endif -+ -+ -+/* C_CloseAllSessions closes all sessions with a token. */ -+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SLOT_ID slotID /* the token's slot */ -+); -+#endif -+ -+ -+/* C_GetSessionInfo obtains information about the session. */ -+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_SESSION_INFO_PTR pInfo /* receives session info */ -+); -+#endif -+ -+ -+/* C_GetOperationState obtains the state of the cryptographic operation -+ * in a session. */ -+CK_PKCS11_FUNCTION_INFO(C_GetOperationState) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pOperationState, /* gets state */ -+ CK_ULONG_PTR pulOperationStateLen /* gets state length */ -+); -+#endif -+ -+ -+/* C_SetOperationState restores the state of the cryptographic -+ * operation in a session. */ -+CK_PKCS11_FUNCTION_INFO(C_SetOperationState) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pOperationState, /* holds state */ -+ CK_ULONG ulOperationStateLen, /* holds state length */ -+ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */ -+ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */ -+); -+#endif -+ -+ -+/* C_Login logs a user into a token. */ -+CK_PKCS11_FUNCTION_INFO(C_Login) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_USER_TYPE userType, /* the user type */ -+ CK_UTF8CHAR_PTR pPin, /* the user's PIN */ -+ CK_ULONG ulPinLen /* the length of the PIN */ -+); -+#endif -+ -+ -+/* C_Logout logs a user out from a token. */ -+CK_PKCS11_FUNCTION_INFO(C_Logout) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession /* the session's handle */ -+); -+#endif -+ -+ -+ -+/* Object management */ -+ -+/* C_CreateObject creates a new object. */ -+CK_PKCS11_FUNCTION_INFO(C_CreateObject) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */ -+ CK_ULONG ulCount, /* attributes in template */ -+ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */ -+); -+#endif -+ -+ -+/* C_CopyObject copies an object, creating a new object for the -+ * copy. */ -+CK_PKCS11_FUNCTION_INFO(C_CopyObject) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_OBJECT_HANDLE hObject, /* the object's handle */ -+ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */ -+ CK_ULONG ulCount, /* attributes in template */ -+ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */ -+); -+#endif -+ -+ -+/* C_DestroyObject destroys an object. */ -+CK_PKCS11_FUNCTION_INFO(C_DestroyObject) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_OBJECT_HANDLE hObject /* the object's handle */ -+); -+#endif -+ -+ -+/* C_GetObjectSize gets the size of an object in bytes. */ -+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_OBJECT_HANDLE hObject, /* the object's handle */ -+ CK_ULONG_PTR pulSize /* receives size of object */ -+); -+#endif -+ -+ -+/* C_GetAttributeValue obtains the value of one or more object -+ * attributes. */ -+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_OBJECT_HANDLE hObject, /* the object's handle */ -+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */ -+ CK_ULONG ulCount /* attributes in template */ -+); -+#endif -+ -+ -+/* C_SetAttributeValue modifies the value of one or more object -+ * attributes */ -+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_OBJECT_HANDLE hObject, /* the object's handle */ -+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */ -+ CK_ULONG ulCount /* attributes in template */ -+); -+#endif -+ -+ -+/* C_FindObjectsInit initializes a search for token and session -+ * objects that match a template. */ -+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ -+ CK_ULONG ulCount /* attrs in search template */ -+); -+#endif -+ -+ -+/* C_FindObjects continues a search for token and session -+ * objects that match a template, obtaining additional object -+ * handles. */ -+CK_PKCS11_FUNCTION_INFO(C_FindObjects) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */ -+ CK_ULONG ulMaxObjectCount, /* max handles to get */ -+ CK_ULONG_PTR pulObjectCount /* actual # returned */ -+); -+#endif -+ -+ -+/* C_FindObjectsFinal finishes a search for token and session -+ * objects. */ -+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession /* the session's handle */ -+); -+#endif -+ -+ -+ -+/* Encryption and decryption */ -+ -+/* C_EncryptInit initializes an encryption operation. */ -+CK_PKCS11_FUNCTION_INFO(C_EncryptInit) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ -+ CK_OBJECT_HANDLE hKey /* handle of encryption key */ -+); -+#endif -+ -+ -+/* C_Encrypt encrypts single-part data. */ -+CK_PKCS11_FUNCTION_INFO(C_Encrypt) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pData, /* the plaintext data */ -+ CK_ULONG ulDataLen, /* bytes of plaintext */ -+ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */ -+ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */ -+); -+#endif -+ -+ -+/* C_EncryptUpdate continues a multiple-part encryption -+ * operation. */ -+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pPart, /* the plaintext data */ -+ CK_ULONG ulPartLen, /* plaintext data len */ -+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ -+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */ -+); -+#endif -+ -+ -+/* C_EncryptFinal finishes a multiple-part encryption -+ * operation. */ -+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session handle */ -+ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */ -+ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */ -+); -+#endif -+ -+ -+/* C_DecryptInit initializes a decryption operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DecryptInit) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ -+ CK_OBJECT_HANDLE hKey /* handle of decryption key */ -+); -+#endif -+ -+ -+/* C_Decrypt decrypts encrypted data in a single part. */ -+CK_PKCS11_FUNCTION_INFO(C_Decrypt) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pEncryptedData, /* ciphertext */ -+ CK_ULONG ulEncryptedDataLen, /* ciphertext length */ -+ CK_BYTE_PTR pData, /* gets plaintext */ -+ CK_ULONG_PTR pulDataLen /* gets p-text size */ -+); -+#endif -+ -+ -+/* C_DecryptUpdate continues a multiple-part decryption -+ * operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pEncryptedPart, /* encrypted data */ -+ CK_ULONG ulEncryptedPartLen, /* input length */ -+ CK_BYTE_PTR pPart, /* gets plaintext */ -+ CK_ULONG_PTR pulPartLen /* p-text size */ -+); -+#endif -+ -+ -+/* C_DecryptFinal finishes a multiple-part decryption -+ * operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pLastPart, /* gets plaintext */ -+ CK_ULONG_PTR pulLastPartLen /* p-text size */ -+); -+#endif -+ -+ -+ -+/* Message digesting */ -+ -+/* C_DigestInit initializes a message-digesting operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DigestInit) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */ -+); -+#endif -+ -+ -+/* C_Digest digests data in a single part. */ -+CK_PKCS11_FUNCTION_INFO(C_Digest) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pData, /* data to be digested */ -+ CK_ULONG ulDataLen, /* bytes of data to digest */ -+ CK_BYTE_PTR pDigest, /* gets the message digest */ -+ CK_ULONG_PTR pulDigestLen /* gets digest length */ -+); -+#endif -+ -+ -+/* C_DigestUpdate continues a multiple-part message-digesting -+ * operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pPart, /* data to be digested */ -+ CK_ULONG ulPartLen /* bytes of data to be digested */ -+); -+#endif -+ -+ -+/* C_DigestKey continues a multi-part message-digesting -+ * operation, by digesting the value of a secret key as part of -+ * the data already digested. */ -+CK_PKCS11_FUNCTION_INFO(C_DigestKey) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_OBJECT_HANDLE hKey /* secret key to digest */ -+); -+#endif -+ -+ -+/* C_DigestFinal finishes a multiple-part message-digesting -+ * operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DigestFinal) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pDigest, /* gets the message digest */ -+ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */ -+); -+#endif -+ -+ -+ -+/* Signing and MACing */ -+ -+/* C_SignInit initializes a signature (private key encryption) -+ * operation, where the signature is (will be) an appendix to -+ * the data, and plaintext cannot be recovered from the -+ *signature. */ -+CK_PKCS11_FUNCTION_INFO(C_SignInit) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ -+ CK_OBJECT_HANDLE hKey /* handle of signature key */ -+); -+#endif -+ -+ -+/* C_Sign signs (encrypts with private key) data in a single -+ * part, where the signature is (will be) an appendix to the -+ * data, and plaintext cannot be recovered from the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_Sign) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pData, /* the data to sign */ -+ CK_ULONG ulDataLen, /* count of bytes to sign */ -+ CK_BYTE_PTR pSignature, /* gets the signature */ -+ CK_ULONG_PTR pulSignatureLen /* gets signature length */ -+); -+#endif -+ -+ -+/* C_SignUpdate continues a multiple-part signature operation, -+ * where the signature is (will be) an appendix to the data, -+ * and plaintext cannot be recovered from the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_SignUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pPart, /* the data to sign */ -+ CK_ULONG ulPartLen /* count of bytes to sign */ -+); -+#endif -+ -+ -+/* C_SignFinal finishes a multiple-part signature operation, -+ * returning the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_SignFinal) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pSignature, /* gets the signature */ -+ CK_ULONG_PTR pulSignatureLen /* gets signature length */ -+); -+#endif -+ -+ -+/* C_SignRecoverInit initializes a signature operation, where -+ * the data can be recovered from the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ -+ CK_OBJECT_HANDLE hKey /* handle of the signature key */ -+); -+#endif -+ -+ -+/* C_SignRecover signs data in a single operation, where the -+ * data can be recovered from the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_SignRecover) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pData, /* the data to sign */ -+ CK_ULONG ulDataLen, /* count of bytes to sign */ -+ CK_BYTE_PTR pSignature, /* gets the signature */ -+ CK_ULONG_PTR pulSignatureLen /* gets signature length */ -+); -+#endif -+ -+ -+ -+/* Verifying signatures and MACs */ -+ -+/* C_VerifyInit initializes a verification operation, where the -+ * signature is an appendix to the data, and plaintext cannot -+ * cannot be recovered from the signature (e.g. DSA). */ -+CK_PKCS11_FUNCTION_INFO(C_VerifyInit) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ -+ CK_OBJECT_HANDLE hKey /* verification key */ -+); -+#endif -+ -+ -+/* C_Verify verifies a signature in a single-part operation, -+ * where the signature is an appendix to the data, and plaintext -+ * cannot be recovered from the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_Verify) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pData, /* signed data */ -+ CK_ULONG ulDataLen, /* length of signed data */ -+ CK_BYTE_PTR pSignature, /* signature */ -+ CK_ULONG ulSignatureLen /* signature length*/ -+); -+#endif -+ -+ -+/* C_VerifyUpdate continues a multiple-part verification -+ * operation, where the signature is an appendix to the data, -+ * and plaintext cannot be recovered from the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pPart, /* signed data */ -+ CK_ULONG ulPartLen /* length of signed data */ -+); -+#endif -+ -+ -+/* C_VerifyFinal finishes a multiple-part verification -+ * operation, checking the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pSignature, /* signature to verify */ -+ CK_ULONG ulSignatureLen /* signature length */ -+); -+#endif -+ -+ -+/* C_VerifyRecoverInit initializes a signature verification -+ * operation, where the data is recovered from the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ -+ CK_OBJECT_HANDLE hKey /* verification key */ -+); -+#endif -+ -+ -+/* C_VerifyRecover verifies a signature in a single-part -+ * operation, where the data is recovered from the signature. */ -+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pSignature, /* signature to verify */ -+ CK_ULONG ulSignatureLen, /* signature length */ -+ CK_BYTE_PTR pData, /* gets signed data */ -+ CK_ULONG_PTR pulDataLen /* gets signed data len */ -+); -+#endif -+ -+ -+ -+/* Dual-function cryptographic operations */ -+ -+/* C_DigestEncryptUpdate continues a multiple-part digesting -+ * and encryption operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pPart, /* the plaintext data */ -+ CK_ULONG ulPartLen, /* plaintext length */ -+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ -+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ -+); -+#endif -+ -+ -+/* C_DecryptDigestUpdate continues a multiple-part decryption and -+ * digesting operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */ -+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */ -+ CK_BYTE_PTR pPart, /* gets plaintext */ -+ CK_ULONG_PTR pulPartLen /* gets plaintext len */ -+); -+#endif -+ -+ -+/* C_SignEncryptUpdate continues a multiple-part signing and -+ * encryption operation. */ -+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pPart, /* the plaintext data */ -+ CK_ULONG ulPartLen, /* plaintext length */ -+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */ -+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */ -+); -+#endif -+ -+ -+/* C_DecryptVerifyUpdate continues a multiple-part decryption and -+ * verify operation. */ -+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */ -+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */ -+ CK_BYTE_PTR pPart, /* gets plaintext */ -+ CK_ULONG_PTR pulPartLen /* gets p-text length */ -+); -+#endif -+ -+ -+ -+/* Key management */ -+ -+/* C_GenerateKey generates a secret key, creating a new key -+ * object. */ -+CK_PKCS11_FUNCTION_INFO(C_GenerateKey) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* key generation mech. */ -+ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */ -+ CK_ULONG ulCount, /* # of attrs in template */ -+ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */ -+); -+#endif -+ -+ -+/* C_GenerateKeyPair generates a public-key/private-key pair, -+ * creating new key objects. */ -+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session -+ * handle */ -+ CK_MECHANISM_PTR pMechanism, /* key-gen -+ * mech. */ -+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template -+ * for pub. -+ * key */ -+ CK_ULONG ulPublicKeyAttributeCount, /* # pub. -+ * attrs. */ -+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template -+ * for priv. -+ * key */ -+ CK_ULONG ulPrivateKeyAttributeCount, /* # priv. -+ * attrs. */ -+ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. -+ * key -+ * handle */ -+ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets -+ * priv. key -+ * handle */ -+); -+#endif -+ -+ -+/* C_WrapKey wraps (i.e., encrypts) a key. */ -+CK_PKCS11_FUNCTION_INFO(C_WrapKey) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */ -+ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */ -+ CK_OBJECT_HANDLE hKey, /* key to be wrapped */ -+ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */ -+ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */ -+); -+#endif -+ -+ -+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new -+ * key object. */ -+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */ -+ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */ -+ CK_BYTE_PTR pWrappedKey, /* the wrapped key */ -+ CK_ULONG ulWrappedKeyLen, /* wrapped key len */ -+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */ -+ CK_ULONG ulAttributeCount, /* template length */ -+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ -+); -+#endif -+ -+ -+/* C_DeriveKey derives a key from a base key, creating a new key -+ * object. */ -+CK_PKCS11_FUNCTION_INFO(C_DeriveKey) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* session's handle */ -+ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */ -+ CK_OBJECT_HANDLE hBaseKey, /* base key */ -+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */ -+ CK_ULONG ulAttributeCount, /* template length */ -+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */ -+); -+#endif -+ -+ -+ -+/* Random number generation */ -+ -+/* C_SeedRandom mixes additional seed material into the token's -+ * random number generator. */ -+CK_PKCS11_FUNCTION_INFO(C_SeedRandom) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR pSeed, /* the seed material */ -+ CK_ULONG ulSeedLen /* length of seed material */ -+); -+#endif -+ -+ -+/* C_GenerateRandom generates random data. */ -+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_BYTE_PTR RandomData, /* receives the random data */ -+ CK_ULONG ulRandomLen /* # of bytes to generate */ -+); -+#endif -+ -+ -+ -+/* Parallel function management */ -+ -+/* C_GetFunctionStatus is a legacy function; it obtains an -+ * updated status of a function running in parallel with an -+ * application. */ -+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession /* the session's handle */ -+); -+#endif -+ -+ -+/* C_CancelFunction is a legacy function; it cancels a function -+ * running in parallel. */ -+CK_PKCS11_FUNCTION_INFO(C_CancelFunction) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_SESSION_HANDLE hSession /* the session's handle */ -+); -+#endif -+ -+ -+ -+/* Functions added in for Cryptoki Version 2.01 or later */ -+ -+/* C_WaitForSlotEvent waits for a slot event (token insertion, -+ * removal, etc.) to occur. */ -+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent) -+#ifdef CK_NEED_ARG_LIST -+( -+ CK_FLAGS flags, /* blocking/nonblocking flag */ -+ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ -+ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */ -+); -+#endif -diff --git a/lib/isc/include/pkcs11/pkcs11t.h b/lib/isc/include/pkcs11/pkcs11t.h -new file mode 100644 -index 0000000..92a80bb ---- /dev/null -+++ b/lib/isc/include/pkcs11/pkcs11t.h -@@ -0,0 +1,1977 @@ -+/* pkcs11t.h include file for PKCS #11. */ -+/* $Revision: 1.2 $ */ -+ -+/* License to copy and use this software is granted provided that it is -+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface -+ * (Cryptoki)" in all material mentioning or referencing this software. -+ -+ * License is also granted to make and use derivative works provided that -+ * such works are identified as "derived from the RSA Security Inc. PKCS #11 -+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or -+ * referencing the derived work. -+ -+ * RSA Security Inc. makes no representations concerning either the -+ * merchantability of this software or the suitability of this software for -+ * any particular purpose. It is provided "as is" without express or implied -+ * warranty of any kind. -+ */ -+ -+/* See top of pkcs11.h for information about the macros that -+ * must be defined and the structure-packing conventions that -+ * must be set before including this file. */ -+ -+#ifndef _PKCS11T_H_ -+#define _PKCS11T_H_ 1 -+ -+#define CRYPTOKI_VERSION_MAJOR 2 -+#define CRYPTOKI_VERSION_MINOR 30 -+#define CRYPTOKI_VERSION_REVISION 0 -+#define CRYPTOKI_VERSION_AMENDMENT 0 -+ -+#define CK_TRUE 1 -+#define CK_FALSE 0 -+ -+#ifndef CK_DISABLE_TRUE_FALSE -+#ifndef FALSE -+#define FALSE CK_FALSE -+#endif -+ -+#ifndef TRUE -+#define TRUE CK_TRUE -+#endif -+#endif -+ -+/* an unsigned 8-bit value */ -+typedef unsigned char CK_BYTE; -+ -+/* an unsigned 8-bit character */ -+typedef CK_BYTE CK_CHAR; -+ -+/* an 8-bit UTF-8 character */ -+typedef CK_BYTE CK_UTF8CHAR; -+ -+/* a BYTE-sized Boolean flag */ -+typedef CK_BYTE CK_BBOOL; -+ -+/* an unsigned value, at least 32 bits long */ -+typedef unsigned long int CK_ULONG; -+ -+/* a signed value, the same size as a CK_ULONG */ -+/* CK_LONG is new for v2.0 */ -+typedef long int CK_LONG; -+ -+/* at least 32 bits; each bit is a Boolean flag */ -+typedef CK_ULONG CK_FLAGS; -+ -+ -+/* some special values for certain CK_ULONG variables */ -+#define CK_UNAVAILABLE_INFORMATION (~0UL) -+#define CK_EFFECTIVELY_INFINITE 0 -+ -+ -+typedef CK_BYTE CK_PTR CK_BYTE_PTR; -+typedef CK_CHAR CK_PTR CK_CHAR_PTR; -+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; -+typedef CK_ULONG CK_PTR CK_ULONG_PTR; -+typedef void CK_PTR CK_VOID_PTR; -+ -+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */ -+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR; -+ -+ -+/* The following value is always invalid if used as a session */ -+/* handle or object handle */ -+#define CK_INVALID_HANDLE 0 -+ -+ -+typedef struct CK_VERSION { -+ CK_BYTE major; /* integer portion of version number */ -+ CK_BYTE minor; /* 1/100ths portion of version number */ -+} CK_VERSION; -+ -+typedef CK_VERSION CK_PTR CK_VERSION_PTR; -+ -+ -+typedef struct CK_INFO { -+ /* manufacturerID and libraryDecription have been changed from -+ * CK_CHAR to CK_UTF8CHAR for v2.10 */ -+ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */ -+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ -+ CK_FLAGS flags; /* must be zero */ -+ -+ /* libraryDescription and libraryVersion are new for v2.0 */ -+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */ -+ CK_VERSION libraryVersion; /* version of library */ -+} CK_INFO; -+ -+typedef CK_INFO CK_PTR CK_INFO_PTR; -+ -+ -+/* CK_NOTIFICATION enumerates the types of notifications that -+ * Cryptoki provides to an application */ -+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG -+ * for v2.0 */ -+typedef CK_ULONG CK_NOTIFICATION; -+#define CKN_SURRENDER 0 -+ -+/* The following notification is new for PKCS #11 v2.20 amendment 3 */ -+#define CKN_OTP_CHANGED 1 -+ -+ -+typedef CK_ULONG CK_SLOT_ID; -+ -+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; -+ -+ -+/* CK_SLOT_INFO provides information about a slot */ -+typedef struct CK_SLOT_INFO { -+ /* slotDescription and manufacturerID have been changed from -+ * CK_CHAR to CK_UTF8CHAR for v2.10 */ -+ CK_UTF8CHAR slotDescription[64]; /* blank padded */ -+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ -+ CK_FLAGS flags; -+ -+ /* hardwareVersion and firmwareVersion are new for v2.0 */ -+ CK_VERSION hardwareVersion; /* version of hardware */ -+ CK_VERSION firmwareVersion; /* version of firmware */ -+} CK_SLOT_INFO; -+ -+/* flags: bit flags that provide capabilities of the slot -+ * Bit Flag Mask Meaning -+ */ -+#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */ -+#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/ -+#define CKF_HW_SLOT 0x00000004 /* hardware slot */ -+ -+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; -+ -+ -+/* CK_TOKEN_INFO provides information about a token */ -+typedef struct CK_TOKEN_INFO { -+ /* label, manufacturerID, and model have been changed from -+ * CK_CHAR to CK_UTF8CHAR for v2.10 */ -+ CK_UTF8CHAR label[32]; /* blank padded */ -+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ -+ CK_UTF8CHAR model[16]; /* blank padded */ -+ CK_CHAR serialNumber[16]; /* blank padded */ -+ CK_FLAGS flags; /* see below */ -+ -+ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount, -+ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been -+ * changed from CK_USHORT to CK_ULONG for v2.0 */ -+ CK_ULONG ulMaxSessionCount; /* max open sessions */ -+ CK_ULONG ulSessionCount; /* sess. now open */ -+ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */ -+ CK_ULONG ulRwSessionCount; /* R/W sess. now open */ -+ CK_ULONG ulMaxPinLen; /* in bytes */ -+ CK_ULONG ulMinPinLen; /* in bytes */ -+ CK_ULONG ulTotalPublicMemory; /* in bytes */ -+ CK_ULONG ulFreePublicMemory; /* in bytes */ -+ CK_ULONG ulTotalPrivateMemory; /* in bytes */ -+ CK_ULONG ulFreePrivateMemory; /* in bytes */ -+ -+ /* hardwareVersion, firmwareVersion, and time are new for -+ * v2.0 */ -+ CK_VERSION hardwareVersion; /* version of hardware */ -+ CK_VERSION firmwareVersion; /* version of firmware */ -+ CK_CHAR utcTime[16]; /* time */ -+} CK_TOKEN_INFO; -+ -+/* The flags parameter is defined as follows: -+ * Bit Flag Mask Meaning -+ */ -+#define CKF_RNG 0x00000001 /* has random # -+ * generator */ -+#define CKF_WRITE_PROTECTED 0x00000002 /* token is -+ * write- -+ * protected */ -+#define CKF_LOGIN_REQUIRED 0x00000004 /* user must -+ * login */ -+#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's -+ * PIN is set */ -+ -+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set, -+ * that means that *every* time the state of cryptographic -+ * operations of a session is successfully saved, all keys -+ * needed to continue those operations are stored in the state */ -+#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020 -+ -+/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means -+ * that the token has some sort of clock. The time on that -+ * clock is returned in the token info structure */ -+#define CKF_CLOCK_ON_TOKEN 0x00000040 -+ -+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is -+ * set, that means that there is some way for the user to login -+ * without sending a PIN through the Cryptoki library itself */ -+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100 -+ -+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true, -+ * that means that a single session with the token can perform -+ * dual simultaneous cryptographic operations (digest and -+ * encrypt; decrypt and digest; sign and encrypt; and decrypt -+ * and sign) */ -+#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 -+ -+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the -+ * token has been initialized using C_InitializeToken or an -+ * equivalent mechanism outside the scope of PKCS #11. -+ * Calling C_InitializeToken when this flag is set will cause -+ * the token to be reinitialized. */ -+#define CKF_TOKEN_INITIALIZED 0x00000400 -+ -+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is -+ * true, the token supports secondary authentication for -+ * private key objects. This flag is deprecated in v2.11 and -+ onwards. */ -+#define CKF_SECONDARY_AUTHENTICATION 0x00000800 -+ -+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an -+ * incorrect user login PIN has been entered at least once -+ * since the last successful authentication. */ -+#define CKF_USER_PIN_COUNT_LOW 0x00010000 -+ -+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true, -+ * supplying an incorrect user PIN will it to become locked. */ -+#define CKF_USER_PIN_FINAL_TRY 0x00020000 -+ -+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the -+ * user PIN has been locked. User login to the token is not -+ * possible. */ -+#define CKF_USER_PIN_LOCKED 0x00040000 -+ -+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, -+ * the user PIN value is the default value set by token -+ * initialization or manufacturing, or the PIN has been -+ * expired by the card. */ -+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 -+ -+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an -+ * incorrect SO login PIN has been entered at least once since -+ * the last successful authentication. */ -+#define CKF_SO_PIN_COUNT_LOW 0x00100000 -+ -+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true, -+ * supplying an incorrect SO PIN will it to become locked. */ -+#define CKF_SO_PIN_FINAL_TRY 0x00200000 -+ -+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO -+ * PIN has been locked. SO login to the token is not possible. -+ */ -+#define CKF_SO_PIN_LOCKED 0x00400000 -+ -+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, -+ * the SO PIN value is the default value set by token -+ * initialization or manufacturing, or the PIN has been -+ * expired by the card. */ -+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 -+ -+/* CKF_ERROR_STATE if new for v2.30. If it is true, -+ * the token failed a FIPS 140-2 self-test and -+ * entered an error state. */ -+#define CKF_ERROR_STATE 0x01000000 -+ -+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; -+ -+ -+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that -+ * identifies a session */ -+typedef CK_ULONG CK_SESSION_HANDLE; -+ -+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; -+ -+ -+/* CK_USER_TYPE enumerates the types of Cryptoki users */ -+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for -+ * v2.0 */ -+typedef CK_ULONG CK_USER_TYPE; -+/* Security Officer */ -+#define CKU_SO 0 -+/* Normal user */ -+#define CKU_USER 1 -+/* Context specific (added in v2.20) */ -+#define CKU_CONTEXT_SPECIFIC 2 -+ -+/* CK_STATE enumerates the session states */ -+/* CK_STATE has been changed from an enum to a CK_ULONG for -+ * v2.0 */ -+typedef CK_ULONG CK_STATE; -+#define CKS_RO_PUBLIC_SESSION 0 -+#define CKS_RO_USER_FUNCTIONS 1 -+#define CKS_RW_PUBLIC_SESSION 2 -+#define CKS_RW_USER_FUNCTIONS 3 -+#define CKS_RW_SO_FUNCTIONS 4 -+ -+ -+/* CK_SESSION_INFO provides information about a session */ -+typedef struct CK_SESSION_INFO { -+ CK_SLOT_ID slotID; -+ CK_STATE state; -+ CK_FLAGS flags; /* see below */ -+ -+ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for -+ * v2.0 */ -+ CK_ULONG ulDeviceError; /* device-dependent error code */ -+} CK_SESSION_INFO; -+ -+/* The flags are defined in the following table: -+ * Bit Flag Mask Meaning -+ */ -+#define CKF_RW_SESSION 0x00000002 /* session is r/w */ -+#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */ -+ -+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR; -+ -+ -+/* CK_OBJECT_HANDLE is a token-specific identifier for an -+ * object */ -+typedef CK_ULONG CK_OBJECT_HANDLE; -+ -+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; -+ -+ -+/* CK_OBJECT_CLASS is a value that identifies the classes (or -+ * types) of objects that Cryptoki recognizes. It is defined -+ * as follows: */ -+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for -+ * v2.0 */ -+typedef CK_ULONG CK_OBJECT_CLASS; -+ -+/* The following classes of objects are defined: */ -+/* CKO_HW_FEATURE is new for v2.10 */ -+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */ -+/* CKO_MECHANISM is new for v2.20 */ -+#define CKO_DATA 0x00000000 -+#define CKO_CERTIFICATE 0x00000001 -+#define CKO_PUBLIC_KEY 0x00000002 -+#define CKO_PRIVATE_KEY 0x00000003 -+#define CKO_SECRET_KEY 0x00000004 -+#define CKO_HW_FEATURE 0x00000005 -+#define CKO_DOMAIN_PARAMETERS 0x00000006 -+#define CKO_MECHANISM 0x00000007 -+ -+/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */ -+#define CKO_OTP_KEY 0x00000008 -+ -+#define CKO_VENDOR_DEFINED 0x80000000 -+ -+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; -+ -+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a -+ * value that identifies the hardware feature type of an object -+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ -+typedef CK_ULONG CK_HW_FEATURE_TYPE; -+ -+/* The following hardware feature types are defined */ -+/* CKH_USER_INTERFACE is new for v2.20 */ -+#define CKH_MONOTONIC_COUNTER 0x00000001 -+#define CKH_CLOCK 0x00000002 -+#define CKH_USER_INTERFACE 0x00000003 -+#define CKH_VENDOR_DEFINED 0x80000000 -+ -+/* CK_KEY_TYPE is a value that identifies a key type */ -+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ -+typedef CK_ULONG CK_KEY_TYPE; -+ -+/* the following key types are defined: */ -+#define CKK_RSA 0x00000000 -+#define CKK_DSA 0x00000001 -+#define CKK_DH 0x00000002 -+ -+/* CKK_ECDSA and CKK_KEA are new for v2.0 */ -+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */ -+#define CKK_ECDSA 0x00000003 -+#define CKK_EC 0x00000003 -+#define CKK_X9_42_DH 0x00000004 -+#define CKK_KEA 0x00000005 -+ -+#define CKK_GENERIC_SECRET 0x00000010 -+#define CKK_RC2 0x00000011 -+#define CKK_RC4 0x00000012 -+#define CKK_DES 0x00000013 -+#define CKK_DES2 0x00000014 -+#define CKK_DES3 0x00000015 -+ -+/* all these key types are new for v2.0 */ -+#define CKK_CAST 0x00000016 -+#define CKK_CAST3 0x00000017 -+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */ -+#define CKK_CAST5 0x00000018 -+#define CKK_CAST128 0x00000018 -+#define CKK_RC5 0x00000019 -+#define CKK_IDEA 0x0000001A -+#define CKK_SKIPJACK 0x0000001B -+#define CKK_BATON 0x0000001C -+#define CKK_JUNIPER 0x0000001D -+#define CKK_CDMF 0x0000001E -+#define CKK_AES 0x0000001F -+ -+/* BlowFish and TwoFish are new for v2.20 */ -+#define CKK_BLOWFISH 0x00000020 -+#define CKK_TWOFISH 0x00000021 -+ -+/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */ -+#define CKK_SECURID 0x00000022 -+#define CKK_HOTP 0x00000023 -+#define CKK_ACTI 0x00000024 -+ -+/* Camellia is new for PKCS #11 v2.20 amendment 3 */ -+#define CKK_CAMELLIA 0x00000025 -+/* ARIA is new for PKCS #11 v2.20 amendment 3 */ -+#define CKK_ARIA 0x00000026 -+ -+/* From PKCS #11 v2.20 amendment 4 draft 2 */ -+#define CKK_MD5_HMAC 0x00000027 -+#define CKK_SHA_1_HMAC 0x00000028 -+#define CKK_RIPEMD128_HMAC 0x00000029 -+#define CKK_RIPEMD160_HMAC 0x0000002A -+#define CKK_SHA256_HMAC 0x0000002B -+#define CKK_SHA384_HMAC 0x0000002C -+#define CKK_SHA512_HMAC 0x0000002D -+#define CKK_SHA224_HMAC 0x0000002E -+ -+/* From PKCS #11 v2.30 */ -+#define CKK_SEED 0x0000002F -+#define CKK_GOSTR3410 0x00000030 -+#define CKK_GOSTR3411 0x00000031 -+#define CKK_GOST28147 0x00000032 -+ -+#define CKK_VENDOR_DEFINED 0x80000000 -+ -+ -+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate -+ * type */ -+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG -+ * for v2.0 */ -+typedef CK_ULONG CK_CERTIFICATE_TYPE; -+ -+/* The following certificate types are defined: */ -+/* CKC_X_509_ATTR_CERT is new for v2.10 */ -+/* CKC_WTLS is new for v2.20 */ -+#define CKC_X_509 0x00000000 -+#define CKC_X_509_ATTR_CERT 0x00000001 -+#define CKC_WTLS 0x00000002 -+#define CKC_VENDOR_DEFINED 0x80000000 -+ -+ -+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute -+ * type */ -+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for -+ * v2.0 */ -+typedef CK_ULONG CK_ATTRIBUTE_TYPE; -+ -+/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which -+ consists of an array of values. */ -+#define CKF_ARRAY_ATTRIBUTE 0x40000000 -+ -+/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 -+ and relates to the CKA_OTP_FORMAT attribute */ -+#define CK_OTP_FORMAT_DECIMAL 0 -+#define CK_OTP_FORMAT_HEXADECIMAL 1 -+#define CK_OTP_FORMAT_ALPHANUMERIC 2 -+#define CK_OTP_FORMAT_BINARY 3 -+ -+/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 -+ and relates to the CKA_OTP_..._REQUIREMENT attributes */ -+#define CK_OTP_PARAM_IGNORED 0 -+#define CK_OTP_PARAM_OPTIONAL 1 -+#define CK_OTP_PARAM_MANDATORY 2 -+ -+/* The following attribute types are defined: */ -+#define CKA_CLASS 0x00000000 -+#define CKA_TOKEN 0x00000001 -+#define CKA_PRIVATE 0x00000002 -+#define CKA_LABEL 0x00000003 -+#define CKA_APPLICATION 0x00000010 -+#define CKA_VALUE 0x00000011 -+ -+/* CKA_OBJECT_ID is new for v2.10 */ -+#define CKA_OBJECT_ID 0x00000012 -+ -+#define CKA_CERTIFICATE_TYPE 0x00000080 -+#define CKA_ISSUER 0x00000081 -+#define CKA_SERIAL_NUMBER 0x00000082 -+ -+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new -+ * for v2.10 */ -+#define CKA_AC_ISSUER 0x00000083 -+#define CKA_OWNER 0x00000084 -+#define CKA_ATTR_TYPES 0x00000085 -+ -+/* CKA_TRUSTED is new for v2.11 */ -+#define CKA_TRUSTED 0x00000086 -+ -+/* CKA_CERTIFICATE_CATEGORY ... -+ * CKA_CHECK_VALUE are new for v2.20 */ -+#define CKA_CERTIFICATE_CATEGORY 0x00000087 -+#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088 -+#define CKA_URL 0x00000089 -+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A -+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B -+/* One from v2.30? */ -+#define CKA_NAME_HASH_ALGORITH 0x0000008C -+#define CKA_CHECK_VALUE 0x00000090 -+ -+#define CKA_KEY_TYPE 0x00000100 -+#define CKA_SUBJECT 0x00000101 -+#define CKA_ID 0x00000102 -+#define CKA_SENSITIVE 0x00000103 -+#define CKA_ENCRYPT 0x00000104 -+#define CKA_DECRYPT 0x00000105 -+#define CKA_WRAP 0x00000106 -+#define CKA_UNWRAP 0x00000107 -+#define CKA_SIGN 0x00000108 -+#define CKA_SIGN_RECOVER 0x00000109 -+#define CKA_VERIFY 0x0000010A -+#define CKA_VERIFY_RECOVER 0x0000010B -+#define CKA_DERIVE 0x0000010C -+#define CKA_START_DATE 0x00000110 -+#define CKA_END_DATE 0x00000111 -+#define CKA_MODULUS 0x00000120 -+#define CKA_MODULUS_BITS 0x00000121 -+#define CKA_PUBLIC_EXPONENT 0x00000122 -+#define CKA_PRIVATE_EXPONENT 0x00000123 -+#define CKA_PRIME_1 0x00000124 -+#define CKA_PRIME_2 0x00000125 -+#define CKA_EXPONENT_1 0x00000126 -+#define CKA_EXPONENT_2 0x00000127 -+#define CKA_COEFFICIENT 0x00000128 -+#define CKA_PRIME 0x00000130 -+#define CKA_SUBPRIME 0x00000131 -+#define CKA_BASE 0x00000132 -+ -+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ -+#define CKA_PRIME_BITS 0x00000133 -+#define CKA_SUBPRIME_BITS 0x00000134 -+#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS -+/* (To retain backwards-compatibility) */ -+ -+#define CKA_VALUE_BITS 0x00000160 -+#define CKA_VALUE_LEN 0x00000161 -+ -+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, -+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS, -+ * and CKA_EC_POINT are new for v2.0 */ -+#define CKA_EXTRACTABLE 0x00000162 -+#define CKA_LOCAL 0x00000163 -+#define CKA_NEVER_EXTRACTABLE 0x00000164 -+#define CKA_ALWAYS_SENSITIVE 0x00000165 -+ -+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */ -+#define CKA_KEY_GEN_MECHANISM 0x00000166 -+ -+#define CKA_MODIFIABLE 0x00000170 -+ -+/* From v2.30? */ -+#define CKA_COPYABLE 0x00000171 -+ -+/* CKA_ECDSA_PARAMS is deprecated in v2.11, -+ * CKA_EC_PARAMS is preferred. */ -+#define CKA_ECDSA_PARAMS 0x00000180 -+#define CKA_EC_PARAMS 0x00000180 -+ -+#define CKA_EC_POINT 0x00000181 -+ -+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, -+ * are new for v2.10. Deprecated in v2.11 and onwards. */ -+#define CKA_SECONDARY_AUTH 0x00000200 -+#define CKA_AUTH_PIN_FLAGS 0x00000201 -+ -+/* CKA_ALWAYS_AUTHENTICATE ... -+ * CKA_UNWRAP_TEMPLATE are new for v2.20 */ -+#define CKA_ALWAYS_AUTHENTICATE 0x00000202 -+ -+#define CKA_WRAP_WITH_TRUSTED 0x00000210 -+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211) -+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212) -+ -+/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */ -+#define CKA_OTP_FORMAT 0x00000220 -+#define CKA_OTP_LENGTH 0x00000221 -+#define CKA_OTP_TIME_INTERVAL 0x00000222 -+#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223 -+#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224 -+#define CKA_OTP_TIME_REQUIREMENT 0x00000225 -+#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226 -+#define CKA_OTP_PIN_REQUIREMENT 0x00000227 -+#define CKA_OTP_COUNTER 0x0000022E -+#define CKA_OTP_TIME 0x0000022F -+#define CKA_OTP_USER_IDENTIFIER 0x0000022A -+#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B -+#define CKA_OTP_SERVICE_LOGO 0x0000022C -+#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D -+ -+/* CKA_GOST... */ -+#define CKA_GOSTR3410_PARAMS 0x00000250 -+#define CKA_GOSTR3411_PARAMS 0x00000251 -+#define CKA_GOST28147_PARAMS 0x00000252 -+ -+/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET -+ * are new for v2.10 */ -+#define CKA_HW_FEATURE_TYPE 0x00000300 -+#define CKA_RESET_ON_INIT 0x00000301 -+#define CKA_HAS_RESET 0x00000302 -+ -+/* The following attributes are new for v2.20 */ -+#define CKA_PIXEL_X 0x00000400 -+#define CKA_PIXEL_Y 0x00000401 -+#define CKA_RESOLUTION 0x00000402 -+#define CKA_CHAR_ROWS 0x00000403 -+#define CKA_CHAR_COLUMNS 0x00000404 -+#define CKA_COLOR 0x00000405 -+#define CKA_BITS_PER_PIXEL 0x00000406 -+#define CKA_CHAR_SETS 0x00000480 -+#define CKA_ENCODING_METHODS 0x00000481 -+#define CKA_MIME_TYPES 0x00000482 -+#define CKA_MECHANISM_TYPE 0x00000500 -+#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501 -+#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502 -+#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503 -+#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600) -+/* From v2.30? */ -+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211) -+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212) -+#define CKA_DERIVE_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000213) -+ -+#define CKA_VENDOR_DEFINED 0x80000000 -+ -+/* CK_ATTRIBUTE is a structure that includes the type, length -+ * and value of an attribute */ -+typedef struct CK_ATTRIBUTE { -+ CK_ATTRIBUTE_TYPE type; -+ CK_VOID_PTR pValue; -+ -+ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */ -+ CK_ULONG ulValueLen; /* in bytes */ -+} CK_ATTRIBUTE; -+ -+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR; -+ -+ -+/* CK_DATE is a structure that defines a date */ -+typedef struct CK_DATE{ -+ CK_CHAR year[4]; /* the year ("1900" - "9999") */ -+ CK_CHAR month[2]; /* the month ("01" - "12") */ -+ CK_CHAR day[2]; /* the day ("01" - "31") */ -+} CK_DATE; -+ -+ -+/* CK_MECHANISM_TYPE is a value that identifies a mechanism -+ * type */ -+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for -+ * v2.0 */ -+typedef CK_ULONG CK_MECHANISM_TYPE; -+ -+/* the following mechanism types are defined: */ -+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 -+#define CKM_RSA_PKCS 0x00000001 -+#define CKM_RSA_9796 0x00000002 -+#define CKM_RSA_X_509 0x00000003 -+ -+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS -+ * are new for v2.0. They are mechanisms which hash and sign */ -+#define CKM_MD2_RSA_PKCS 0x00000004 -+#define CKM_MD5_RSA_PKCS 0x00000005 -+#define CKM_SHA1_RSA_PKCS 0x00000006 -+ -+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and -+ * CKM_RSA_PKCS_OAEP are new for v2.10 */ -+#define CKM_RIPEMD128_RSA_PKCS 0x00000007 -+#define CKM_RIPEMD160_RSA_PKCS 0x00000008 -+#define CKM_RSA_PKCS_OAEP 0x00000009 -+ -+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31, -+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */ -+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A -+#define CKM_RSA_X9_31 0x0000000B -+#define CKM_SHA1_RSA_X9_31 0x0000000C -+#define CKM_RSA_PKCS_PSS 0x0000000D -+#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E -+ -+#define CKM_DSA_KEY_PAIR_GEN 0x00000010 -+#define CKM_DSA 0x00000011 -+#define CKM_DSA_SHA1 0x00000012 -+/* Other DSAs */ -+#define CKM_DSA_SHA224 0x00000013 -+#define CKM_DSA_SHA256 0x00000014 -+#define CKM_DSA_SHA384 0x00000015 -+#define CKM_DSA_SHA512 0x00000016 -+ -+#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 -+#define CKM_DH_PKCS_DERIVE 0x00000021 -+ -+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, -+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for -+ * v2.11 */ -+#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030 -+#define CKM_X9_42_DH_DERIVE 0x00000031 -+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 -+#define CKM_X9_42_MQV_DERIVE 0x00000033 -+ -+/* CKM_SHA256/384/512 are new for v2.20 */ -+#define CKM_SHA256_RSA_PKCS 0x00000040 -+#define CKM_SHA384_RSA_PKCS 0x00000041 -+#define CKM_SHA512_RSA_PKCS 0x00000042 -+#define CKM_SHA256_RSA_PKCS_PSS 0x00000043 -+#define CKM_SHA384_RSA_PKCS_PSS 0x00000044 -+#define CKM_SHA512_RSA_PKCS_PSS 0x00000045 -+ -+/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */ -+#define CKM_SHA224_RSA_PKCS 0x00000046 -+#define CKM_SHA224_RSA_PKCS_PSS 0x00000047 -+ -+#define CKM_RC2_KEY_GEN 0x00000100 -+#define CKM_RC2_ECB 0x00000101 -+#define CKM_RC2_CBC 0x00000102 -+#define CKM_RC2_MAC 0x00000103 -+ -+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */ -+#define CKM_RC2_MAC_GENERAL 0x00000104 -+#define CKM_RC2_CBC_PAD 0x00000105 -+ -+#define CKM_RC4_KEY_GEN 0x00000110 -+#define CKM_RC4 0x00000111 -+#define CKM_DES_KEY_GEN 0x00000120 -+#define CKM_DES_ECB 0x00000121 -+#define CKM_DES_CBC 0x00000122 -+#define CKM_DES_MAC 0x00000123 -+ -+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */ -+#define CKM_DES_MAC_GENERAL 0x00000124 -+#define CKM_DES_CBC_PAD 0x00000125 -+ -+#define CKM_DES2_KEY_GEN 0x00000130 -+#define CKM_DES3_KEY_GEN 0x00000131 -+#define CKM_DES3_ECB 0x00000132 -+#define CKM_DES3_CBC 0x00000133 -+#define CKM_DES3_MAC 0x00000134 -+ -+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN, -+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC, -+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0, -+ * CKM_DES3_CMAC_GENERAL and CKM_DES3_CMAC are from v2.30? */ -+#define CKM_DES3_MAC_GENERAL 0x00000135 -+#define CKM_DES3_CBC_PAD 0x00000136 -+#define CKM_DES3_CMAC_GENERAL 0x00000137 -+#define CKM_DES3_CMAC 0x00000138 -+#define CKM_CDMF_KEY_GEN 0x00000140 -+#define CKM_CDMF_ECB 0x00000141 -+#define CKM_CDMF_CBC 0x00000142 -+#define CKM_CDMF_MAC 0x00000143 -+#define CKM_CDMF_MAC_GENERAL 0x00000144 -+#define CKM_CDMF_CBC_PAD 0x00000145 -+ -+/* the following four DES mechanisms are new for v2.20 */ -+#define CKM_DES_OFB64 0x00000150 -+#define CKM_DES_OFB8 0x00000151 -+#define CKM_DES_CFB64 0x00000152 -+#define CKM_DES_CFB8 0x00000153 -+ -+#define CKM_MD2 0x00000200 -+ -+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ -+#define CKM_MD2_HMAC 0x00000201 -+#define CKM_MD2_HMAC_GENERAL 0x00000202 -+ -+#define CKM_MD5 0x00000210 -+ -+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */ -+#define CKM_MD5_HMAC 0x00000211 -+#define CKM_MD5_HMAC_GENERAL 0x00000212 -+ -+#define CKM_SHA_1 0x00000220 -+ -+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */ -+#define CKM_SHA_1_HMAC 0x00000221 -+#define CKM_SHA_1_HMAC_GENERAL 0x00000222 -+ -+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, -+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, -+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ -+#define CKM_RIPEMD128 0x00000230 -+#define CKM_RIPEMD128_HMAC 0x00000231 -+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232 -+#define CKM_RIPEMD160 0x00000240 -+#define CKM_RIPEMD160_HMAC 0x00000241 -+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 -+ -+/* CKM_SHA256/384/512 are new for v2.20 */ -+#define CKM_SHA256 0x00000250 -+#define CKM_SHA256_HMAC 0x00000251 -+#define CKM_SHA256_HMAC_GENERAL 0x00000252 -+ -+/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ -+#define CKM_SHA224 0x00000255 -+#define CKM_SHA224_HMAC 0x00000256 -+#define CKM_SHA224_HMAC_GENERAL 0x00000257 -+ -+#define CKM_SHA384 0x00000260 -+#define CKM_SHA384_HMAC 0x00000261 -+#define CKM_SHA384_HMAC_GENERAL 0x00000262 -+#define CKM_SHA512 0x00000270 -+#define CKM_SHA512_HMAC 0x00000271 -+#define CKM_SHA512_HMAC_GENERAL 0x00000272 -+ -+/* SecurID is new for PKCS #11 v2.20 amendment 1 */ -+#define CKM_SECURID_KEY_GEN 0x00000280 -+#define CKM_SECURID 0x00000282 -+ -+/* HOTP is new for PKCS #11 v2.20 amendment 1 */ -+#define CKM_HOTP_KEY_GEN 0x00000290 -+#define CKM_HOTP 0x00000291 -+ -+/* ACTI is new for PKCS #11 v2.20 amendment 1 */ -+#define CKM_ACTI 0x000002A0 -+#define CKM_ACTI_KEY_GEN 0x000002A1 -+ -+/* All of the following mechanisms are new for v2.0 */ -+/* Note that CAST128 and CAST5 are the same algorithm */ -+#define CKM_CAST_KEY_GEN 0x00000300 -+#define CKM_CAST_ECB 0x00000301 -+#define CKM_CAST_CBC 0x00000302 -+#define CKM_CAST_MAC 0x00000303 -+#define CKM_CAST_MAC_GENERAL 0x00000304 -+#define CKM_CAST_CBC_PAD 0x00000305 -+#define CKM_CAST3_KEY_GEN 0x00000310 -+#define CKM_CAST3_ECB 0x00000311 -+#define CKM_CAST3_CBC 0x00000312 -+#define CKM_CAST3_MAC 0x00000313 -+#define CKM_CAST3_MAC_GENERAL 0x00000314 -+#define CKM_CAST3_CBC_PAD 0x00000315 -+#define CKM_CAST5_KEY_GEN 0x00000320 -+#define CKM_CAST128_KEY_GEN 0x00000320 -+#define CKM_CAST5_ECB 0x00000321 -+#define CKM_CAST128_ECB 0x00000321 -+#define CKM_CAST5_CBC 0x00000322 -+#define CKM_CAST128_CBC 0x00000322 -+#define CKM_CAST5_MAC 0x00000323 -+#define CKM_CAST128_MAC 0x00000323 -+#define CKM_CAST5_MAC_GENERAL 0x00000324 -+#define CKM_CAST128_MAC_GENERAL 0x00000324 -+#define CKM_CAST5_CBC_PAD 0x00000325 -+#define CKM_CAST128_CBC_PAD 0x00000325 -+#define CKM_RC5_KEY_GEN 0x00000330 -+#define CKM_RC5_ECB 0x00000331 -+#define CKM_RC5_CBC 0x00000332 -+#define CKM_RC5_MAC 0x00000333 -+#define CKM_RC5_MAC_GENERAL 0x00000334 -+#define CKM_RC5_CBC_PAD 0x00000335 -+#define CKM_IDEA_KEY_GEN 0x00000340 -+#define CKM_IDEA_ECB 0x00000341 -+#define CKM_IDEA_CBC 0x00000342 -+#define CKM_IDEA_MAC 0x00000343 -+#define CKM_IDEA_MAC_GENERAL 0x00000344 -+#define CKM_IDEA_CBC_PAD 0x00000345 -+#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350 -+#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360 -+#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362 -+#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363 -+#define CKM_XOR_BASE_AND_DATA 0x00000364 -+#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365 -+#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 -+#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 -+#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 -+ -+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, -+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and -+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */ -+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 -+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 -+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 -+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 -+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 -+ -+/* CKM_TLS_PRF is new for v2.20 */ -+#define CKM_TLS_PRF 0x00000378 -+ -+#define CKM_SSL3_MD5_MAC 0x00000380 -+#define CKM_SSL3_SHA1_MAC 0x00000381 -+#define CKM_MD5_KEY_DERIVATION 0x00000390 -+#define CKM_MD2_KEY_DERIVATION 0x00000391 -+#define CKM_SHA1_KEY_DERIVATION 0x00000392 -+ -+/* CKM_SHA256/384/512 are new for v2.20 */ -+#define CKM_SHA256_KEY_DERIVATION 0x00000393 -+#define CKM_SHA384_KEY_DERIVATION 0x00000394 -+#define CKM_SHA512_KEY_DERIVATION 0x00000395 -+ -+/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */ -+#define CKM_SHA224_KEY_DERIVATION 0x00000396 -+ -+#define CKM_PBE_MD2_DES_CBC 0x000003A0 -+#define CKM_PBE_MD5_DES_CBC 0x000003A1 -+#define CKM_PBE_MD5_CAST_CBC 0x000003A2 -+#define CKM_PBE_MD5_CAST3_CBC 0x000003A3 -+#define CKM_PBE_MD5_CAST5_CBC 0x000003A4 -+#define CKM_PBE_MD5_CAST128_CBC 0x000003A4 -+#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5 -+#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5 -+#define CKM_PBE_SHA1_RC4_128 0x000003A6 -+#define CKM_PBE_SHA1_RC4_40 0x000003A7 -+#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8 -+#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 -+#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA -+#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB -+ -+/* CKM_PKCS5_PBKD2 is new for v2.10 */ -+#define CKM_PKCS5_PBKD2 0x000003B0 -+ -+#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 -+ -+/* WTLS mechanisms are new for v2.20 */ -+#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0 -+#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1 -+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2 -+#define CKM_WTLS_PRF 0x000003D3 -+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4 -+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5 -+ -+#define CKM_KEY_WRAP_LYNKS 0x00000400 -+#define CKM_KEY_WRAP_SET_OAEP 0x00000401 -+ -+/* CKM_CMS_SIG is new for v2.20 */ -+#define CKM_CMS_SIG 0x00000500 -+ -+/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */ -+#define CKM_KIP_DERIVE 0x00000510 -+#define CKM_KIP_WRAP 0x00000511 -+#define CKM_KIP_MAC 0x00000512 -+ -+/* Camellia is new for PKCS #11 v2.20 amendment 3 */ -+#define CKM_CAMELLIA_KEY_GEN 0x00000550 -+#define CKM_CAMELLIA_ECB 0x00000551 -+#define CKM_CAMELLIA_CBC 0x00000552 -+#define CKM_CAMELLIA_MAC 0x00000553 -+#define CKM_CAMELLIA_MAC_GENERAL 0x00000554 -+#define CKM_CAMELLIA_CBC_PAD 0x00000555 -+#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556 -+#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557 -+#define CKM_CAMELLIA_CTR 0x00000558 -+ -+/* ARIA is new for PKCS #11 v2.20 amendment 3 */ -+#define CKM_ARIA_KEY_GEN 0x00000560 -+#define CKM_ARIA_ECB 0x00000561 -+#define CKM_ARIA_CBC 0x00000562 -+#define CKM_ARIA_MAC 0x00000563 -+#define CKM_ARIA_MAC_GENERAL 0x00000564 -+#define CKM_ARIA_CBC_PAD 0x00000565 -+#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566 -+#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567 -+ -+/* SEED is new from PKCS #11 v2.30? */ -+#define CKM_SEED_KEY_GEN 0x00000650 -+#define CKM_SEED_ECB 0x00000651 -+#define CKM_SEED_CBC 0x00000652 -+#define CKM_SEED_MAC 0x00000653 -+#define CKM_SEED_MAC_GENERAL 0x00000654 -+#define CKM_SEED_CBC_PAD 0x00000655 -+#define CKM_SEED_ECB_ENCRYPT_DATA 0x00000656 -+#define CKM_SEED_CBC_ENCRYPT_DATA 0x00000657 -+ -+/* Fortezza mechanisms */ -+#define CKM_SKIPJACK_KEY_GEN 0x00001000 -+#define CKM_SKIPJACK_ECB64 0x00001001 -+#define CKM_SKIPJACK_CBC64 0x00001002 -+#define CKM_SKIPJACK_OFB64 0x00001003 -+#define CKM_SKIPJACK_CFB64 0x00001004 -+#define CKM_SKIPJACK_CFB32 0x00001005 -+#define CKM_SKIPJACK_CFB16 0x00001006 -+#define CKM_SKIPJACK_CFB8 0x00001007 -+#define CKM_SKIPJACK_WRAP 0x00001008 -+#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009 -+#define CKM_SKIPJACK_RELAYX 0x0000100a -+#define CKM_KEA_KEY_PAIR_GEN 0x00001010 -+#define CKM_KEA_KEY_DERIVE 0x00001011 -+#define CKM_FORTEZZA_TIMESTAMP 0x00001020 -+#define CKM_BATON_KEY_GEN 0x00001030 -+#define CKM_BATON_ECB128 0x00001031 -+#define CKM_BATON_ECB96 0x00001032 -+#define CKM_BATON_CBC128 0x00001033 -+#define CKM_BATON_COUNTER 0x00001034 -+#define CKM_BATON_SHUFFLE 0x00001035 -+#define CKM_BATON_WRAP 0x00001036 -+ -+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11, -+ * CKM_EC_KEY_PAIR_GEN is preferred */ -+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 -+#define CKM_EC_KEY_PAIR_GEN 0x00001040 -+ -+#define CKM_ECDSA 0x00001041 -+#define CKM_ECDSA_SHA1 0x00001042 -+ -+/* From v2.30? */ -+#define CKM_ECDSA_SHA224 0x00001043 -+#define CKM_ECDSA_SHA256 0x00001044 -+#define CKM_ECDSA_SHA384 0x00001045 -+#define CKM_ECDSA_SHA512 0x00001046 -+ -+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE -+ * are new for v2.11 */ -+#define CKM_ECDH1_DERIVE 0x00001050 -+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 -+#define CKM_ECMQV_DERIVE 0x00001052 -+ -+#define CKM_JUNIPER_KEY_GEN 0x00001060 -+#define CKM_JUNIPER_ECB128 0x00001061 -+#define CKM_JUNIPER_CBC128 0x00001062 -+#define CKM_JUNIPER_COUNTER 0x00001063 -+#define CKM_JUNIPER_SHUFFLE 0x00001064 -+#define CKM_JUNIPER_WRAP 0x00001065 -+#define CKM_FASTHASH 0x00001070 -+ -+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC, -+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN, -+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are -+ * new for v2.11 */ -+#define CKM_AES_KEY_GEN 0x00001080 -+#define CKM_AES_ECB 0x00001081 -+#define CKM_AES_CBC 0x00001082 -+#define CKM_AES_MAC 0x00001083 -+#define CKM_AES_MAC_GENERAL 0x00001084 -+#define CKM_AES_CBC_PAD 0x00001085 -+ -+/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */ -+#define CKM_AES_CTR 0x00001086 -+ -+/* Missing CKM_AES_GCM and co! */ -+ -+/* BlowFish and TwoFish are new for v2.20 */ -+#define CKM_BLOWFISH_KEY_GEN 0x00001090 -+#define CKM_BLOWFISH_CBC 0x00001091 -+#define CKM_TWOFISH_KEY_GEN 0x00001092 -+#define CKM_TWOFISH_CBC 0x00001093 -+ -+ -+/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */ -+#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100 -+#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101 -+#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102 -+#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103 -+#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104 -+#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105 -+ -+/* GOST mechanism from v2.30? */ -+#define CKM_GOSTR3410_KEY_PAIR_GEN 0x00001200 -+#define CKM_GOSTR3410 0x00001201 -+#define CKM_GOSTR3410_WITH_GOSTR3411 0x00001202 -+#define CKM_GOSTR3410_KEY_WRAP 0x00001203 -+#define CKM_GOSTR3410_DERIVE 0x00001204 -+#define CKM_GOSTR3411 0x00001210 -+#define CKM_GOSTR3411_HMAC 0x00001211 -+#define CKM_GOST28147_KEY_GEN 0x00001220 -+#define CKM_GOST28147_ECB 0x00001221 -+#define CKM_GOST28147 0x00001222 -+#define CKM_GOST28147_MAC 0x00001223 -+#define CKM_GOST28147_KEY_WRAP 0x00001224 -+ -+#define CKM_DSA_PARAMETER_GEN 0x00002000 -+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 -+#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002 -+ -+/* Missing AES_OFB and co, and RSA_PKCS 1_1 */ -+ -+#define CKM_VENDOR_DEFINED 0x80000000 -+ -+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; -+ -+ -+/* CK_MECHANISM is a structure that specifies a particular -+ * mechanism */ -+typedef struct CK_MECHANISM { -+ CK_MECHANISM_TYPE mechanism; -+ CK_VOID_PTR pParameter; -+ -+ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for -+ * v2.0 */ -+ CK_ULONG ulParameterLen; /* in bytes */ -+} CK_MECHANISM; -+ -+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR; -+ -+ -+/* CK_MECHANISM_INFO provides information about a particular -+ * mechanism */ -+typedef struct CK_MECHANISM_INFO { -+ CK_ULONG ulMinKeySize; -+ CK_ULONG ulMaxKeySize; -+ CK_FLAGS flags; -+} CK_MECHANISM_INFO; -+ -+/* The flags are defined as follows: -+ * Bit Flag Mask Meaning */ -+#define CKF_HW 0x00000001 /* performed by HW */ -+ -+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN, -+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER, -+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, -+ * and CKF_DERIVE are new for v2.0. They specify whether or not -+ * a mechanism can be used for a particular task */ -+#define CKF_ENCRYPT 0x00000100 -+#define CKF_DECRYPT 0x00000200 -+#define CKF_DIGEST 0x00000400 -+#define CKF_SIGN 0x00000800 -+#define CKF_SIGN_RECOVER 0x00001000 -+#define CKF_VERIFY 0x00002000 -+#define CKF_VERIFY_RECOVER 0x00004000 -+#define CKF_GENERATE 0x00008000 -+#define CKF_GENERATE_KEY_PAIR 0x00010000 -+#define CKF_WRAP 0x00020000 -+#define CKF_UNWRAP 0x00040000 -+#define CKF_DERIVE 0x00080000 -+ -+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, -+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They -+ * describe a token's EC capabilities not available in mechanism -+ * information. */ -+#define CKF_EC_F_P 0x00100000 -+#define CKF_EC_F_2M 0x00200000 -+#define CKF_EC_ECPARAMETERS 0x00400000 -+#define CKF_EC_NAMEDCURVE 0x00800000 -+#define CKF_EC_UNCOMPRESS 0x01000000 -+#define CKF_EC_COMPRESS 0x02000000 -+ -+#define CKF_EXTENSION 0x80000000 /* FALSE for this version */ -+ -+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; -+ -+ -+/* CK_RV is a value that identifies the return value of a -+ * Cryptoki function */ -+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */ -+typedef CK_ULONG CK_RV; -+ -+#define CKR_OK 0x00000000 -+#define CKR_CANCEL 0x00000001 -+#define CKR_HOST_MEMORY 0x00000002 -+#define CKR_SLOT_ID_INVALID 0x00000003 -+ -+/* CKR_FLAGS_INVALID was removed for v2.0 */ -+ -+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */ -+#define CKR_GENERAL_ERROR 0x00000005 -+#define CKR_FUNCTION_FAILED 0x00000006 -+ -+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS, -+ * and CKR_CANT_LOCK are new for v2.01 */ -+#define CKR_ARGUMENTS_BAD 0x00000007 -+#define CKR_NO_EVENT 0x00000008 -+#define CKR_NEED_TO_CREATE_THREADS 0x00000009 -+#define CKR_CANT_LOCK 0x0000000A -+ -+#define CKR_ATTRIBUTE_READ_ONLY 0x00000010 -+#define CKR_ATTRIBUTE_SENSITIVE 0x00000011 -+#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012 -+#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013 -+/* New CKR_COPY_PROHIBITED in v2.30? */ -+#define CKR_COPY_PROHIBITED 0x0000001A -+#define CKR_DATA_INVALID 0x00000020 -+#define CKR_DATA_LEN_RANGE 0x00000021 -+#define CKR_DEVICE_ERROR 0x00000030 -+#define CKR_DEVICE_MEMORY 0x00000031 -+#define CKR_DEVICE_REMOVED 0x00000032 -+#define CKR_ENCRYPTED_DATA_INVALID 0x00000040 -+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041 -+#define CKR_FUNCTION_CANCELED 0x00000050 -+#define CKR_FUNCTION_NOT_PARALLEL 0x00000051 -+ -+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */ -+#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054 -+ -+#define CKR_KEY_HANDLE_INVALID 0x00000060 -+ -+/* CKR_KEY_SENSITIVE was removed for v2.0 */ -+ -+#define CKR_KEY_SIZE_RANGE 0x00000062 -+#define CKR_KEY_TYPE_INCONSISTENT 0x00000063 -+ -+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED, -+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED, -+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for -+ * v2.0 */ -+#define CKR_KEY_NOT_NEEDED 0x00000064 -+#define CKR_KEY_CHANGED 0x00000065 -+#define CKR_KEY_NEEDED 0x00000066 -+#define CKR_KEY_INDIGESTIBLE 0x00000067 -+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068 -+#define CKR_KEY_NOT_WRAPPABLE 0x00000069 -+#define CKR_KEY_UNEXTRACTABLE 0x0000006A -+ -+#define CKR_MECHANISM_INVALID 0x00000070 -+#define CKR_MECHANISM_PARAM_INVALID 0x00000071 -+ -+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID -+ * were removed for v2.0 */ -+#define CKR_OBJECT_HANDLE_INVALID 0x00000082 -+#define CKR_OPERATION_ACTIVE 0x00000090 -+#define CKR_OPERATION_NOT_INITIALIZED 0x00000091 -+#define CKR_PIN_INCORRECT 0x000000A0 -+#define CKR_PIN_INVALID 0x000000A1 -+#define CKR_PIN_LEN_RANGE 0x000000A2 -+ -+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */ -+#define CKR_PIN_EXPIRED 0x000000A3 -+#define CKR_PIN_LOCKED 0x000000A4 -+ -+#define CKR_SESSION_CLOSED 0x000000B0 -+#define CKR_SESSION_COUNT 0x000000B1 -+#define CKR_SESSION_HANDLE_INVALID 0x000000B3 -+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4 -+#define CKR_SESSION_READ_ONLY 0x000000B5 -+#define CKR_SESSION_EXISTS 0x000000B6 -+ -+/* CKR_SESSION_READ_ONLY_EXISTS and -+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */ -+#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7 -+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8 -+ -+#define CKR_SIGNATURE_INVALID 0x000000C0 -+#define CKR_SIGNATURE_LEN_RANGE 0x000000C1 -+#define CKR_TEMPLATE_INCOMPLETE 0x000000D0 -+#define CKR_TEMPLATE_INCONSISTENT 0x000000D1 -+#define CKR_TOKEN_NOT_PRESENT 0x000000E0 -+#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1 -+#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2 -+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0 -+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1 -+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2 -+ -+/* private extra values */ -+#define CKR_LIBRARY_ALREADY_INITIALIZED 0x000000FD -+#define CKR_LIBRARY_FAILED_TO_LOAD 0x000000FE -+#define CKR_SYMBOL_RESOLUTION_FAILED 0x000000FF -+ -+#define CKR_USER_ALREADY_LOGGED_IN 0x00000100 -+#define CKR_USER_NOT_LOGGED_IN 0x00000101 -+#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102 -+#define CKR_USER_TYPE_INVALID 0x00000103 -+ -+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES -+ * are new to v2.01 */ -+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104 -+#define CKR_USER_TOO_MANY_TYPES 0x00000105 -+ -+#define CKR_WRAPPED_KEY_INVALID 0x00000110 -+#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112 -+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113 -+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114 -+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 -+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 -+ -+/* These are new to v2.0 */ -+#define CKR_RANDOM_NO_RNG 0x00000121 -+ -+/* These are new to v2.11 */ -+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130 -+ -+/* These are new to v2.0 */ -+#define CKR_BUFFER_TOO_SMALL 0x00000150 -+#define CKR_SAVED_STATE_INVALID 0x00000160 -+#define CKR_INFORMATION_SENSITIVE 0x00000170 -+#define CKR_STATE_UNSAVEABLE 0x00000180 -+ -+/* These are new to v2.01 */ -+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190 -+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191 -+#define CKR_MUTEX_BAD 0x000001A0 -+#define CKR_MUTEX_NOT_LOCKED 0x000001A1 -+ -+/* The following return values are new for PKCS #11 v2.20 amendment 3 */ -+#define CKR_NEW_PIN_MODE 0x000001B0 -+#define CKR_NEXT_OTP 0x000001B1 -+ -+/* New from v2.30? */ -+#define CKR_EXCEEDED_MAX_ITERATIONS 0x000001B5 -+#define CKR_FIPS_SELF_TEST_FAILED 0x000001B6 -+#define CKR_LIBRARY_LOAD_FAILED 0x000001B7 -+#define CKR_PIN_TOO_WEAK 0x000001B8 -+#define CKR_PUBLIC_KEY_INVALID 0x000001B9 -+ -+/* This is new to v2.20 */ -+#define CKR_FUNCTION_REJECTED 0x00000200 -+ -+#define CKR_VENDOR_DEFINED 0x80000000 -+ -+ -+/* CK_NOTIFY is an application callback that processes events */ -+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)( -+ CK_SESSION_HANDLE hSession, /* the session's handle */ -+ CK_NOTIFICATION event, -+ CK_VOID_PTR pApplication /* passed to C_OpenSession */ -+); -+ -+ -+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec -+ * version and pointers of appropriate types to all the -+ * Cryptoki functions */ -+/* CK_FUNCTION_LIST is new for v2.0 */ -+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; -+ -+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR; -+ -+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR; -+ -+ -+/* CK_CREATEMUTEX is an application callback for creating a -+ * mutex object */ -+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)( -+ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */ -+); -+ -+ -+/* CK_DESTROYMUTEX is an application callback for destroying a -+ * mutex object */ -+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)( -+ CK_VOID_PTR pMutex /* pointer to mutex */ -+); -+ -+ -+/* CK_LOCKMUTEX is an application callback for locking a mutex */ -+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)( -+ CK_VOID_PTR pMutex /* pointer to mutex */ -+); -+ -+ -+/* CK_UNLOCKMUTEX is an application callback for unlocking a -+ * mutex */ -+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)( -+ CK_VOID_PTR pMutex /* pointer to mutex */ -+); -+ -+ -+/* CK_C_INITIALIZE_ARGS provides the optional arguments to -+ * C_Initialize */ -+typedef struct CK_C_INITIALIZE_ARGS { -+ CK_CREATEMUTEX CreateMutex; -+ CK_DESTROYMUTEX DestroyMutex; -+ CK_LOCKMUTEX LockMutex; -+ CK_UNLOCKMUTEX UnlockMutex; -+ CK_FLAGS flags; -+ CK_VOID_PTR pReserved; -+} CK_C_INITIALIZE_ARGS; -+ -+/* flags: bit flags that provide capabilities of the slot -+ * Bit Flag Mask Meaning -+ */ -+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001 -+#define CKF_OS_LOCKING_OK 0x00000002 -+ -+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; -+ -+ -+/* additional flags for parameters to functions */ -+ -+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ -+#define CKF_DONT_BLOCK 1 -+ -+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. -+ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message -+ * Generation Function (MGF) applied to a message block when -+ * formatting a message block for the PKCS #1 OAEP encryption -+ * scheme. */ -+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; -+ -+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; -+ -+/* The following MGFs are defined */ -+/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512 -+ * are new for v2.20 */ -+#define CKG_MGF1_SHA1 0x00000001 -+#define CKG_MGF1_SHA256 0x00000002 -+#define CKG_MGF1_SHA384 0x00000003 -+#define CKG_MGF1_SHA512 0x00000004 -+/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */ -+#define CKG_MGF1_SHA224 0x00000005 -+ -+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. -+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source -+ * of the encoding parameter when formatting a message block -+ * for the PKCS #1 OAEP encryption scheme. */ -+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; -+ -+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; -+ -+/* The following encoding parameter sources are defined */ -+#define CKZ_DATA_SPECIFIED 0x00000001 -+ -+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. -+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the -+ * CKM_RSA_PKCS_OAEP mechanism. */ -+typedef struct CK_RSA_PKCS_OAEP_PARAMS { -+ CK_MECHANISM_TYPE hashAlg; -+ CK_RSA_PKCS_MGF_TYPE mgf; -+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source; -+ CK_VOID_PTR pSourceData; -+ CK_ULONG ulSourceDataLen; -+} CK_RSA_PKCS_OAEP_PARAMS; -+ -+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; -+ -+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11. -+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the -+ * CKM_RSA_PKCS_PSS mechanism(s). */ -+typedef struct CK_RSA_PKCS_PSS_PARAMS { -+ CK_MECHANISM_TYPE hashAlg; -+ CK_RSA_PKCS_MGF_TYPE mgf; -+ CK_ULONG sLen; -+} CK_RSA_PKCS_PSS_PARAMS; -+ -+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR; -+ -+/* CK_EC_KDF_TYPE is new for v2.11. */ -+typedef CK_ULONG CK_EC_KDF_TYPE; -+ -+/* The following EC Key Derivation Functions are defined */ -+#define CKD_NULL 0x00000001 -+#define CKD_SHA1_KDF 0x00000002 -+ -+/* CK_ECDH1_DERIVE_PARAMS is new for v2.11. -+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the -+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms, -+ * where each party contributes one key pair. -+ */ -+typedef struct CK_ECDH1_DERIVE_PARAMS { -+ CK_EC_KDF_TYPE kdf; -+ CK_ULONG ulSharedDataLen; -+ CK_BYTE_PTR pSharedData; -+ CK_ULONG ulPublicDataLen; -+ CK_BYTE_PTR pPublicData; -+} CK_ECDH1_DERIVE_PARAMS; -+ -+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; -+ -+ -+/* CK_ECDH2_DERIVE_PARAMS is new for v2.11. -+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the -+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */ -+typedef struct CK_ECDH2_DERIVE_PARAMS { -+ CK_EC_KDF_TYPE kdf; -+ CK_ULONG ulSharedDataLen; -+ CK_BYTE_PTR pSharedData; -+ CK_ULONG ulPublicDataLen; -+ CK_BYTE_PTR pPublicData; -+ CK_ULONG ulPrivateDataLen; -+ CK_OBJECT_HANDLE hPrivateData; -+ CK_ULONG ulPublicDataLen2; -+ CK_BYTE_PTR pPublicData2; -+} CK_ECDH2_DERIVE_PARAMS; -+ -+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR; -+ -+typedef struct CK_ECMQV_DERIVE_PARAMS { -+ CK_EC_KDF_TYPE kdf; -+ CK_ULONG ulSharedDataLen; -+ CK_BYTE_PTR pSharedData; -+ CK_ULONG ulPublicDataLen; -+ CK_BYTE_PTR pPublicData; -+ CK_ULONG ulPrivateDataLen; -+ CK_OBJECT_HANDLE hPrivateData; -+ CK_ULONG ulPublicDataLen2; -+ CK_BYTE_PTR pPublicData2; -+ CK_OBJECT_HANDLE publicKey; -+} CK_ECMQV_DERIVE_PARAMS; -+ -+typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR; -+ -+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the -+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */ -+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE; -+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR; -+ -+/* The following X9.42 DH key derivation functions are defined -+ (besides CKD_NULL already defined : */ -+#define CKD_SHA1_KDF_ASN1 0x00000003 -+#define CKD_SHA1_KDF_CONCATENATE 0x00000004 -+ -+/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11. -+ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the -+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party -+ * contributes one key pair */ -+typedef struct CK_X9_42_DH1_DERIVE_PARAMS { -+ CK_X9_42_DH_KDF_TYPE kdf; -+ CK_ULONG ulOtherInfoLen; -+ CK_BYTE_PTR pOtherInfo; -+ CK_ULONG ulPublicDataLen; -+ CK_BYTE_PTR pPublicData; -+} CK_X9_42_DH1_DERIVE_PARAMS; -+ -+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR; -+ -+/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11. -+ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the -+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation -+ * mechanisms, where each party contributes two key pairs */ -+typedef struct CK_X9_42_DH2_DERIVE_PARAMS { -+ CK_X9_42_DH_KDF_TYPE kdf; -+ CK_ULONG ulOtherInfoLen; -+ CK_BYTE_PTR pOtherInfo; -+ CK_ULONG ulPublicDataLen; -+ CK_BYTE_PTR pPublicData; -+ CK_ULONG ulPrivateDataLen; -+ CK_OBJECT_HANDLE hPrivateData; -+ CK_ULONG ulPublicDataLen2; -+ CK_BYTE_PTR pPublicData2; -+} CK_X9_42_DH2_DERIVE_PARAMS; -+ -+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR; -+ -+typedef struct CK_X9_42_MQV_DERIVE_PARAMS { -+ CK_X9_42_DH_KDF_TYPE kdf; -+ CK_ULONG ulOtherInfoLen; -+ CK_BYTE_PTR pOtherInfo; -+ CK_ULONG ulPublicDataLen; -+ CK_BYTE_PTR pPublicData; -+ CK_ULONG ulPrivateDataLen; -+ CK_OBJECT_HANDLE hPrivateData; -+ CK_ULONG ulPublicDataLen2; -+ CK_BYTE_PTR pPublicData2; -+ CK_OBJECT_HANDLE publicKey; -+} CK_X9_42_MQV_DERIVE_PARAMS; -+ -+typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR; -+ -+/* CK_KEA_DERIVE_PARAMS provides the parameters to the -+ * CKM_KEA_DERIVE mechanism */ -+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */ -+typedef struct CK_KEA_DERIVE_PARAMS { -+ CK_BBOOL isSender; -+ CK_ULONG ulRandomLen; -+ CK_BYTE_PTR pRandomA; -+ CK_BYTE_PTR pRandomB; -+ CK_ULONG ulPublicDataLen; -+ CK_BYTE_PTR pPublicData; -+} CK_KEA_DERIVE_PARAMS; -+ -+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR; -+ -+ -+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and -+ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just -+ * holds the effective keysize */ -+typedef CK_ULONG CK_RC2_PARAMS; -+ -+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR; -+ -+ -+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC -+ * mechanism */ -+typedef struct CK_RC2_CBC_PARAMS { -+ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for -+ * v2.0 */ -+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ -+ -+ CK_BYTE iv[8]; /* IV for CBC mode */ -+} CK_RC2_CBC_PARAMS; -+ -+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR; -+ -+ -+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the -+ * CKM_RC2_MAC_GENERAL mechanism */ -+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */ -+typedef struct CK_RC2_MAC_GENERAL_PARAMS { -+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */ -+ CK_ULONG ulMacLength; /* Length of MAC in bytes */ -+} CK_RC2_MAC_GENERAL_PARAMS; -+ -+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \ -+ CK_RC2_MAC_GENERAL_PARAMS_PTR; -+ -+ -+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and -+ * CKM_RC5_MAC mechanisms */ -+/* CK_RC5_PARAMS is new for v2.0 */ -+typedef struct CK_RC5_PARAMS { -+ CK_ULONG ulWordsize; /* wordsize in bits */ -+ CK_ULONG ulRounds; /* number of rounds */ -+} CK_RC5_PARAMS; -+ -+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR; -+ -+ -+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC -+ * mechanism */ -+/* CK_RC5_CBC_PARAMS is new for v2.0 */ -+typedef struct CK_RC5_CBC_PARAMS { -+ CK_ULONG ulWordsize; /* wordsize in bits */ -+ CK_ULONG ulRounds; /* number of rounds */ -+ CK_BYTE_PTR pIv; /* pointer to IV */ -+ CK_ULONG ulIvLen; /* length of IV in bytes */ -+} CK_RC5_CBC_PARAMS; -+ -+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR; -+ -+ -+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the -+ * CKM_RC5_MAC_GENERAL mechanism */ -+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */ -+typedef struct CK_RC5_MAC_GENERAL_PARAMS { -+ CK_ULONG ulWordsize; /* wordsize in bits */ -+ CK_ULONG ulRounds; /* number of rounds */ -+ CK_ULONG ulMacLength; /* Length of MAC in bytes */ -+} CK_RC5_MAC_GENERAL_PARAMS; -+ -+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \ -+ CK_RC5_MAC_GENERAL_PARAMS_PTR; -+ -+ -+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block -+ * ciphers' MAC_GENERAL mechanisms. Its value is the length of -+ * the MAC */ -+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */ -+typedef CK_ULONG CK_MAC_GENERAL_PARAMS; -+ -+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; -+ -+/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */ -+typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS { -+ CK_BYTE iv[8]; -+ CK_BYTE_PTR pData; -+ CK_ULONG length; -+} CK_DES_CBC_ENCRYPT_DATA_PARAMS; -+ -+typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; -+ -+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { -+ CK_BYTE iv[16]; -+ CK_BYTE_PTR pData; -+ CK_ULONG length; -+} CK_AES_CBC_ENCRYPT_DATA_PARAMS; -+ -+typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; -+ -+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the -+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ -+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */ -+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS { -+ CK_ULONG ulPasswordLen; -+ CK_BYTE_PTR pPassword; -+ CK_ULONG ulPublicDataLen; -+ CK_BYTE_PTR pPublicData; -+ CK_ULONG ulPAndGLen; -+ CK_ULONG ulQLen; -+ CK_ULONG ulRandomLen; -+ CK_BYTE_PTR pRandomA; -+ CK_BYTE_PTR pPrimeP; -+ CK_BYTE_PTR pBaseG; -+ CK_BYTE_PTR pSubprimeQ; -+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS; -+ -+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \ -+ CK_SKIPJACK_PRIVATE_WRAP_PTR; -+ -+ -+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the -+ * CKM_SKIPJACK_RELAYX mechanism */ -+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */ -+typedef struct CK_SKIPJACK_RELAYX_PARAMS { -+ CK_ULONG ulOldWrappedXLen; -+ CK_BYTE_PTR pOldWrappedX; -+ CK_ULONG ulOldPasswordLen; -+ CK_BYTE_PTR pOldPassword; -+ CK_ULONG ulOldPublicDataLen; -+ CK_BYTE_PTR pOldPublicData; -+ CK_ULONG ulOldRandomLen; -+ CK_BYTE_PTR pOldRandomA; -+ CK_ULONG ulNewPasswordLen; -+ CK_BYTE_PTR pNewPassword; -+ CK_ULONG ulNewPublicDataLen; -+ CK_BYTE_PTR pNewPublicData; -+ CK_ULONG ulNewRandomLen; -+ CK_BYTE_PTR pNewRandomA; -+} CK_SKIPJACK_RELAYX_PARAMS; -+ -+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ -+ CK_SKIPJACK_RELAYX_PARAMS_PTR; -+ -+ -+typedef struct CK_PBE_PARAMS { -+ CK_BYTE_PTR pInitVector; -+ CK_UTF8CHAR_PTR pPassword; -+ CK_ULONG ulPasswordLen; -+ CK_BYTE_PTR pSalt; -+ CK_ULONG ulSaltLen; -+ CK_ULONG ulIteration; -+} CK_PBE_PARAMS; -+ -+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; -+ -+ -+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the -+ * CKM_KEY_WRAP_SET_OAEP mechanism */ -+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */ -+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS { -+ CK_BYTE bBC; /* block contents byte */ -+ CK_BYTE_PTR pX; /* extra data */ -+ CK_ULONG ulXLen; /* length of extra data in bytes */ -+} CK_KEY_WRAP_SET_OAEP_PARAMS; -+ -+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \ -+ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR; -+ -+ -+typedef struct CK_SSL3_RANDOM_DATA { -+ CK_BYTE_PTR pClientRandom; -+ CK_ULONG ulClientRandomLen; -+ CK_BYTE_PTR pServerRandom; -+ CK_ULONG ulServerRandomLen; -+} CK_SSL3_RANDOM_DATA; -+ -+ -+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS { -+ CK_SSL3_RANDOM_DATA RandomInfo; -+ CK_VERSION_PTR pVersion; -+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS; -+ -+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \ -+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR; -+ -+ -+typedef struct CK_SSL3_KEY_MAT_OUT { -+ CK_OBJECT_HANDLE hClientMacSecret; -+ CK_OBJECT_HANDLE hServerMacSecret; -+ CK_OBJECT_HANDLE hClientKey; -+ CK_OBJECT_HANDLE hServerKey; -+ CK_BYTE_PTR pIVClient; -+ CK_BYTE_PTR pIVServer; -+} CK_SSL3_KEY_MAT_OUT; -+ -+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR; -+ -+ -+typedef struct CK_SSL3_KEY_MAT_PARAMS { -+ CK_ULONG ulMacSizeInBits; -+ CK_ULONG ulKeySizeInBits; -+ CK_ULONG ulIVSizeInBits; -+ CK_BBOOL bIsExport; -+ CK_SSL3_RANDOM_DATA RandomInfo; -+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial; -+} CK_SSL3_KEY_MAT_PARAMS; -+ -+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; -+ -+/* CK_TLS_PRF_PARAMS is new for version 2.20 */ -+typedef struct CK_TLS_PRF_PARAMS { -+ CK_BYTE_PTR pSeed; -+ CK_ULONG ulSeedLen; -+ CK_BYTE_PTR pLabel; -+ CK_ULONG ulLabelLen; -+ CK_BYTE_PTR pOutput; -+ CK_ULONG_PTR pulOutputLen; -+} CK_TLS_PRF_PARAMS; -+ -+typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR; -+ -+/* WTLS is new for version 2.20 */ -+typedef struct CK_WTLS_RANDOM_DATA { -+ CK_BYTE_PTR pClientRandom; -+ CK_ULONG ulClientRandomLen; -+ CK_BYTE_PTR pServerRandom; -+ CK_ULONG ulServerRandomLen; -+} CK_WTLS_RANDOM_DATA; -+ -+typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR; -+ -+typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS { -+ CK_MECHANISM_TYPE DigestMechanism; -+ CK_WTLS_RANDOM_DATA RandomInfo; -+ CK_BYTE_PTR pVersion; -+} CK_WTLS_MASTER_KEY_DERIVE_PARAMS; -+ -+typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \ -+ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR; -+ -+typedef struct CK_WTLS_PRF_PARAMS { -+ CK_MECHANISM_TYPE DigestMechanism; -+ CK_BYTE_PTR pSeed; -+ CK_ULONG ulSeedLen; -+ CK_BYTE_PTR pLabel; -+ CK_ULONG ulLabelLen; -+ CK_BYTE_PTR pOutput; -+ CK_ULONG_PTR pulOutputLen; -+} CK_WTLS_PRF_PARAMS; -+ -+typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR; -+ -+typedef struct CK_WTLS_KEY_MAT_OUT { -+ CK_OBJECT_HANDLE hMacSecret; -+ CK_OBJECT_HANDLE hKey; -+ CK_BYTE_PTR pIV; -+} CK_WTLS_KEY_MAT_OUT; -+ -+typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR; -+ -+typedef struct CK_WTLS_KEY_MAT_PARAMS { -+ CK_MECHANISM_TYPE DigestMechanism; -+ CK_ULONG ulMacSizeInBits; -+ CK_ULONG ulKeySizeInBits; -+ CK_ULONG ulIVSizeInBits; -+ CK_ULONG ulSequenceNumber; -+ CK_BBOOL bIsExport; -+ CK_WTLS_RANDOM_DATA RandomInfo; -+ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial; -+} CK_WTLS_KEY_MAT_PARAMS; -+ -+typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR; -+ -+/* CMS is new for version 2.20 */ -+typedef struct CK_CMS_SIG_PARAMS { -+ CK_OBJECT_HANDLE certificateHandle; -+ CK_MECHANISM_PTR pSigningMechanism; -+ CK_MECHANISM_PTR pDigestMechanism; -+ CK_UTF8CHAR_PTR pContentType; -+ CK_BYTE_PTR pRequestedAttributes; -+ CK_ULONG ulRequestedAttributesLen; -+ CK_BYTE_PTR pRequiredAttributes; -+ CK_ULONG ulRequiredAttributesLen; -+} CK_CMS_SIG_PARAMS; -+ -+typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR; -+ -+typedef struct CK_KEY_DERIVATION_STRING_DATA { -+ CK_BYTE_PTR pData; -+ CK_ULONG ulLen; -+} CK_KEY_DERIVATION_STRING_DATA; -+ -+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \ -+ CK_KEY_DERIVATION_STRING_DATA_PTR; -+ -+ -+/* The CK_EXTRACT_PARAMS is used for the -+ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit -+ * of the base key should be used as the first bit of the -+ * derived key */ -+/* CK_EXTRACT_PARAMS is new for v2.0 */ -+typedef CK_ULONG CK_EXTRACT_PARAMS; -+ -+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; -+ -+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. -+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to -+ * indicate the Pseudo-Random Function (PRF) used to generate -+ * key bits using PKCS #5 PBKDF2. */ -+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; -+ -+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; -+ -+/* The following PRFs are defined in PKCS #5 v2.0. */ -+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 -+ -+ -+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10. -+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the -+ * source of the salt value when deriving a key using PKCS #5 -+ * PBKDF2. */ -+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; -+ -+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; -+ -+/* The following salt value sources are defined in PKCS #5 v2.0. */ -+#define CKZ_SALT_SPECIFIED 0x00000001 -+ -+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10. -+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the -+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */ -+typedef struct CK_PKCS5_PBKD2_PARAMS { -+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; -+ CK_VOID_PTR pSaltSourceData; -+ CK_ULONG ulSaltSourceDataLen; -+ CK_ULONG iterations; -+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; -+ CK_VOID_PTR pPrfData; -+ CK_ULONG ulPrfDataLen; -+ CK_UTF8CHAR_PTR pPassword; -+ CK_ULONG_PTR ulPasswordLen; -+} CK_PKCS5_PBKD2_PARAMS; -+ -+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; -+ -+/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */ -+ -+typedef CK_ULONG CK_OTP_PARAM_TYPE; -+typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */ -+ -+typedef struct CK_OTP_PARAM { -+ CK_OTP_PARAM_TYPE type; -+ CK_VOID_PTR pValue; -+ CK_ULONG ulValueLen; -+} CK_OTP_PARAM; -+ -+typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR; -+ -+typedef struct CK_OTP_PARAMS { -+ CK_OTP_PARAM_PTR pParams; -+ CK_ULONG ulCount; -+} CK_OTP_PARAMS; -+ -+typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR; -+ -+typedef struct CK_OTP_SIGNATURE_INFO { -+ CK_OTP_PARAM_PTR pParams; -+ CK_ULONG ulCount; -+} CK_OTP_SIGNATURE_INFO; -+ -+typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR; -+ -+/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ -+#define CK_OTP_VALUE 0 -+#define CK_OTP_PIN 1 -+#define CK_OTP_CHALLENGE 2 -+#define CK_OTP_TIME 3 -+#define CK_OTP_COUNTER 4 -+#define CK_OTP_FLAGS 5 -+#define CK_OTP_OUTPUT_LENGTH 6 -+#define CK_OTP_OUTPUT_FORMAT 7 -+ -+/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */ -+#define CKF_NEXT_OTP 0x00000001 -+#define CKF_EXCLUDE_TIME 0x00000002 -+#define CKF_EXCLUDE_COUNTER 0x00000004 -+#define CKF_EXCLUDE_CHALLENGE 0x00000008 -+#define CKF_EXCLUDE_PIN 0x00000010 -+#define CKF_USER_FRIENDLY_OTP 0x00000020 -+ -+/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */ -+typedef struct CK_KIP_PARAMS { -+ CK_MECHANISM_PTR pMechanism; -+ CK_OBJECT_HANDLE hKey; -+ CK_BYTE_PTR pSeed; -+ CK_ULONG ulSeedLen; -+} CK_KIP_PARAMS; -+ -+typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR; -+ -+/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ -+typedef struct CK_AES_CTR_PARAMS { -+ CK_ULONG ulCounterBits; -+ CK_BYTE cb[16]; -+} CK_AES_CTR_PARAMS; -+ -+typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR; -+ -+/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */ -+typedef struct CK_CAMELLIA_CTR_PARAMS { -+ CK_ULONG ulCounterBits; -+ CK_BYTE cb[16]; -+} CK_CAMELLIA_CTR_PARAMS; -+ -+typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR; -+ -+/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ -+typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS { -+ CK_BYTE iv[16]; -+ CK_BYTE_PTR pData; -+ CK_ULONG length; -+} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS; -+ -+typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR; -+ -+/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */ -+typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS { -+ CK_BYTE iv[16]; -+ CK_BYTE_PTR pData; -+ CK_ULONG length; -+} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS; -+ -+typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR; -+ -+#endif -diff --git a/lib/isc/md5.c b/lib/isc/md5.c -index 7c6419b..2e3cf9a 100644 ---- a/lib/isc/md5.c -+++ b/lib/isc/md5.c -@@ -41,6 +41,12 @@ - #include - #include - #include -+ -+#if PKCS11CRYPTO -+#include -+#include -+#endif -+ - #include - - #ifdef ISC_PLATFORM_OPENSSLHASH -@@ -65,6 +71,50 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { - EVP_DigestFinal(ctx, digest, NULL); - } - -+#elif PKCS11CRYPTO -+ -+void -+isc_md5_init(isc_md5_t *ctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_MD5, NULL, 0 }; -+ -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech)); -+} -+ -+void -+isc_md5_invalidate(isc_md5_t *ctx) { -+ CK_BYTE garbage[ISC_MD5_DIGESTLENGTH]; -+ CK_ULONG len = ISC_MD5_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_DigestFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ pk11_return_session(ctx); -+} -+ -+void -+isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) { -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { -+ CK_RV rv; -+ CK_ULONG len = ISC_MD5_DIGESTLENGTH; -+ -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (ctx->session, (CK_BYTE_PTR) digest, &len)); -+ pk11_return_session(ctx); -+} -+ - #else - - static void -diff --git a/lib/isc/pk11.c b/lib/isc/pk11.c -new file mode 100644 -index 0000000..015bff2 ---- /dev/null -+++ b/lib/isc/pk11.c -@@ -0,0 +1,1327 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Portions copyright (c) 2008 Nominet UK. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. 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. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -+ */ -+ -+/* -+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. -+ * Use is subject to license terms. -+ */ -+ -+/* -+ * This product includes software developed by the OpenSSL Project for -+ * use in the OpenSSL Toolkit (http://www.openssl.org/). -+ * -+ * This project also referenced hw_pkcs11-0.9.7b.patch written by -+ * Afchine Madjlessi. -+ */ -+/* -+ * ==================================================================== -+ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * 2. 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. -+ * -+ * 3. All advertising materials mentioning features or use of this -+ * software must display the following acknowledgment: -+ * "This product includes software developed by the OpenSSL Project -+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" -+ * -+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to -+ * endorse or promote products derived from this software without -+ * prior written permission. For written permission, please contact -+ * licensing@OpenSSL.org. -+ * -+ * 5. Products derived from this software may not be called "OpenSSL" -+ * nor may "OpenSSL" appear in their names without prior written -+ * permission of the OpenSSL Project. -+ * -+ * 6. Redistributions of any form whatsoever must retain the following -+ * acknowledgment: -+ * "This product includes software developed by the OpenSSL Project -+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY -+ * EXPRESSED 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 OpenSSL PROJECT OR -+ * ITS 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. -+ * ==================================================================== -+ * -+ * This product includes cryptographic software written by Eric Young -+ * (eay@cryptsoft.com). This product includes software written by Tim -+ * Hudson (tjh@cryptsoft.com). -+ * -+ */ -+ -+/* $Id$ */ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define PINLEN 32 -+ -+#ifndef PK11_NO_LOGERR -+#define PK11_NO_LOGERR 1 -+#endif -+ -+static isc_once_t once = ISC_ONCE_INIT; -+static isc_mem_t *pk11_mctx = NULL; -+static isc_int32_t allocsize = 0; -+static isc_boolean_t initialized = ISC_FALSE; -+ -+typedef struct pk11_session pk11_session_t; -+typedef struct pk11_token pk11_token_t; -+typedef ISC_LIST(pk11_session_t) pk11_sessionlist_t; -+ -+struct pk11_session { -+ unsigned int magic; -+ CK_SESSION_HANDLE session; -+ ISC_LINK(pk11_session_t) link; -+ pk11_token_t *token; -+}; -+ -+struct pk11_token { -+ unsigned int magic; -+ unsigned int operations; -+ ISC_LINK(pk11_token_t) link; -+ CK_SLOT_ID slotid; -+ pk11_sessionlist_t sessions; -+ isc_boolean_t logged; -+ char name[32]; -+ char manuf[32]; -+ char model[16]; -+ char serial[16]; -+ char pin[PINLEN]; -+}; -+static ISC_LIST(pk11_token_t) tokens; -+ -+static pk11_token_t *rand_token; -+static pk11_token_t *best_rsa_token; -+static pk11_token_t *best_dsa_token; -+static pk11_token_t *best_dh_token; -+static pk11_token_t *digest_token; -+static pk11_token_t *best_ec_token; -+static pk11_token_t *best_gost_token; -+static pk11_token_t *aes_token; -+ -+static isc_result_t free_all_sessions(void); -+static isc_result_t free_session_list(pk11_sessionlist_t *slist); -+static isc_result_t setup_session(pk11_session_t *sp, -+ pk11_token_t *token, -+ isc_boolean_t rw); -+static void choose_slots(void); -+static isc_result_t token_login(pk11_session_t *sp); -+static char *percent_decode(char *x, size_t *len); -+static isc_boolean_t pk11strcmp(const char *x, size_t lenx, -+ const char *y, size_t leny); -+static CK_ATTRIBUTE *push_attribute(pk11_object_t *obj, -+ isc_mem_t *mctx, -+ size_t len); -+ -+static isc_mutex_t alloclock; -+static isc_mutex_t sessionlock; -+ -+static pk11_sessionlist_t actives; -+ -+static CK_C_INITIALIZE_ARGS pk11_init_args = { -+ NULL_PTR, /* CreateMutex */ -+ NULL_PTR, /* DestroyMutex */ -+ NULL_PTR, /* LockMutex */ -+ NULL_PTR, /* UnlockMutex */ -+ CKF_OS_LOCKING_OK, /* flags */ -+ NULL_PTR, /* pReserved */ -+}; -+ -+#ifndef PK11_LIB_LOCATION -+#define PK11_LIB_LOCATION "unknown_provider" -+#endif -+ -+#ifndef WIN32 -+static const char *lib_name = PK11_LIB_LOCATION; -+#else -+static const char *lib_name = PK11_LIB_LOCATION ".dll"; -+#endif -+ -+void -+pk11_set_lib_name(const char *name) { -+ lib_name = name; -+} -+ -+const char * -+pk11_get_lib_name(void) { -+ return (lib_name); -+} -+ -+static void -+initialize(void) { -+ char *pk11_provider; -+ -+ RUNTIME_CHECK(isc_mutex_init(&alloclock) == ISC_R_SUCCESS); -+ RUNTIME_CHECK(isc_mutex_init(&sessionlock) == ISC_R_SUCCESS); -+ -+ pk11_provider = getenv("PKCS11_PROVIDER"); -+ if (pk11_provider != NULL) -+ lib_name = pk11_provider; -+} -+ -+void * -+pk11_mem_get(size_t size) { -+ void *ptr; -+ -+ LOCK(&alloclock); -+ if (pk11_mctx != NULL) -+ ptr = isc_mem_get(pk11_mctx, size); -+ else { -+ ptr = malloc(size); -+ if (ptr != NULL) -+ allocsize += (int)size; -+ } -+ UNLOCK(&alloclock); -+ -+ if (ptr != NULL) -+ memset(ptr, 0, size); -+ return (ptr); -+} -+ -+void -+pk11_mem_put(void *ptr, size_t size) { -+ if (ptr != NULL) -+ memset(ptr, 0, size); -+ LOCK(&alloclock); -+ if (pk11_mctx != NULL) -+ isc_mem_put(pk11_mctx, ptr, size); -+ else { -+ if (ptr != NULL) -+ allocsize -= (int)size; -+ free(ptr); -+ } -+ UNLOCK(&alloclock); -+} -+ -+isc_result_t -+pk11_initialize(isc_mem_t *mctx, const char *engine) { -+ isc_result_t result; -+ CK_RV rv; -+ -+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); -+ -+ LOCK(&alloclock); -+ if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0)) -+ isc_mem_attach(mctx, &pk11_mctx); -+ if (initialized) { -+ UNLOCK(&alloclock); -+ return (ISC_R_SUCCESS); -+ } else { -+ LOCK(&sessionlock); -+ initialized = ISC_TRUE; -+ UNLOCK(&alloclock); -+ } -+ -+ ISC_LIST_INIT(tokens); -+ ISC_LIST_INIT(actives); -+ -+ if (engine != NULL) -+ lib_name = engine; -+ -+ /* Initialize the CRYPTOKI library */ -+ rv = pkcs_C_Initialize((CK_VOID_PTR) &pk11_init_args); -+ -+ if (rv == 0xfe) { -+ result = PK11_R_NOPROVIDER; -+ goto unlock; -+ } -+ if (rv != CKR_OK) { -+ result = PK11_R_INITFAILED; -+ goto unlock; -+ } -+ -+ choose_slots(); -+#ifdef PKCS11CRYPTO -+ if (rand_token == NULL) { -+ result = PK11_R_NORANDOMSERVICE; -+ goto unlock; -+ } -+ if (digest_token == NULL) { -+ result = PK11_R_NODIGESTSERVICE; -+ goto unlock; -+ } -+#if defined(ISC_PLATFORM_USESIT) && defined(AES_SIT) -+ if (aes_token == NULL) { -+ result = PK11_R_NOAESSERVICE; -+ goto unlock; -+ } -+#endif -+#endif /* PKCS11CRYPTO */ -+ result = ISC_R_SUCCESS; -+ unlock: -+ UNLOCK(&sessionlock); -+ return (result); -+} -+ -+isc_result_t -+pk11_finalize(void) { -+ pk11_token_t *token, *next; -+ isc_result_t ret; -+ -+ ret = free_all_sessions(); -+ (void) pkcs_C_Finalize(NULL_PTR); -+ token = ISC_LIST_HEAD(tokens); -+ while (token != NULL) { -+ next = ISC_LIST_NEXT(token, link); -+ ISC_LIST_UNLINK(tokens, token, link); -+ if (token == rand_token) -+ rand_token = NULL; -+ if (token == best_rsa_token) -+ best_rsa_token = NULL; -+ if (token == best_dsa_token) -+ best_dsa_token = NULL; -+ if (token == best_dh_token) -+ best_dh_token = NULL; -+ if (token == digest_token) -+ digest_token = NULL; -+ if (token == best_ec_token) -+ best_ec_token = NULL; -+ if (token == best_gost_token) -+ best_gost_token = NULL; -+ if (token == aes_token) -+ aes_token = NULL; -+ pk11_mem_put(token, sizeof(*token)); -+ token = next; -+ } -+ if (pk11_mctx != NULL) -+ isc_mem_detach(&pk11_mctx); -+ initialized = ISC_FALSE; -+ return (ret); -+} -+ -+isc_result_t -+pk11_rand_bytes(unsigned char *buf, int num) { -+ isc_result_t ret; -+ CK_RV rv; -+ pk11_context_t ctx; -+ -+ ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE, -+ ISC_FALSE, NULL, 0); -+ if ((ret != ISC_R_SUCCESS) && -+ (ret != PK11_R_NODIGESTSERVICE) && -+ (ret != PK11_R_NOAESSERVICE)) -+ return (ret); -+ RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE); -+ rv = pkcs_C_GenerateRandom(ctx.session, -+ (CK_BYTE_PTR) buf, (CK_ULONG) num); -+ pk11_return_session(&ctx); -+ if (rv == CKR_OK) -+ return (ISC_R_SUCCESS); -+ else -+ return (DST_R_CRYPTOFAILURE); -+} -+ -+#define SEEDSIZE 1024 -+ -+static CK_BYTE seed[SEEDSIZE]; -+ -+void -+pk11_rand_seed_fromfile(const char *randomfile) { -+ pk11_context_t ctx; -+ FILE *stream = NULL; -+ size_t cc = 0; -+ isc_result_t ret; -+ -+ ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE, -+ ISC_FALSE, NULL, 0); -+ if ((ret != ISC_R_SUCCESS) && -+ (ret != PK11_R_NODIGESTSERVICE) && -+ (ret != PK11_R_NOAESSERVICE)) -+ return; -+ RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE); -+ ret = isc_stdio_open(randomfile, "r", &stream); -+ if (ret != ISC_R_SUCCESS) -+ goto cleanup; -+ ret = isc_stdio_read(seed, 1, SEEDSIZE, stream, &cc); -+ if (ret!= ISC_R_SUCCESS) -+ goto cleanup; -+ ret = isc_stdio_close(stream); -+ stream = NULL; -+ if (ret!= ISC_R_SUCCESS) -+ goto cleanup; -+ (void) pkcs_C_SeedRandom(ctx.session, seed, (CK_ULONG) cc); -+ -+ cleanup: -+ if (stream != NULL) -+ (void) isc_stdio_close(stream); -+ pk11_return_session(&ctx); -+} -+ -+isc_result_t -+pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype, -+ isc_boolean_t need_services, isc_boolean_t rw, -+ isc_boolean_t logon, const char *pin, CK_SLOT_ID slot) -+{ -+ pk11_token_t *token = NULL; -+ pk11_sessionlist_t *freelist; -+ pk11_session_t *sp; -+ isc_result_t ret; -+#ifdef PKCS11CRYPTO -+ isc_result_t service_ret = ISC_R_SUCCESS; -+#else -+ UNUSED(need_services); -+#endif -+ -+ memset(ctx, 0, sizeof(pk11_context_t)); -+ ctx->handle = NULL; -+ ctx->session = CK_INVALID_HANDLE; -+ -+ ret = pk11_initialize(NULL, NULL); -+#ifdef PKCS11CRYPTO -+ if (ret == PK11_R_NORANDOMSERVICE || -+ ret == PK11_R_NODIGESTSERVICE || -+ ret == PK11_R_NOAESSERVICE) { -+ if (need_services) -+ return (ret); -+ service_ret = ret; -+ } -+ else -+#endif /* PKCS11CRYPTO */ -+ if (ret != ISC_R_SUCCESS) -+ return (ret); -+ -+ LOCK(&sessionlock); -+ /* wait for initialization to finish */ -+ UNLOCK(&sessionlock); -+ -+ switch(optype) { -+#ifdef PKCS11CRYPTO -+ case OP_RAND: -+ token = rand_token; -+ break; -+ case OP_DIGEST: -+ token = digest_token; -+ break; -+ case OP_AES: -+ token = aes_token; -+ break; -+ case OP_ANY: -+ for (token = ISC_LIST_HEAD(tokens); -+ token != NULL; -+ token = ISC_LIST_NEXT(token, link)) -+ if (token->slotid == slot) -+ break; -+ break; -+#endif -+ default: -+ for (token = ISC_LIST_HEAD(tokens); -+ token != NULL; -+ token = ISC_LIST_NEXT(token, link)) -+ if (token->slotid == slot) -+ break; -+#ifdef PKCS11CRYPTO -+ if ((token == NULL) || -+ ((token->operations & (1 << optype)) == 0)) -+ return (ISC_R_NOTFOUND); -+#endif -+ break; -+ } -+ if (token == NULL) -+ return (ISC_R_NOTFOUND); -+ -+ /* Override the token's PIN */ -+ if (logon && pin != NULL && *pin != '\0') { -+ memset(token->pin, 0, PINLEN); -+ strncpy(token->pin, pin, PINLEN); -+ } -+ -+ freelist = &token->sessions; -+ -+ LOCK(&sessionlock); -+ sp = ISC_LIST_HEAD(*freelist); -+ if (sp != NULL) { -+ ISC_LIST_UNLINK(*freelist, sp, link); -+ ISC_LIST_APPEND(actives, sp, link); -+ UNLOCK(&sessionlock); -+ if (logon) -+ ret = token_login(sp); -+ ctx->handle = sp; -+ ctx->session = sp->session; -+ return (ret); -+ } -+ UNLOCK(&sessionlock); -+ -+ sp = pk11_mem_get(sizeof(*sp)); -+ if (sp == NULL) -+ return (ISC_R_NOMEMORY); -+ sp->magic = SES_MAGIC; -+ sp->token = token; -+ sp->session = CK_INVALID_HANDLE; -+ ISC_LINK_INIT(sp, link); -+ ret = setup_session(sp, token, rw); -+ if ((ret == ISC_R_SUCCESS) && logon) -+ ret = token_login(sp); -+ LOCK(&sessionlock); -+ ISC_LIST_APPEND(actives, sp, link); -+ UNLOCK(&sessionlock); -+ ctx->handle = sp; -+ ctx->session = sp->session; -+#ifdef PKCS11CRYPTO -+ if (ret == ISC_R_SUCCESS) -+ ret = service_ret; -+#endif -+ return (ret); -+} -+ -+void -+pk11_return_session(pk11_context_t *ctx) { -+ pk11_session_t *sp = (pk11_session_t *) ctx->handle; -+ -+ if (sp == NULL) -+ return; -+ ctx->handle = NULL; -+ ctx->session = CK_INVALID_HANDLE; -+ -+ LOCK(&sessionlock); -+ ISC_LIST_UNLINK(actives, sp, link); -+ UNLOCK(&sessionlock); -+ if (sp->session == CK_INVALID_HANDLE) { -+ pk11_mem_put(sp, sizeof(*sp)); -+ return; -+ } -+ -+ LOCK(&sessionlock); -+ ISC_LIST_APPEND(sp->token->sessions, sp, link); -+ UNLOCK(&sessionlock); -+} -+ -+static isc_result_t -+free_all_sessions(void) { -+ pk11_token_t *token; -+ isc_result_t ret = ISC_R_SUCCESS; -+ isc_result_t oret; -+ -+ for (token = ISC_LIST_HEAD(tokens); -+ token != NULL; -+ token = ISC_LIST_NEXT(token, link)) { -+ oret = free_session_list(&token->sessions); -+ if (oret != ISC_R_SUCCESS) -+ ret = oret; -+ } -+ if (!ISC_LIST_EMPTY(actives)) { -+ ret = ISC_R_ADDRINUSE; -+ oret = free_session_list(&actives); -+ if (oret != ISC_R_SUCCESS) -+ ret = oret; -+ } -+ return (ret); -+} -+ -+static isc_result_t -+free_session_list(pk11_sessionlist_t *slist) { -+ pk11_session_t *sp; -+ CK_RV rv; -+ isc_result_t ret; -+ -+ ret = ISC_R_SUCCESS; -+ LOCK(&sessionlock); -+ while (!ISC_LIST_EMPTY(*slist)) { -+ sp = ISC_LIST_HEAD(*slist); -+ UNLOCK(&sessionlock); -+ if (sp->session != CK_INVALID_HANDLE) { -+ rv = pkcs_C_CloseSession(sp->session); -+ if (rv != CKR_OK) -+ ret = DST_R_CRYPTOFAILURE; -+ } -+ LOCK(&sessionlock); -+ ISC_LIST_UNLINK(*slist, sp, link); -+ pk11_mem_put(sp, sizeof(*sp)); -+ } -+ UNLOCK(&sessionlock); -+ -+ return (ret); -+} -+ -+static isc_result_t -+setup_session(pk11_session_t *sp, pk11_token_t *token, -+ isc_boolean_t rw) -+{ -+ CK_RV rv; -+ CK_FLAGS flags = CKF_SERIAL_SESSION; -+ -+ if (rw) -+ flags += CKF_RW_SESSION; -+ -+ rv = pkcs_C_OpenSession(token->slotid, flags, NULL_PTR, -+ NULL_PTR, &sp->session); -+ if (rv != CKR_OK) -+ return (DST_R_CRYPTOFAILURE); -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+token_login(pk11_session_t *sp) { -+ CK_RV rv; -+ pk11_token_t *token = sp->token; -+ isc_result_t ret = ISC_R_SUCCESS; -+ -+ LOCK(&sessionlock); -+ if (!token->logged) { -+ rv = pkcs_C_Login(sp->session, CKU_USER, -+ (CK_UTF8CHAR_PTR) token->pin, -+ (CK_ULONG) strlen(token->pin)); -+ if (rv != CKR_OK) { -+ ret = ISC_R_NOPERM; -+#if PK11_NO_LOGERR -+ pk11_error_fatalcheck(__FILE__, __LINE__, -+ "pkcs_C_Login", rv); -+#endif -+ } else -+ token->logged = ISC_TRUE; -+ } -+ UNLOCK(&sessionlock); -+ return (ret); -+} -+ -+static void -+choose_slots(void) { -+ CK_MECHANISM_INFO mechInfo; -+ CK_TOKEN_INFO tokenInfo; -+ CK_RV rv; -+ CK_SLOT_ID slot; -+ CK_SLOT_ID_PTR slotList; -+ CK_ULONG slotCount; -+ pk11_token_t *token; -+ unsigned int i; -+ -+ slotCount = 0; -+ PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount)); -+ /* it's not an error if we didn't find any providers */ -+ if (slotCount == 0) -+ return; -+ slotList = pk11_mem_get(sizeof(CK_SLOT_ID_PTR) * slotCount); -+ RUNTIME_CHECK(slotList != NULL); -+ PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount)); -+ -+ for (i = 0; i < slotCount; i++) { -+ slot = slotList[i]; -+ -+ rv = pkcs_C_GetTokenInfo(slot, &tokenInfo); -+ if (rv != CKR_OK) -+ continue; -+ token = pk11_mem_get(sizeof(*token)); -+ RUNTIME_CHECK(token != NULL); -+ token->magic = TOK_MAGIC; -+ token->slotid = slot; -+ ISC_LINK_INIT(token, link); -+ ISC_LIST_INIT(token->sessions); -+ memmove(token->name, tokenInfo.label, 32); -+ memmove(token->manuf, tokenInfo.manufacturerID, 32); -+ memmove(token->model, tokenInfo.model, 16); -+ memmove(token->serial, tokenInfo.serialNumber, 16); -+ ISC_LIST_APPEND(tokens, token, link); -+ if ((tokenInfo.flags & CKF_RNG) == 0) -+ goto try_rsa; -+ token->operations |= 1 << OP_RAND; -+ if (rand_token == NULL) -+ rand_token = token; -+ -+ try_rsa: -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) -+ goto try_dsa; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_RSA_PKCS, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_SIGN) == 0) || -+ ((mechInfo.flags & CKF_VERIFY) == 0)) -+ goto try_dsa; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_SIGN) == 0) || -+ ((mechInfo.flags & CKF_VERIFY) == 0)) -+ goto try_dsa; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_RSA_PKCS, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_SIGN) == 0) || -+ ((mechInfo.flags & CKF_VERIFY) == 0)) -+ goto try_dsa; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_RSA_PKCS, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_SIGN) == 0) || -+ ((mechInfo.flags & CKF_VERIFY) == 0)) -+ goto try_dsa; -+ token->operations |= 1 << OP_RSA; -+ if (best_rsa_token == NULL) -+ best_rsa_token = token; -+ -+ try_dsa: -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_PARAMETER_GEN, -+ &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0)) -+ goto try_dh; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_KEY_PAIR_GEN, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) -+ goto try_dh; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_SHA1, &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_SIGN) == 0) || -+ ((mechInfo.flags & CKF_VERIFY) == 0)) -+ goto try_dh; -+ token->operations |= 1 << OP_DSA; -+ if (best_dsa_token == NULL) -+ best_dsa_token = token; -+ -+ try_dh: -+#ifdef notdef -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_PARAMETER_GEN, -+ &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0)) -+ goto try_digest; -+#endif -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_KEY_PAIR_GEN, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) -+ goto try_digest; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_DERIVE, -+ &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DERIVE) == 0)) -+ goto try_digest; -+ token->operations |= 1 << OP_DH; -+ if (best_dh_token == NULL) -+ best_dh_token = token; -+ -+ try_digest: -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) -+ continue; -+#ifdef PKCS11CRYPTOWITHHMAC -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_HMAC, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) -+ continue; -+#endif -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1_HMAC, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224_HMAC, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_HMAC, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384_HMAC, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) -+ continue; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_HMAC, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) -+ continue; -+ token->operations |= 1 << OP_DIGEST; -+ if (digest_token == NULL) -+ digest_token = token; -+ -+ /* ECDSA requires digest */ -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_KEY_PAIR_GEN, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) -+ goto try_gost; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_ECDSA, &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_SIGN) == 0) || -+ ((mechInfo.flags & CKF_VERIFY) == 0)) -+ goto try_gost; -+ token->operations |= 1 << OP_EC; -+ if (best_ec_token == NULL) -+ best_ec_token = token; -+ -+ try_gost: -+ /* does GOST require digest too? */ -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3411, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) -+ goto try_aes; -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3410_KEY_PAIR_GEN, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0)) -+ goto try_aes; -+ rv = pkcs_C_GetMechanismInfo(slot, -+ CKM_GOSTR3410_WITH_GOSTR3411, -+ &mechInfo); -+ if ((rv != CKR_OK) || -+ ((mechInfo.flags & CKF_SIGN) == 0) || -+ ((mechInfo.flags & CKF_VERIFY) == 0)) -+ goto try_aes; -+ token->operations |= 1 << OP_GOST; -+ if (best_gost_token == NULL) -+ best_gost_token = token; -+ -+ try_aes: -+ rv = pkcs_C_GetMechanismInfo(slot, CKM_AES_ECB, &mechInfo); -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_ENCRYPT) == 0)) -+ continue; -+ token->operations |= 1 << OP_AES; -+ if (aes_token == NULL) -+ aes_token = token; -+ } -+ -+ if (slotList != NULL) -+ pk11_mem_put(slotList, sizeof(CK_SLOT_ID_PTR) * slotCount); -+} -+ -+CK_SLOT_ID -+pk11_get_best_token(pk11_optype_t optype) { -+ pk11_token_t *token = NULL; -+ -+ switch (optype) { -+ case OP_RAND: -+ token = rand_token; -+ break; -+ case OP_RSA: -+ token = best_rsa_token; -+ break; -+ case OP_DSA: -+ token = best_dsa_token; -+ break; -+ case OP_DH: -+ token = best_dh_token; -+ break; -+ case OP_DIGEST: -+ token = digest_token; -+ break; -+ case OP_EC: -+ token = best_ec_token; -+ break; -+ case OP_GOST: -+ token = best_gost_token; -+ break; -+ case OP_AES: -+ token = aes_token; -+ break; -+ default: -+ break; -+ } -+ if (token == NULL) -+ return (0); -+ return (token->slotid); -+} -+ -+unsigned int -+pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) { -+ unsigned int bitcnt, i; -+ CK_BYTE top; -+ -+ if (bytecnt == 0) -+ return (0); -+ bitcnt = bytecnt * 8; -+ for (i = 0; i < bytecnt; i++) { -+ top = data[i]; -+ if (top == 0) { -+ bitcnt -= 8; -+ continue; -+ } -+ if (top & 0x80) -+ return (bitcnt); -+ if (top & 0x40) -+ return (bitcnt - 1); -+ if (top & 0x20) -+ return (bitcnt - 2); -+ if (top & 0x10) -+ return (bitcnt - 3); -+ if (top & 0x08) -+ return (bitcnt - 4); -+ if (top & 0x04) -+ return (bitcnt - 5); -+ if (top & 0x02) -+ return (bitcnt - 6); -+ if (top & 0x01) -+ return (bitcnt - 7); -+ break; -+ } -+ INSIST(0); -+} -+ -+CK_ATTRIBUTE * -+pk11_attribute_first(const pk11_object_t *obj) { -+ return (obj->repr); -+} -+ -+CK_ATTRIBUTE * -+pk11_attribute_next(const pk11_object_t *obj, CK_ATTRIBUTE *attr) { -+ CK_ATTRIBUTE *next; -+ -+ next = attr + 1; -+ if ((next - obj->repr) >= obj->attrcnt) -+ return (NULL); -+ return (next); -+} -+ -+CK_ATTRIBUTE * -+pk11_attribute_bytype(const pk11_object_t *obj, CK_ATTRIBUTE_TYPE type) { -+ CK_ATTRIBUTE *attr; -+ -+ for(attr = pk11_attribute_first(obj); -+ attr != NULL; -+ attr = pk11_attribute_next(obj, attr)) -+ if (attr->type == type) -+ return (attr); -+ return (NULL); -+} -+ -+static char * -+percent_decode(char *x, size_t *len) { -+ char *p, *c; -+ unsigned char v; -+ -+ INSIST(len != NULL); -+ -+ for (p = c = x; p[0] != '\0'; p++, c++) { -+ switch (p[0]) { -+ case '%': -+ v = 0; -+ switch (p[1]) { -+ case '0': -+ case '1': -+ case '2': -+ case '3': -+ case '4': -+ case '5': -+ case '6': -+ case '7': -+ case '8': -+ case '9': -+ v = (p[1] - '0') << 4; -+ break; -+ case 'A': -+ case 'B': -+ case 'C': -+ case 'D': -+ case 'E': -+ case 'F': -+ v = (p[1] - 'A' + 10) << 4; -+ break; -+ case 'a': -+ case 'b': -+ case 'c': -+ case 'd': -+ case 'e': -+ case 'f': -+ v = (p[1] - 'a' + 10) << 4; -+ break; -+ default: -+ return (NULL); -+ } -+ switch (p[2]) { -+ case '0': -+ case '1': -+ case '2': -+ case '3': -+ case '4': -+ case '5': -+ case '6': -+ case '7': -+ case '8': -+ case '9': -+ v |= (p[2] - '0') & 0x0f; -+ break; -+ case 'A': -+ case 'B': -+ case 'C': -+ case 'D': -+ case 'E': -+ case 'F': -+ v = (p[2] - 'A' + 10) & 0x0f; -+ break; -+ case 'a': -+ case 'b': -+ case 'c': -+ case 'd': -+ case 'e': -+ case 'f': -+ v = (p[2] - 'a' + 10) & 0x0f; -+ break; -+ default: -+ return (NULL); -+ } -+ p += 2; -+ *c = (char) v; -+ (*len)++; -+ break; -+ default: -+ *c = *p; -+ (*len)++; -+ } -+ } -+ return (x); -+} -+ -+static isc_boolean_t -+pk11strcmp(const char *x, size_t lenx, const char *y, size_t leny) { -+ char buf[32]; -+ -+ INSIST((leny == 32) || (leny == 16)); -+ -+ memset(buf, ' ', 32); -+ if (lenx > leny) -+ lenx = leny; -+ memmove(buf, x, lenx); -+ return (ISC_TF(memcmp(buf, y, leny) == 0)); -+} -+ -+static CK_ATTRIBUTE * -+push_attribute(pk11_object_t *obj, isc_mem_t *mctx, size_t len) { -+ CK_ATTRIBUTE *old = obj->repr; -+ CK_ATTRIBUTE *attr; -+ CK_BYTE cnt = obj->attrcnt; -+ -+ obj->repr = isc_mem_get(mctx, (cnt + 1) * sizeof(*attr)); -+ if (obj->repr == NULL) { -+ obj->repr = old; -+ return (NULL); -+ } -+ memset(obj->repr, 0, (cnt + 1) * sizeof(*attr)); -+ memmove(obj->repr, old, cnt * sizeof(*attr)); -+ attr = obj->repr + cnt; -+ attr->ulValueLen = (CK_ULONG) len; -+ attr->pValue = isc_mem_get(mctx, len); -+ if (attr->pValue == NULL) { -+ memset(obj->repr, 0, (cnt + 1) * sizeof(*attr)); -+ isc_mem_put(mctx, obj->repr, (cnt + 1) * sizeof(*attr)); -+ obj->repr = old; -+ return (NULL); -+ } -+ memset(attr->pValue, 0, len); -+ if (old != NULL) { -+ memset(old, 0, cnt * sizeof(*attr)); -+ isc_mem_put(mctx, old, cnt * sizeof(*attr)); -+ } -+ obj->attrcnt++; -+ return (attr); -+} -+ -+#define DST_RET(a) { ret = a; goto err; } -+ -+isc_result_t -+pk11_parse_uri(pk11_object_t *obj, const char *label, -+ isc_mem_t *mctx, pk11_optype_t optype) -+{ -+ CK_ATTRIBUTE *attr; -+ pk11_token_t *token = NULL; -+ char *uri, *p, *a, *na, *v; -+ size_t len, l; -+ FILE *stream = NULL; -+ char pin[PINLEN]; -+ isc_boolean_t gotpin = ISC_FALSE; -+ isc_result_t ret; -+ -+ /* get values to work on */ -+ len = strlen(label) + 1; -+ uri = isc_mem_get(mctx, len); -+ if (uri == NULL) -+ return (ISC_R_NOMEMORY); -+ memmove(uri, label, len); -+ -+ /* get the URI scheme */ -+ p = strchr(uri, ':'); -+ if (p == NULL) -+ DST_RET(PK11_R_NOPROVIDER); -+ *p++ = '\0'; -+ if (strcmp(uri, "pkcs11") != 0) -+ DST_RET(PK11_R_NOPROVIDER); -+ -+ /* get attributes */ -+ for (na = p; na != NULL;) { -+ a = na; -+ p = strchr(a, ';'); -+ if (p == NULL) { -+ /* last attribute */ -+ na = NULL; -+ } else { -+ *p++ = '\0'; -+ na = p; -+ } -+ p = strchr(a, '='); -+ if (p != NULL) { -+ *p++ = '\0'; -+ v = p; -+ } else -+ v = a; -+ l = 0; -+ v = percent_decode(v, &l); -+ if (v == NULL) -+ DST_RET(PK11_R_NOPROVIDER); -+ if ((a == v) || (strcmp(a, "object") == 0)) { -+ /* object: CKA_LABEL */ -+ attr = pk11_attribute_bytype(obj, CKA_LABEL); -+ if (attr != NULL) -+ DST_RET(PK11_R_NOPROVIDER); -+ attr = push_attribute(obj, mctx, l); -+ if (attr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ attr->type = CKA_LABEL; -+ memmove(attr->pValue, v, l); -+ } else if (strcmp(a, "token") == 0) { -+ /* token: CK_TOKEN_INFO label */ -+ if (token == NULL) -+ for (token = ISC_LIST_HEAD(tokens); -+ token != NULL; -+ token = ISC_LIST_NEXT(token, link)) -+ if (pk11strcmp(v, l, token->name, 32)) -+ break; -+ } else if (strcmp(a, "manufacturer") == 0) { -+ /* manufacturer: CK_TOKEN_INFO manufacturerID */ -+ if (token == NULL) -+ for (token = ISC_LIST_HEAD(tokens); -+ token != NULL; -+ token = ISC_LIST_NEXT(token, link)) -+ if (pk11strcmp(v, l, token->manuf, 32)) -+ break; -+ } else if (strcmp(a, "serial") == 0) { -+ /* serial: CK_TOKEN_INFO serialNumber */ -+ if (token == NULL) -+ for (token = ISC_LIST_HEAD(tokens); -+ token != NULL; -+ token = ISC_LIST_NEXT(token, link)) -+ if (pk11strcmp(v, l, token->serial, 16)) -+ break; -+ } else if (strcmp(a, "model") == 0) { -+ /* model: CK_TOKEN_INFO model */ -+ if (token == NULL) -+ for (token = ISC_LIST_HEAD(tokens); -+ token != NULL; -+ token = ISC_LIST_NEXT(token, link)) -+ if (pk11strcmp(v, l, token->model, 16)) -+ break; -+ } else if (strcmp(a, "library-manufacturer") == 0) { -+ /* ignored */ -+ } else if (strcmp(a, "library-description") == 0) { -+ /* ignored */ -+ } else if (strcmp(a, "library-version") == 0) { -+ /* ignored */ -+ } else if (strcmp(a, "object-type") == 0) { -+ /* object-type: CKA_CLASS */ -+ /* only private makes sense */ -+ if (strcmp(v, "private") != 0) -+ DST_RET(PK11_R_NOPROVIDER); -+ } else if (strcmp(a, "id") == 0) { -+ /* id: CKA_ID */ -+ attr = pk11_attribute_bytype(obj, CKA_ID); -+ if (attr != NULL) -+ DST_RET(PK11_R_NOPROVIDER); -+ attr = push_attribute(obj, mctx, l); -+ if (attr == NULL) -+ DST_RET(ISC_R_NOMEMORY); -+ attr->type = CKA_ID; -+ memmove(attr->pValue, v, l); -+ } else if (strcmp(a, "pin-source") == 0) { -+ /* pin-source: PIN */ -+ ret = isc_stdio_open(v, "r", &stream); -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ memset(pin, 0, PINLEN); -+ ret = isc_stdio_read(pin, 1, PINLEN - 1, stream, NULL); -+ if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF)) -+ goto err; -+ ret = isc_stdio_close(stream); -+ stream = NULL; -+ if (ret != ISC_R_SUCCESS) -+ goto err; -+ gotpin = ISC_TRUE; -+ } else -+ DST_RET(PK11_R_NOPROVIDER); -+ } -+ -+ if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) && -+ (pk11_attribute_bytype(obj, CKA_ID) == NULL)) -+ DST_RET(ISC_R_NOTFOUND); -+ -+ if (token == NULL) { -+ if (optype == OP_RSA) -+ token = best_rsa_token; -+ else if (optype == OP_DSA) -+ token = best_dsa_token; -+ else if (optype == OP_DH) -+ token = best_dh_token; -+ else if (optype == OP_EC) -+ token = best_ec_token; -+ } -+ if (token == NULL) -+ DST_RET(ISC_R_NOTFOUND); -+ obj->slot = token->slotid; -+ if (gotpin) { -+ memmove(token->pin, pin, PINLEN); -+ obj->reqlogon = ISC_TRUE; -+ } -+ -+ ret = ISC_R_SUCCESS; -+ -+ err: -+ if (stream != NULL) -+ (void) isc_stdio_close(stream); -+ isc_mem_put(mctx, uri, len); -+ return (ret); -+} -+ -+void -+pk11_error_fatalcheck(const char *file, int line, -+ const char *funcname, CK_RV rv) -+{ -+ isc_error_fatal(file, line, "%s: Error = 0x%.8lX\n", funcname, rv); -+} -+ -+void -+pk11_dump_tokens(void) -+{ -+ pk11_token_t *token; -+ isc_boolean_t first; -+ -+ printf("DEFAULTS\n"); -+ printf("\trand_token=%p\n", rand_token); -+ printf("\tbest_rsa_token=%p\n", best_rsa_token); -+ printf("\tbest_dsa_token=%p\n", best_dsa_token); -+ printf("\tbest_dh_token=%p\n", best_dh_token); -+ printf("\tdigest_token=%p\n", digest_token); -+ printf("\tbest_ec_token=%p\n", best_ec_token); -+ printf("\tbest_gost_token=%p\n", best_gost_token); -+ printf("\taes_token=%p\n", aes_token); -+ -+ for (token = ISC_LIST_HEAD(tokens); -+ token != NULL; -+ token = ISC_LIST_NEXT(token, link)) { -+ printf("\nTOKEN\n"); -+ printf("\taddress=%p\n", token); -+ printf("\tslotID=%lu\n", token->slotid); -+ printf("\tlabel=%.32s\n", token->name); -+ printf("\tmanufacturerID=%.32s\n", token->manuf); -+ printf("\tmodel=%.16s\n", token->model); -+ printf("\tserialNumber=%.16s\n", token->serial); -+ printf("\tsupported operations=0x%x (", token->operations); -+ first = ISC_TRUE; -+ if (token->operations & (1 << OP_RAND)) { -+ if (!first) -+ printf(","); -+ first = ISC_FALSE; -+ printf("RAND"); -+ } -+ if (token->operations & (1 << OP_RSA)) { -+ if (!first) -+ printf(","); -+ first = ISC_FALSE; -+ printf("RSA"); -+ } -+ if (token->operations & (1 << OP_DSA)) { -+ if (!first) -+ printf(","); -+ first = ISC_FALSE; -+ printf("DSA"); -+ } -+ if (token->operations & (1 << OP_DH)) { -+ if (!first) -+ printf(","); -+ first = ISC_FALSE; -+ printf("DH"); -+ } -+ if (token->operations & (1 << OP_DIGEST)) { -+ if (!first) -+ printf(","); -+ first = ISC_FALSE; -+ printf("DIGEST"); -+ } -+ if (token->operations & (1 << OP_EC)) { -+ if (!first) -+ printf(","); -+ first = ISC_FALSE; -+ printf("EC"); -+ } -+ printf(")\n"); -+ } -+} -diff --git a/lib/isc/pk11_result.c b/lib/isc/pk11_result.c -new file mode 100644 -index 0000000..0ada753 ---- /dev/null -+++ b/lib/isc/pk11_result.c -@@ -0,0 +1,85 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+LIBISC_EXTERNAL_DATA isc_msgcat_t * pk11_msgcat = NULL; -+ -+static isc_once_t msgcat_once = ISC_ONCE_INIT; -+ -+static const char *text[PK11_R_NRESULTS] = { -+ "PKCS#11 initialization failed", /*%< 0 */ -+ "no PKCS#11 provider", /*%< 1 */ -+ "PKCS#11 provider has no random service", /*%< 2 */ -+ "PKCS#11 provider has no digest service", /*%< 3 */ -+ "PKCS#11 provider has no AES service", /*%< 4 */ -+}; -+ -+#define PK11_RESULT_RESULTSET 2 -+ -+static isc_once_t once = ISC_ONCE_INIT; -+ -+static void -+open_msgcat(void) { -+ isc_msgcat_open("libpk11.cat", &pk11_msgcat); -+} -+ -+void -+pk11_initmsgcat(void) { -+ -+ /* -+ * Initialize the PKCS#11 support's message catalog, -+ * pk11_msgcat, if it has not already been initialized. -+ */ -+ -+ RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS); -+} -+ -+static void -+initialize_action(void) { -+ isc_result_t result; -+ -+ result = isc_result_register(ISC_RESULTCLASS_PK11, PK11_R_NRESULTS, -+ text, pk11_msgcat, PK11_RESULT_RESULTSET); -+ if (result != ISC_R_SUCCESS) -+ UNEXPECTED_ERROR(__FILE__, __LINE__, -+ "isc_result_register() failed: %u", result); -+} -+ -+static void -+initialize(void) { -+ pk11_initmsgcat(); -+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); -+} -+ -+const char * -+pk11_result_totext(isc_result_t result) { -+ initialize(); -+ -+ return (isc_result_totext(result)); -+} -+ -+void -+pk11_result_register(void) { -+ initialize(); -+} -diff --git a/lib/isc/sha1.c b/lib/isc/sha1.c -index cce9603..caa721e 100644 ---- a/lib/isc/sha1.c -+++ b/lib/isc/sha1.c -@@ -44,8 +44,12 @@ - #include - #include - --#ifdef ISC_PLATFORM_OPENSSLHASH -+#if PKCS11CRYPTO -+#include -+#include -+#endif - -+#ifdef ISC_PLATFORM_OPENSSLHASH - void - isc_sha1_init(isc_sha1_t *context) - { -@@ -77,6 +81,50 @@ isc_sha1_final(isc_sha1_t *context, unsigned char *digest) { - EVP_DigestFinal(context, digest, NULL); - } - -+#elif PKCS11CRYPTO -+ -+void -+isc_sha1_init(isc_sha1_t *ctx) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA_1, NULL, 0 }; -+ -+ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech)); -+} -+ -+void -+isc_sha1_invalidate(isc_sha1_t *ctx) { -+ CK_BYTE garbage[ISC_SHA1_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA1_DIGESTLENGTH; -+ -+ if (ctx->handle == NULL) -+ return; -+ (void) pkcs_C_DigestFinal(ctx->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ pk11_return_session(ctx); -+} -+ -+void -+isc_sha1_update(isc_sha1_t *ctx, const unsigned char *buf, unsigned int len) { -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ DE_CONST(buf, pPart); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (ctx->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_sha1_final(isc_sha1_t *ctx, unsigned char *digest) { -+ CK_RV rv; -+ CK_ULONG len = ISC_SHA1_DIGESTLENGTH; -+ -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (ctx->session, (CK_BYTE_PTR) digest, &len)); -+ pk11_return_session(ctx); -+} -+ - #else - - #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) -diff --git a/lib/isc/sha2.c b/lib/isc/sha2.c -index db2e349..d7e0cf6 100644 ---- a/lib/isc/sha2.c -+++ b/lib/isc/sha2.c -@@ -63,6 +63,11 @@ - #include - #include - -+#if PKCS11CRYPTO -+#include -+#include -+#endif -+ - #ifdef ISC_PLATFORM_OPENSSLHASH - - void -@@ -219,6 +224,272 @@ isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) { - } - } - -+#elif PKCS11CRYPTO -+ -+void -+isc_sha224_init(isc_sha224_t *context) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA224, NULL, 0 }; -+ -+ if (context == (isc_sha224_t *)0) { -+ return; -+ } -+ RUNTIME_CHECK(pk11_get_session(context, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ PK11_FATALCHECK(pkcs_C_DigestInit, (context->session, &mech)); -+} -+ -+void -+isc_sha224_invalidate(isc_sha224_t *context) { -+ CK_BYTE garbage[ISC_SHA224_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA224_DIGESTLENGTH; -+ -+ if (context->handle == NULL) -+ return; -+ (void) pkcs_C_DigestFinal(context->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ pk11_return_session(context); -+} -+ -+void -+isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) { -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ if (len == 0U) { -+ /* Calling with no data is valid - we do nothing */ -+ return; -+ } -+ -+ /* Sanity check: */ -+ REQUIRE(context != (isc_sha224_t *)0 && data != (isc_uint8_t*)0); -+ -+ DE_CONST(data, pPart); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (context->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) { -+ CK_RV rv; -+ CK_ULONG len = ISC_SHA224_DIGESTLENGTH; -+ -+ /* Sanity check: */ -+ REQUIRE(context != (isc_sha224_t *)0); -+ -+ /* If no digest buffer is passed, we don't bother doing this: */ -+ if (digest != (isc_uint8_t*)0) { -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (context->session, -+ (CK_BYTE_PTR) digest, -+ &len)); -+ } else { -+ CK_BYTE garbage[ISC_SHA224_DIGESTLENGTH]; -+ -+ (void) pkcs_C_DigestFinal(context->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ } -+ pk11_return_session(context); -+} -+ -+void -+isc_sha256_init(isc_sha256_t *context) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA256, NULL, 0 }; -+ -+ if (context == (isc_sha256_t *)0) { -+ return; -+ } -+ RUNTIME_CHECK(pk11_get_session(context, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ PK11_FATALCHECK(pkcs_C_DigestInit, (context->session, &mech)); -+} -+ -+void -+isc_sha256_invalidate(isc_sha256_t *context) { -+ CK_BYTE garbage[ISC_SHA256_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA256_DIGESTLENGTH; -+ -+ if (context->handle == NULL) -+ return; -+ (void) pkcs_C_DigestFinal(context->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ pk11_return_session(context); -+} -+ -+void -+isc_sha256_update(isc_sha256_t *context, const isc_uint8_t* data, size_t len) { -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ if (len == 0U) { -+ /* Calling with no data is valid - we do nothing */ -+ return; -+ } -+ -+ /* Sanity check: */ -+ REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0); -+ -+ DE_CONST(data, pPart); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (context->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) { -+ CK_RV rv; -+ CK_ULONG len = ISC_SHA256_DIGESTLENGTH; -+ -+ /* Sanity check: */ -+ REQUIRE(context != (isc_sha256_t *)0); -+ -+ /* If no digest buffer is passed, we don't bother doing this: */ -+ if (digest != (isc_uint8_t*)0) { -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (context->session, -+ (CK_BYTE_PTR) digest, -+ &len)); -+ } else { -+ CK_BYTE garbage[ISC_SHA256_DIGESTLENGTH]; -+ -+ (void) pkcs_C_DigestFinal(context->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ } -+ pk11_return_session(context); -+} -+ -+void -+isc_sha512_init(isc_sha512_t *context) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA512, NULL, 0 }; -+ -+ if (context == (isc_sha512_t *)0) { -+ return; -+ } -+ RUNTIME_CHECK(pk11_get_session(context, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ PK11_FATALCHECK(pkcs_C_DigestInit, (context->session, &mech)); -+} -+ -+void -+isc_sha512_invalidate(isc_sha512_t *context) { -+ CK_BYTE garbage[ISC_SHA512_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA512_DIGESTLENGTH; -+ -+ if (context->handle == NULL) -+ return; -+ (void) pkcs_C_DigestFinal(context->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ pk11_return_session(context); -+} -+ -+void -+isc_sha512_update(isc_sha512_t *context, const isc_uint8_t* data, size_t len) { -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ if (len == 0U) { -+ /* Calling with no data is valid - we do nothing */ -+ return; -+ } -+ -+ /* Sanity check: */ -+ REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0); -+ -+ DE_CONST(data, pPart); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (context->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) { -+ CK_RV rv; -+ CK_ULONG len = ISC_SHA512_DIGESTLENGTH; -+ -+ /* Sanity check: */ -+ REQUIRE(context != (isc_sha512_t *)0); -+ -+ /* If no digest buffer is passed, we don't bother doing this: */ -+ if (digest != (isc_uint8_t*)0) { -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (context->session, -+ (CK_BYTE_PTR) digest, -+ &len)); -+ } else { -+ CK_BYTE garbage[ISC_SHA512_DIGESTLENGTH]; -+ -+ (void) pkcs_C_DigestFinal(context->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ } -+ pk11_return_session(context); -+} -+ -+void -+isc_sha384_init(isc_sha384_t *context) { -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_SHA384, NULL, 0 }; -+ -+ if (context == (isc_sha384_t *)0) { -+ return; -+ } -+ RUNTIME_CHECK(pk11_get_session(context, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS); -+ PK11_FATALCHECK(pkcs_C_DigestInit, (context->session, &mech)); -+} -+ -+void -+isc_sha384_invalidate(isc_sha384_t *context) { -+ CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH]; -+ CK_ULONG len = ISC_SHA384_DIGESTLENGTH; -+ -+ if (context->handle == NULL) -+ return; -+ (void) pkcs_C_DigestFinal(context->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ pk11_return_session(context); -+} -+ -+void -+isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) { -+ CK_RV rv; -+ CK_BYTE_PTR pPart; -+ -+ if (len == 0U) { -+ /* Calling with no data is valid - we do nothing */ -+ return; -+ } -+ -+ /* Sanity check: */ -+ REQUIRE(context != (isc_sha384_t *)0 && data != (isc_uint8_t*)0); -+ -+ DE_CONST(data, pPart); -+ PK11_FATALCHECK(pkcs_C_DigestUpdate, -+ (context->session, pPart, (CK_ULONG) len)); -+} -+ -+void -+isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) { -+ CK_RV rv; -+ CK_ULONG len = ISC_SHA384_DIGESTLENGTH; -+ -+ /* Sanity check: */ -+ REQUIRE(context != (isc_sha384_t *)0); -+ -+ /* If no digest buffer is passed, we don't bother doing this: */ -+ if (digest != (isc_uint8_t*)0) { -+ PK11_FATALCHECK(pkcs_C_DigestFinal, -+ (context->session, -+ (CK_BYTE_PTR) digest, -+ &len)); -+ } else { -+ CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH]; -+ -+ (void) pkcs_C_DigestFinal(context->session, garbage, &len); -+ memset(garbage, 0, sizeof(garbage)); -+ } -+ pk11_return_session(context); -+} -+ - #else - - /* -@@ -1312,6 +1583,8 @@ isc_sha224_end(isc_sha224_t *context, char buffer[]) { - } else { - #ifdef ISC_PLATFORM_OPENSSLHASH - EVP_MD_CTX_cleanup(context); -+#elif PKCS11CRYPTO -+ pk11_return_session(context); - #else - memset(context, 0, sizeof(*context)); - #endif -@@ -1351,6 +1624,8 @@ isc_sha256_end(isc_sha256_t *context, char buffer[]) { - } else { - #ifdef ISC_PLATFORM_OPENSSLHASH - EVP_MD_CTX_cleanup(context); -+#elif PKCS11CRYPTO -+ pk11_return_session(context); - #else - memset(context, 0, sizeof(*context)); - #endif -@@ -1390,6 +1665,8 @@ isc_sha512_end(isc_sha512_t *context, char buffer[]) { - } else { - #ifdef ISC_PLATFORM_OPENSSLHASH - EVP_MD_CTX_cleanup(context); -+#elif PKCS11CRYPTO -+ pk11_return_session(context); - #else - memset(context, 0, sizeof(*context)); - #endif -@@ -1429,6 +1706,8 @@ isc_sha384_end(isc_sha384_t *context, char buffer[]) { - } else { - #ifdef ISC_PLATFORM_OPENSSLHASH - EVP_MD_CTX_cleanup(context); -+#elif PKCS11CRYPTO -+ pk11_return_session(context); - #else - memset(context, 0, sizeof(*context)); - #endif -diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in -index c1411cb..0595fa2 100644 ---- a/lib/isc/unix/Makefile.in -+++ b/lib/isc/unix/Makefile.in -@@ -29,14 +29,14 @@ CDEFINES = - CWARNINGS = - - # Alphabetically --OBJS = @ISC_IPV6_O@ \ -+OBJS = @ISC_IPV6_O@ @ISC_PK11_API_O@ \ - app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \ - fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \ - os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \ - strerror.@O@ syslog.@O@ time.@O@ - - # Alphabetically --SRCS = @ISC_IPV6_C@ \ -+SRCS = @ISC_IPV6_C@ @ISC_PK11_API_C@ \ - app.c dir.c entropy.c errno2result.c file.c \ - fsaccess.c interfaceiter.c keyboard.c net.c \ - os.c resource.c socket.c stdio.c stdtime.c \ -diff --git a/lib/isc/unix/include/Makefile.in b/lib/isc/unix/include/Makefile.in -index 46c243e..354e6c8 100644 ---- a/lib/isc/unix/include/Makefile.in -+++ b/lib/isc/unix/include/Makefile.in -@@ -19,7 +19,7 @@ srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ - --SUBDIRS = isc -+SUBDIRS = isc pkcs11 - TARGETS = - - @BIND9_MAKE_RULES@ -diff --git a/lib/isc/unix/include/pkcs11/Makefile.in b/lib/isc/unix/include/pkcs11/Makefile.in -new file mode 100644 -index 0000000..8b175f4 ---- /dev/null -+++ b/lib/isc/unix/include/pkcs11/Makefile.in -@@ -0,0 +1,33 @@ -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id: Makefile.in,v 1.4 2007/06/19 23:47:23 tbox Exp $ -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+HEADERS = cryptoki.h -+SUBDIRS = -+TARGETS = -+ -+@BIND9_MAKE_RULES@ -+ -+installdirs: -+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pkcs11 -+ -+install:: installdirs -+ for i in ${HEADERS}; do \ -+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/pkcs11 ; \ -+ done -diff --git a/lib/isc/unix/include/pkcs11/cryptoki.h b/lib/isc/unix/include/pkcs11/cryptoki.h -new file mode 100644 -index 0000000..7dc48b0 ---- /dev/null -+++ b/lib/isc/unix/include/pkcs11/cryptoki.h -@@ -0,0 +1,66 @@ -+/* cryptoki.h include file for PKCS #11. */ -+/* -+ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE -+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+/* $Revision: 1.3 $ */ -+ -+/* -+ * Portions Copyright RSA Security Inc. -+ * -+ * License to copy and use this software is granted provided that it is -+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface -+ * (Cryptoki)" in all material mentioning or referencing this software. -+ -+ * License is also granted to make and use derivative works provided that -+ * such works are identified as "derived from the RSA Security Inc. PKCS #11 -+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or -+ * referencing the derived work. -+ -+ * RSA Security Inc. makes no representations concerning either the -+ * merchantability of this software or the suitability of this software for -+ * any particular purpose. It is provided "as is" without express or implied -+ * warranty of any kind. -+ */ -+ -+/* This is a sample file containing the top level include directives -+ * for building Unix Cryptoki libraries and applications. -+ */ -+ -+#ifndef ___CRYPTOKI_H_INC___ -+#define ___CRYPTOKI_H_INC___ -+ -+#define CK_PTR * -+ -+#define CK_DEFINE_FUNCTION(returnType, name) \ -+ returnType name -+ -+#define CK_DECLARE_FUNCTION(returnType, name) \ -+ returnType name -+ -+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ -+ returnType (* name) -+ -+#define CK_CALLBACK_FUNCTION(returnType, name) \ -+ returnType (* name) -+ -+/* NULL is in unistd.h */ -+#include -+#define NULL_PTR NULL -+ -+#undef CK_PKCS11_FUNCTION_INFO -+ -+#include -+ -+#endif /* ___CRYPTOKI_H_INC___ */ -diff --git a/lib/isc/unix/pk11_api.c b/lib/isc/unix/pk11_api.c -new file mode 100644 -index 0000000..9ccb959 ---- /dev/null -+++ b/lib/isc/unix/pk11_api.c -@@ -0,0 +1,673 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define KEEP_PKCS11_NAMES -+#include -+#include -+ -+static void *hPK11 = NULL; -+ -+CK_RV -+pkcs_C_Initialize(CK_VOID_PTR pReserved) { -+ CK_C_Initialize sym; -+ -+ if (hPK11 != NULL) -+ return (CKR_LIBRARY_ALREADY_INITIALIZED); -+ -+ hPK11 = dlopen(pk11_get_lib_name(), RTLD_NOW); -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ sym = (CK_C_Initialize)dlsym(hPK11, "C_Initialize"); -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(pReserved); -+} -+ -+CK_RV -+pkcs_C_Finalize(CK_VOID_PTR pReserved) { -+ CK_C_Finalize sym; -+ CK_RV rv; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ sym = (CK_C_Finalize)dlsym(hPK11, "C_Finalize"); -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ rv = (*sym)(pReserved); -+ if ((rv == CKR_OK) && (dlclose(hPK11) != 0)) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ hPK11 = NULL; -+ return (rv); -+} -+ -+CK_RV -+pkcs_C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, -+ CK_ULONG_PTR pulCount) -+{ -+ static CK_C_GetSlotList sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_GetSlotList)dlsym(hPK11, "C_GetSlotList"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(tokenPresent, pSlotList, pulCount); -+} -+ -+CK_RV -+pkcs_C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) { -+ static CK_C_GetTokenInfo sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_GetTokenInfo)dlsym(hPK11, "C_GetTokenInfo"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(slotID, pInfo); -+} -+ -+CK_RV -+pkcs_C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, -+ CK_MECHANISM_INFO_PTR pInfo) -+{ -+ static CK_C_GetMechanismInfo sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_GetMechanismInfo)dlsym(hPK11, -+ "C_GetMechanismInfo"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(slotID, type, pInfo); -+} -+ -+CK_RV -+pkcs_C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, -+ CK_VOID_PTR pApplication, -+ CK_RV (*Notify) (CK_SESSION_HANDLE hSession, -+ CK_NOTIFICATION event, -+ CK_VOID_PTR pApplication), -+ CK_SESSION_HANDLE_PTR phSession) -+{ -+ static CK_C_OpenSession sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ hPK11 = dlopen(pk11_get_lib_name(), RTLD_NOW); -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_OpenSession)dlsym(hPK11, "C_OpenSession"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(slotID, flags, pApplication, Notify, phSession); -+} -+ -+CK_RV -+pkcs_C_CloseSession(CK_SESSION_HANDLE hSession) { -+ static CK_C_CloseSession sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_CloseSession)dlsym(hPK11, "C_CloseSession"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession); -+} -+ -+CK_RV -+pkcs_C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, -+ CK_CHAR_PTR pPin, CK_ULONG usPinLen) -+{ -+ static CK_C_Login sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_Login)dlsym(hPK11, "C_Login"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, userType, pPin, usPinLen); -+} -+ -+CK_RV -+pkcs_C_Logout(CK_SESSION_HANDLE hSession) { -+ static CK_C_Logout sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_Logout)dlsym(hPK11, "C_Logout"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession); -+} -+ -+CK_RV -+pkcs_C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, -+ CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phObject) -+{ -+ static CK_C_CreateObject sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_CreateObject)dlsym(hPK11, "C_CreateObject"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pTemplate, usCount, phObject); -+} -+ -+CK_RV -+pkcs_C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) { -+ static CK_C_DestroyObject sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_DestroyObject)dlsym(hPK11, "C_DestroyObject"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, hObject); -+} -+ -+CK_RV -+pkcs_C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, -+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount) -+{ -+ static CK_C_GetAttributeValue sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_GetAttributeValue)dlsym(hPK11, -+ "C_GetAttributeValue"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, hObject, pTemplate, usCount); -+} -+ -+CK_RV -+pkcs_C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, -+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount) -+{ -+ static CK_C_SetAttributeValue sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_SetAttributeValue)dlsym(hPK11, -+ "C_SetAttributeValue"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, hObject, pTemplate, usCount); -+} -+ -+CK_RV -+pkcs_C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, -+ CK_ULONG usCount) -+{ -+ static CK_C_FindObjectsInit sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_FindObjectsInit)dlsym(hPK11, "C_FindObjectsInit"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pTemplate, usCount); -+} -+ -+CK_RV -+pkcs_C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, -+ CK_ULONG usMaxObjectCount, CK_ULONG_PTR pusObjectCount) -+{ -+ static CK_C_FindObjects sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_FindObjects)dlsym(hPK11, "C_FindObjects"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, phObject, usMaxObjectCount, pusObjectCount); -+} -+ -+CK_RV -+pkcs_C_FindObjectsFinal(CK_SESSION_HANDLE hSession) -+{ -+ static CK_C_FindObjectsFinal sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_FindObjectsFinal)dlsym(hPK11, -+ "C_FindObjectsFinal"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession); -+} -+ -+CK_RV -+pkcs_C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey) -+{ -+ static CK_C_EncryptInit sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_EncryptInit)dlsym(hPK11, "C_EncryptInit"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pMechanism, hKey); -+} -+ -+CK_RV -+pkcs_C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, -+ CK_ULONG_PTR pulEncryptedDataLen) -+{ -+ static CK_C_Encrypt sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_Encrypt)dlsym(hPK11, "C_Encrypt"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pData, ulDataLen, -+ pEncryptedData, pulEncryptedDataLen); -+} -+ -+CK_RV -+pkcs_C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) { -+ static CK_C_DigestInit sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_DigestInit)dlsym(hPK11, "C_DigestInit"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pMechanism); -+} -+ -+CK_RV -+pkcs_C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen) -+{ -+ static CK_C_DigestUpdate sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_DigestUpdate)dlsym(hPK11, "C_DigestUpdate"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pPart, ulPartLen); -+} -+ -+CK_RV -+pkcs_C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, -+ CK_ULONG_PTR pulDigestLen) -+{ -+ static CK_C_DigestFinal sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_DigestFinal)dlsym(hPK11, "C_DigestFinal"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pDigest, pulDigestLen); -+} -+ -+CK_RV -+pkcs_C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey) -+{ -+ static CK_C_SignInit sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_SignInit)dlsym(hPK11, "C_SignInit"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pMechanism, hKey); -+} -+ -+CK_RV -+pkcs_C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, -+ CK_ULONG_PTR pulSignatureLen) -+{ -+ static CK_C_Sign sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_Sign)dlsym(hPK11, "C_Sign"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pData, ulDataLen, pSignature, pulSignatureLen); -+} -+ -+CK_RV -+pkcs_C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen) -+{ -+ static CK_C_SignUpdate sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_SignUpdate)dlsym(hPK11, "C_SignUpdate"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pPart, ulPartLen); -+} -+ -+CK_RV -+pkcs_C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, -+ CK_ULONG_PTR pulSignatureLen) -+{ -+ static CK_C_SignFinal sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_SignFinal)dlsym(hPK11, "C_SignFinal"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pSignature, pulSignatureLen); -+} -+ -+CK_RV -+pkcs_C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey) -+{ -+ static CK_C_VerifyInit sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_VerifyInit)dlsym(hPK11, "C_VerifyInit"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pMechanism, hKey); -+} -+ -+CK_RV -+pkcs_C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, -+ CK_ULONG ulSignatureLen) -+{ -+ static CK_C_Verify sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_Verify)dlsym(hPK11, "C_Verify"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pData, ulDataLen, pSignature, ulSignatureLen); -+} -+ -+CK_RV -+pkcs_C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen) -+{ -+ static CK_C_VerifyUpdate sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_VerifyUpdate)dlsym(hPK11, "C_VerifyUpdate"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pPart, ulPartLen); -+} -+ -+CK_RV -+pkcs_C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, -+ CK_ULONG ulSignatureLen) -+{ -+ static CK_C_VerifyFinal sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_VerifyFinal)dlsym(hPK11, "C_VerifyFinal"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pSignature, ulSignatureLen); -+} -+ -+CK_RV -+pkcs_C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, -+ CK_OBJECT_HANDLE_PTR phKey) -+{ -+ static CK_C_GenerateKey sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_GenerateKey)dlsym(hPK11, "C_GenerateKey"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pMechanism, pTemplate, ulCount, phKey); -+} -+ -+CK_RV -+pkcs_C_GenerateKeyPair(CK_SESSION_HANDLE hSession, -+ CK_MECHANISM_PTR pMechanism, -+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, -+ CK_ULONG usPublicKeyAttributeCount, -+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, -+ CK_ULONG usPrivateKeyAttributeCount, -+ CK_OBJECT_HANDLE_PTR phPrivateKey, -+ CK_OBJECT_HANDLE_PTR phPublicKey) -+{ -+ static CK_C_GenerateKeyPair sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_GenerateKeyPair)dlsym(hPK11, "C_GenerateKeyPair"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, -+ pMechanism, -+ pPublicKeyTemplate, -+ usPublicKeyAttributeCount, -+ pPrivateKeyTemplate, -+ usPrivateKeyAttributeCount, -+ phPrivateKey, -+ phPublicKey); -+} -+ -+CK_RV -+pkcs_C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, -+ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) -+{ -+ static CK_C_DeriveKey sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_DeriveKey)dlsym(hPK11, "C_DeriveKey"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, -+ pMechanism, -+ hBaseKey, -+ pTemplate, -+ ulAttributeCount, -+ phKey); -+} -+ -+CK_RV -+pkcs_C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, -+ CK_ULONG ulSeedLen) -+{ -+ static CK_C_SeedRandom sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_SeedRandom)dlsym(hPK11, "C_SeedRandom"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, pSeed, ulSeedLen); -+} -+ -+CK_RV -+pkcs_C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData, -+ CK_ULONG ulRandomLen) -+{ -+ static CK_C_GenerateRandom sym = NULL; -+ static void *pPK11 = NULL; -+ -+ if (hPK11 == NULL) -+ return (CKR_LIBRARY_FAILED_TO_LOAD); -+ if ((sym == NULL) || (hPK11 != pPK11)) { -+ pPK11 = hPK11; -+ sym = (CK_C_GenerateRandom)dlsym(hPK11, "C_GenerateRandom"); -+ } -+ if (sym == NULL) -+ return (CKR_SYMBOL_RESOLUTION_FAILED); -+ return (*sym)(hSession, RandomData, ulRandomLen); -+} --- -2.1.0 - diff --git a/SOURCES/bind-9.9.1-P2-dlz-libdb.patch b/SOURCES/bind-9.9.1-P2-dlz-libdb.patch index 7c62d87..866ed8f 100644 --- a/SOURCES/bind-9.9.1-P2-dlz-libdb.patch +++ b/SOURCES/bind-9.9.1-P2-dlz-libdb.patch @@ -1,26 +1,30 @@ -diff -up bind-9.9.4/contrib/dlz/config.dlz.in.libdb bind-9.9.4/contrib/dlz/config.dlz.in ---- bind-9.9.4/contrib/dlz/config.dlz.in.libdb 2014-01-06 13:24:24.669256364 +0100 -+++ bind-9.9.4/contrib/dlz/config.dlz.in 2014-01-06 13:26:29.861420493 +0100 -@@ -257,7 +257,7 @@ case "$use_dlz_bdb" in +diff -up bind-9.10.1b1/contrib/dlz/config.dlz.in.libdb bind-9.10.1b1/contrib/dlz/config.dlz.in +--- bind-9.10.1b1/contrib/dlz/config.dlz.in.libdb 2014-08-04 12:33:09.320735111 +0200 ++++ bind-9.10.1b1/contrib/dlz/config.dlz.in 2014-08-04 12:41:46.888241910 +0200 +@@ -263,7 +263,7 @@ case "$use_dlz_bdb" in # Check other locations for includes. # Order is important (sigh). -- bdb_incdirs="/ /db48/ /db47/ /db46/ /db45/ /db44/ /db43/ /db42/ /db41/ /db4/ /db/" -+ bdb_incdirs="/ /db48/ /db47/ /db46/ /db45/ /db44/ /db43/ /db42/ /db41/ /db4/ /libdb/ /db/" - for d in $bdb_incdirs +- bdb_incdirs="/db53 /db51 /db48 /db47 /db46 /db45 /db44 /db43 /db42 /db41 /db4 /db" ++ bdb_incdirs="/db53 /db51 /db48 /db47 /db46 /db45 /db44 /db43 /db42 /db41 /db4 /libdb /db" + # include a blank element first + for d in "" $bdb_incdirs do - if test -f "$dd/include${d}db.h" -@@ -283,13 +283,7 @@ case "$use_dlz_bdb" in +@@ -288,16 +288,9 @@ case "$use_dlz_bdb" in + bdb_libnames="db53 db-5.3 db51 db-5.1 db48 db-4.8 db47 db-4.7 db46 db-4.6 db45 db-4.5 db44 db-4.4 db43 db-4.3 db42 db-4.2 db41 db-4.1 db" + for d in $bdb_libnames do - if test -f "$dd/${target_lib}/lib${d}.so" +- if test "$dd" = "/usr" ++ if test -f "$dd/${target_lib}/lib${d}.so" then -- if test "$dd" != "/usr" +- AC_CHECK_LIB($d, db_create, dlz_bdb_libs="-l${d}") +- if test $dlz_bdb_libs != "yes" - then -- dlz_bdb_libs="-L${dd}/${target_lib} " -- else -- dlz_bdb_libs="" +- break - fi -- dlz_bdb_libs="${dlz_bdb_libs}-l${d}" +- elif test -f "$dd/${target_lib}/lib${d}.so" +- then +- dlz_bdb_libs="-L${dd}/${target_lib} -l${d}" + dlz_bdb_libs="-L${dd}/${target_lib}/libdb -l${d}" break fi diff --git a/SOURCES/bind-9.9.1-P2-multlib-conflict.patch b/SOURCES/bind-9.9.1-P2-multlib-conflict.patch index 03d5f5c..96506dd 100644 --- a/SOURCES/bind-9.9.1-P2-multlib-conflict.patch +++ b/SOURCES/bind-9.9.1-P2-multlib-conflict.patch @@ -1,8 +1,9 @@ -diff -up bind-9.9.3rc2/config.h.in.multlib-conflict bind-9.9.3rc2/config.h.in ---- bind-9.9.3rc2/config.h.in.multlib-conflict 2013-04-30 08:38:46.000000000 +0200 -+++ bind-9.9.3rc2/config.h.in 2013-05-13 12:10:22.514870894 +0200 -@@ -416,7 +416,7 @@ int sigwait(const unsigned int *set, int - #undef PORT_NONBLOCK +diff --git a/config.h.in b/config.h.in +index e1364dd921..1dc65cfb21 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -588,7 +588,7 @@ int sigwait(const unsigned int *set, int *sig); + #undef PREFER_GOSTASN1 /* The size of `void *', as computed by sizeof. */ -#undef SIZEOF_VOID_P @@ -10,24 +11,42 @@ diff -up bind-9.9.3rc2/config.h.in.multlib-conflict bind-9.9.3rc2/config.h.in /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS -diff -up bind-9.9.3rc2/configure.in.multlib-conflict bind-9.9.3rc2/configure.in ---- bind-9.9.3rc2/configure.in.multlib-conflict 2013-05-13 12:10:22.481870901 +0200 -+++ bind-9.9.3rc2/configure.in 2013-05-13 12:10:22.515870894 +0200 -@@ -2251,7 +2251,9 @@ int getnameinfo(const struct sockaddr *, - size_t, char *, size_t, int);], +diff --git a/configure.in b/configure.in +index 73b1c8ccbb..129fc3f311 100644 +--- a/configure.in ++++ b/configure.in +@@ -3523,14 +3523,14 @@ AC_TRY_COMPILE([ + #include + #include + int getnameinfo(const struct sockaddr *, socklen_t, char *, +- socklen_t, char *, socklen_t, unsigned int);], ++ socklen_t, char *, socklen_t, int);], [ return (0);], - [AC_MSG_RESULT(size_t for buflen; int for flags) -- AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, size_t) -+ # Changed to solve multilib conflict on Fedora -+ #AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, size_t) -+ AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, socklen_t) - AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, int)], +- [AC_MSG_RESULT(socklen_t for buflen; u_int for flags) ++ [AC_MSG_RESULT(socklen_t for buflen; int for flags) + AC_DEFINE(IRS_GETNAMEINFO_SOCKLEN_T, socklen_t, + [Define to the sockaddr length type used by getnameinfo(3).]) + AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, socklen_t, + [Define to the buffer length type used by getnameinfo(3).]) +- AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, unsigned int, ++ AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, int, + [Define to the flags type used by getnameinfo(3).])], + [AC_TRY_COMPILE([ + #include +@@ -3557,7 +3557,7 @@ int getnameinfo(const struct sockaddr *, size_t, char *, [AC_MSG_RESULT(not match any subspecies; assume standard definition) + AC_DEFINE(IRS_GETNAMEINFO_SOCKLEN_T, socklen_t) AC_DEFINE(IRS_GETNAMEINFO_BUFLEN_T, socklen_t) -diff -up bind-9.9.3rc2/isc-config.sh.in.multlib-conflict bind-9.9.3rc2/isc-config.sh.in ---- bind-9.9.3rc2/isc-config.sh.in.multlib-conflict 2013-04-30 08:38:46.000000000 +0200 -+++ bind-9.9.3rc2/isc-config.sh.in 2013-05-13 12:26:40.258698745 +0200 -@@ -21,7 +21,18 @@ prefix=@prefix@ +-AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, int)])])]) ++AC_DEFINE(IRS_GETNAMEINFO_FLAGS_T, unsigned int)])])]) + + # + # ...and same for gai_strerror(). +diff --git a/isc-config.sh.in b/isc-config.sh.in +index a8a0a89e88..b5e94ed13e 100644 +--- a/isc-config.sh.in ++++ b/isc-config.sh.in +@@ -13,7 +13,18 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ exec_prefix_set= includedir=@includedir@ @@ -47,9 +66,9 @@ diff -up bind-9.9.3rc2/isc-config.sh.in.multlib-conflict bind-9.9.3rc2/isc-confi usage() { -@@ -133,6 +144,16 @@ if test x"$echo_libs" = x"true"; then +@@ -132,6 +143,16 @@ if test x"$echo_libs" = x"true"; then if test x"${exec_prefix_set}" = x"true"; then - includes="-L${exec_prefix}/lib" + libs="-L${exec_prefix}/lib" else + if [ ! -x $libdir/libisc.so ] ; then + if [ ! -x $sec_libdir/libisc.so ] ; then @@ -63,4 +82,4 @@ diff -up bind-9.9.3rc2/isc-config.sh.in.multlib-conflict bind-9.9.3rc2/isc-confi + fi libs="-L${libdir}" fi - if test x"$liblwres" = x"true" ; then + if test x"$libirs" = x"true" ; then diff --git a/SOURCES/bind-9.9.3-include-update-h.patch b/SOURCES/bind-9.9.3-include-update-h.patch deleted file mode 100644 index f7ea486..0000000 --- a/SOURCES/bind-9.9.3-include-update-h.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up bind-9.9.3/lib/dns/include/dns/Makefile.in.update bind-9.9.3/lib/dns/include/dns/Makefile.in ---- bind-9.9.3/lib/dns/include/dns/Makefile.in.update 2013-06-03 09:29:41.049197873 +0200 -+++ bind-9.9.3/lib/dns/include/dns/Makefile.in 2013-06-03 09:30:09.229213170 +0200 -@@ -30,7 +30,7 @@ HEADERS = acl.h adb.h byaddr.h cache.h c - rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \ - rdataslab.h rdatatype.h request.h resolver.h result.h \ - rootns.h rpz.h sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h \ -- tcpmsg.h time.h tkey.h tsig.h ttl.h types.h \ -+ tcpmsg.h time.h tkey.h tsig.h ttl.h types.h update.h\ - validator.h version.h view.h xfrin.h zone.h zonekey.h zt.h \ - forward.h rrl.h - diff --git a/SOURCES/bind-95-rh452060.patch b/SOURCES/bind-95-rh452060.patch index 58808b0..dac3a8d 100644 --- a/SOURCES/bind-95-rh452060.patch +++ b/SOURCES/bind-95-rh452060.patch @@ -1,10 +1,12 @@ -diff -up bind-9.5.0-P2/bin/dig/dighost.c.rh452060 bind-9.5.0-P2/bin/dig/dighost.c ---- bind-9.5.0-P2/bin/dig/dighost.c.rh452060 2008-12-01 22:30:01.000000000 +0100 -+++ bind-9.5.0-P2/bin/dig/dighost.c 2008-12-01 22:30:07.000000000 +0100 -@@ -1280,6 +1280,12 @@ clear_query(dig_query_t *query) { - - debug("clear_query(%p)", query); +diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c +index f657c30..ff9a2d2 100644 +--- a/bin/dig/dighost.c ++++ b/bin/dig/dighost.c +@@ -1694,6 +1694,13 @@ clear_query(dig_query_t *query) { + if (query->timer != NULL) + isc_timer_detach(&query->timer); ++ + if (query->waiting_senddone) { + debug("send_done not yet called"); + query->pending_free = ISC_TRUE; @@ -14,7 +16,7 @@ diff -up bind-9.5.0-P2/bin/dig/dighost.c.rh452060 bind-9.5.0-P2/bin/dig/dighost. lookup = query->lookup; if (lookup->current_query == query) -@@ -1301,10 +1307,7 @@ clear_query(dig_query_t *query) { +@@ -1719,10 +1726,7 @@ clear_query(dig_query_t *query) { isc_mempool_put(commctx, query->recvspace); isc_buffer_invalidate(&query->recvbuf); isc_buffer_invalidate(&query->lengthbuf); @@ -26,7 +28,7 @@ diff -up bind-9.5.0-P2/bin/dig/dighost.c.rh452060 bind-9.5.0-P2/bin/dig/dighost. } /*% -@@ -2175,9 +2178,9 @@ send_done(isc_task_t *_task, isc_event_t +@@ -2811,9 +2815,9 @@ send_done(isc_task_t *_task, isc_event_t *event) { isc_event_free(&event); if (query->pending_free) diff --git a/SOURCES/bind-99-socket-maxevents.patch b/SOURCES/bind-99-socket-maxevents.patch deleted file mode 100644 index 75fe038..0000000 --- a/SOURCES/bind-99-socket-maxevents.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c -index 05eaeaa..82d0d16 100644 ---- a/lib/isc/unix/socket.c -+++ b/lib/isc/unix/socket.c -@@ -214,7 +214,7 @@ typedef enum { poll_idle, poll_active, poll_checking } pollstate_t; - */ - #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) - #ifndef ISC_SOCKET_MAXEVENTS --#define ISC_SOCKET_MAXEVENTS 64 -+#define ISC_SOCKET_MAXEVENTS 2048 - #endif - #endif - diff --git a/SOURCES/bind-nonexec.patch b/SOURCES/bind-nonexec.patch deleted file mode 100644 index 780ffed..0000000 --- a/SOURCES/bind-nonexec.patch +++ /dev/null @@ -1,72 +0,0 @@ -diff -up bind-9.7.0rc2/lib/bind9/Makefile.in.nonexec bind-9.7.0rc2/lib/bind9/Makefile.in ---- bind-9.7.0rc2/lib/bind9/Makefile.in.nonexec 2009-12-06 00:31:40.000000000 +0100 -+++ bind-9.7.0rc2/lib/bind9/Makefile.in 2010-01-28 12:13:33.406696161 +0100 -@@ -78,7 +78,7 @@ installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libbind9.@A@ ${DESTDIR}${libdir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libbind9.@A@ ${DESTDIR}${libdir} - - clean distclean:: - rm -f libbind9.@A@ timestamp -diff -up bind-9.7.0rc2/lib/dns/Makefile.in.nonexec bind-9.7.0rc2/lib/dns/Makefile.in ---- bind-9.7.0rc2/lib/dns/Makefile.in.nonexec 2009-12-06 00:31:40.000000000 +0100 -+++ bind-9.7.0rc2/lib/dns/Makefile.in 2010-01-28 12:13:33.406696161 +0100 -@@ -131,7 +131,7 @@ installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libdns.@A@ ${DESTDIR}${libdir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns.@A@ ${DESTDIR}${libdir} - - clean distclean:: - rm -f libdns.@A@ timestamp -diff -up bind-9.7.0rc2/lib/isccc/Makefile.in.nonexec bind-9.7.0rc2/lib/isccc/Makefile.in ---- bind-9.7.0rc2/lib/isccc/Makefile.in.nonexec 2009-12-06 00:31:41.000000000 +0100 -+++ bind-9.7.0rc2/lib/isccc/Makefile.in 2010-01-28 12:13:33.406696161 +0100 -@@ -80,7 +80,7 @@ installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisccc.@A@ ${DESTDIR}${libdir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisccc.@A@ ${DESTDIR}${libdir} - - clean distclean:: - rm -f libisccc.@A@ timestamp -diff -up bind-9.7.0rc2/lib/isccfg/Makefile.in.nonexec bind-9.7.0rc2/lib/isccfg/Makefile.in ---- bind-9.7.0rc2/lib/isccfg/Makefile.in.nonexec 2009-12-06 00:31:41.000000000 +0100 -+++ bind-9.7.0rc2/lib/isccfg/Makefile.in 2010-01-28 12:13:33.406696161 +0100 -@@ -77,7 +77,7 @@ installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisccfg.@A@ ${DESTDIR}${libdir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisccfg.@A@ ${DESTDIR}${libdir} - - clean distclean:: - rm -f libisccfg.@A@ timestamp -diff -up bind-9.7.0rc2/lib/isc/Makefile.in.nonexec bind-9.7.0rc2/lib/isc/Makefile.in ---- bind-9.7.0rc2/lib/isc/Makefile.in.nonexec 2009-12-18 05:09:55.000000000 +0100 -+++ bind-9.7.0rc2/lib/isc/Makefile.in 2010-01-28 12:13:53.566696766 +0100 -@@ -121,7 +121,7 @@ installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ ${DESTDIR}${libdir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisc.@A@ ${DESTDIR}${libdir} - - clean distclean:: - rm -f libisc.@A@ libisc-nosymtbl.@A@ libisc.la \ -diff -up bind-9.7.0rc2/lib/lwres/Makefile.in.nonexec bind-9.7.0rc2/lib/lwres/Makefile.in ---- bind-9.7.0rc2/lib/lwres/Makefile.in.nonexec 2007-06-20 01:47:22.000000000 +0200 -+++ bind-9.7.0rc2/lib/lwres/Makefile.in 2010-01-28 12:13:33.406696161 +0100 -@@ -78,7 +78,7 @@ installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} liblwres.@A@ ${DESTDIR}${libdir} -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} liblwres.@A@ ${DESTDIR}${libdir} - - clean distclean:: - rm -f liblwres.@A@ liblwres.la timestamp diff --git a/SOURCES/bind93-rh726120.patch b/SOURCES/bind93-rh726120.patch index 5eb11ee..5b6cc05 100644 --- a/SOURCES/bind93-rh726120.patch +++ b/SOURCES/bind93-rh726120.patch @@ -1,4 +1,4 @@ -From 23c33ea76e916cc16e354faa218b6a0ca6385d00 Mon Sep 17 00:00:00 2001 +From 976b84dced599a74348834e11bcc3fec67a99387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= Date: Tue, 5 Dec 2017 16:33:08 +0100 Subject: [PATCH] Fix bug #726120 @@ -8,11 +8,11 @@ Subject: [PATCH] Fix bug #726120 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c -index 42a2fe2..3a066c6 100644 +index 97ca54e71..eb66793a4 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c -@@ -3416,7 +3416,8 @@ recv_done(isc_task_t *task, isc_event_t *event) { - return; +@@ -4107,7 +4107,8 @@ recv_done(isc_task_t *task, isc_event_t *event) { + } } if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) || - (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse)) @@ -22,5 +22,5 @@ index 42a2fe2..3a066c6 100644 dig_query_t *next = ISC_LIST_NEXT(query, link); if (l->current_query == query) -- -2.9.5 +2.20.1 diff --git a/SOURCES/bind95-rh461409.patch b/SOURCES/bind95-rh461409.patch deleted file mode 100644 index 8c0c772..0000000 --- a/SOURCES/bind95-rh461409.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff -up bind-9.5.1b1/bin/dig/dighost.c.rh461409 bind-9.5.1b1/bin/dig/dighost.c ---- bind-9.5.1b1/bin/dig/dighost.c.rh461409 2008-09-16 14:04:03.000000000 +0200 -+++ bind-9.5.1b1/bin/dig/dighost.c 2008-09-16 14:06:06.000000000 +0200 -@@ -3665,6 +3665,15 @@ output_filter (isc_buffer_t *buffer, uns - (void) strcpy (tmp1, tmp2); - free (tmp2); - -+ tmp2 = stringprep_utf8_to_locale (tmp1); -+ if (tmp2 == NULL) { -+ debug ("output_filter: stringprep_utf8_to_locale failed"); -+ return ISC_R_SUCCESS; -+ } -+ -+ (void) strcpy (tmp1, tmp2); -+ free (tmp2); -+ - tolen = strlen (tmp1); - if (absolute && !end_with_dot && tmp1[tolen - 1] == '.') - tolen--; diff --git a/SOURCES/bind97-exportlib.patch b/SOURCES/bind97-exportlib.patch deleted file mode 100644 index 4468ef5..0000000 --- a/SOURCES/bind97-exportlib.patch +++ /dev/null @@ -1,226 +0,0 @@ -diff -up bind-9.9.3rc2/isc-config.sh.in.exportlib bind-9.9.3rc2/isc-config.sh.in -diff -up bind-9.9.3rc2/lib/export/dns/Makefile.in.exportlib bind-9.9.3rc2/lib/export/dns/Makefile.in ---- bind-9.9.3rc2/lib/export/dns/Makefile.in.exportlib 2013-04-30 08:38:46.000000000 +0200 -+++ bind-9.9.3rc2/lib/export/dns/Makefile.in 2013-05-13 10:45:22.574089729 +0200 -@@ -35,9 +35,9 @@ CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_ - - CWARNINGS = - --ISCLIBS = ../isc/libisc.@A@ -+ISCLIBS = ../isc/libisc-export.@A@ - --ISCDEPLIBS = ../isc/libisc.@A@ -+ISCDEPLIBS = ../isc/libisc-export.@A@ - - LIBS = @LIBS@ - -@@ -116,29 +116,29 @@ version.@O@: ${srcdir}/version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - --libdns.@SA@: ${OBJS} -+libdns-export.@SA@: ${OBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} - ${RANLIB} $@ - --libdns.la: ${OBJS} -+libdns-export.la: ${OBJS} - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns.la \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-export.la \ - -rpath ${export_libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} - --timestamp: libdns.@A@ -+timestamp: libdns-export.@A@ - touch timestamp - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libdns.@A@ \ -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns-export.@A@ \ - ${DESTDIR}${export_libdir}/ - - clean distclean:: -- rm -f libdns.@A@ timestamp -+ rm -f libdns-export.@A@ timestamp - rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h - rm -f include/dns/rdatastruct.h - -diff -up bind-9.9.3rc2/lib/export/irs/Makefile.in.exportlib bind-9.9.3rc2/lib/export/irs/Makefile.in ---- bind-9.9.3rc2/lib/export/irs/Makefile.in.exportlib 2013-04-30 08:38:46.000000000 +0200 -+++ bind-9.9.3rc2/lib/export/irs/Makefile.in 2013-05-13 10:45:22.575089729 +0200 -@@ -43,9 +43,9 @@ SRCS = context.c \ - gai_sterror.c getaddrinfo.c getnameinfo.c \ - resconf.c - --ISCLIBS = ../isc/libisc.@A@ --DNSLIBS = ../dns/libdns.@A@ --ISCCFGLIBS = ../isccfg/libisccfg.@A@ -+ISCLIBS = ../isc/libisc-export.@A@ -+DNSLIBS = ../dns/libdns-export.@A@ -+ISCCFGLIBS = ../isccfg/libisccfg-export.@A@ - - LIBS = @LIBS@ - -@@ -62,26 +62,26 @@ version.@O@: ${srcdir}/version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - --libirs.@SA@: ${OBJS} version.@O@ -+libirs-export.@SA@: ${OBJS} version.@O@ - ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@ - ${RANLIB} $@ - --libirs.la: ${OBJS} version.@O@ -+libirs-export.la: ${OBJS} version.@O@ - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs.la \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs-export.la \ - -rpath ${export_libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} version.@O@ ${LIBS} ${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS} - --timestamp: libirs.@A@ -+timestamp: libirs-export.@A@ - touch timestamp - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libirs.@A@ \ -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libirs-export.@A@ \ - ${DESTDIR}${export_libdir}/ - - clean distclean:: -- rm -f libirs.@A@ libirs.la timestamp -+ rm -f libirs-export.@A@ libirs-export.la timestamp -diff -up bind-9.9.3rc2/lib/export/isccfg/Makefile.in.exportlib bind-9.9.3rc2/lib/export/isccfg/Makefile.in ---- bind-9.9.3rc2/lib/export/isccfg/Makefile.in.exportlib 2013-04-30 08:38:46.000000000 +0200 -+++ bind-9.9.3rc2/lib/export/isccfg/Makefile.in 2013-05-13 10:45:22.576089729 +0200 -@@ -30,11 +30,11 @@ CINCLUDES = -I. ${DNS_INCLUDES} -I${expo - CDEFINES = - CWARNINGS = - --ISCLIBS = ../isc/libisc.@A@ --DNSLIBS = ../dns/libdns.@A@ @DNS_CRYPTO_LIBS@ -+ISCLIBS = ../isc/libisc-export.@A@ -+DNSLIBS = ../dns/libdns-export.@A@ @DNS_CRYPTO_LIBS@ - - ISCDEPLIBS = ../../lib/isc/libisc.@A@ --ISCCFGDEPLIBS = libisccfg.@A@ -+ISCCFGDEPLIBS = libisccfg-export.@A@ - - LIBS = @LIBS@ - -@@ -58,26 +58,26 @@ version.@O@: ${srcdir}/version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - --libisccfg.@SA@: ${OBJS} -+libisccfg-export.@SA@: ${OBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} - ${RANLIB} $@ - --libisccfg.la: ${OBJS} -+libisccfg-export.la: ${OBJS} - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccfg.la \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccfg-export.la \ - -rpath ${export_libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${LIBS} ${DNSLIBS} ${ISCLIBS} - --timestamp: libisccfg.@A@ -+timestamp: libisccfg-export.@A@ - touch timestamp - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisccfg.@A@ \ -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisccfg-export.@A@ \ - ${DESTDIR}${export_libdir}/ - - clean distclean:: -- rm -f libisccfg.@A@ timestamp -+ rm -f libisccfg-export.@A@ timestamp -diff -up bind-9.9.3rc2/lib/export/isc/Makefile.in.exportlib bind-9.9.3rc2/lib/export/isc/Makefile.in ---- bind-9.9.3rc2/lib/export/isc/Makefile.in.exportlib 2013-04-30 08:38:46.000000000 +0200 -+++ bind-9.9.3rc2/lib/export/isc/Makefile.in 2013-05-13 10:45:22.576089729 +0200 -@@ -100,6 +100,10 @@ SRCS = @ISC_EXTRA_SRCS@ \ - - LIBS = @LIBS@ - -+# Note: the order of SUBDIRS is important. -+# Attempt to disable parallel processing. -+.NOTPARALLEL: -+.NO_PARALLEL: - SUBDIRS = include unix nls @ISC_THREAD_DIR@ - TARGETS = timestamp - -@@ -113,26 +117,26 @@ version.@O@: ${srcdir}/version.c - -DLIBAGE=${LIBAGE} \ - -c ${srcdir}/version.c - --libisc.@SA@: ${OBJS} -+libisc-export.@SA@: ${OBJS} - ${AR} ${ARFLAGS} $@ ${OBJS} - ${RANLIB} $@ - --libisc.la: ${OBJS} -+libisc-export.la: ${OBJS} - ${LIBTOOL_MODE_LINK} \ -- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la \ -+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-export.la \ - -rpath ${export_libdir} \ - -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ - ${OBJS} ${LIBS} - --timestamp: libisc.@A@ -+timestamp: libisc-export.@A@ - touch timestamp - - installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir} - - install:: timestamp installdirs -- ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ \ -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisc-export.@A@ \ - ${DESTDIR}${export_libdir} - - clean distclean:: -- rm -f libisc.@A@ libisc.la timestamp -+ rm -f libisc-export.@A@ libisc-export.la timestamp -diff -up bind-9.9.3rc2/lib/export/samples/Makefile.in.exportlib bind-9.9.3rc2/lib/export/samples/Makefile.in ---- bind-9.9.3rc2/lib/export/samples/Makefile.in.exportlib 2013-04-30 08:38:46.000000000 +0200 -+++ bind-9.9.3rc2/lib/export/samples/Makefile.in 2013-05-13 10:45:22.577089729 +0200 -@@ -31,15 +31,15 @@ CINCLUDES = -I${srcdir}/include -I../dns - CDEFINES = - CWARNINGS = - --DNSLIBS = ../dns/libdns.@A@ @DNS_CRYPTO_LIBS@ --ISCLIBS = ../isc/libisc.@A@ --ISCCFGLIBS = ../isccfg/libisccfg.@A@ --IRSLIBS = ../irs/libirs.@A@ -+DNSLIBS = ../dns/libdns-export.@A@ @DNS_CRYPTO_LIBS@ -+ISCLIBS = ../isc/libisc-export.@A@ -+ISCCFGLIBS = ../isccfg/libisccfg-export.@A@ -+IRSLIBS = ../irs/libirs-export.@A@ - --DNSDEPLIBS = ../dns/libdns.@A@ --ISCDEPLIBS = ../isc/libisc.@A@ --ISCCFGDEPLIBS = ../isccfg/libisccfg.@A@ --IRSDEPLIBS = ../irs/libirs.@A@ -+DNSDEPLIBS = ../dns/libdns-export.@A@ -+ISCDEPLIBS = ../isc/libisc-export.@A@ -+ISCCFGDEPLIBS = ../isccfg/libisccfg-export.@A@ -+IRSDEPLIBS = ../irs/libirs-export.@A@ - - DEPLIBS = ${DNSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} - diff --git a/SOURCES/bind97-rh478718.patch b/SOURCES/bind97-rh478718.patch index c6ea596..ef44490 100644 --- a/SOURCES/bind97-rh478718.patch +++ b/SOURCES/bind97-rh478718.patch @@ -1,7 +1,8 @@ -diff -up bind-9.7.0/configure.in.rh478718 bind-9.7.0/configure.in ---- bind-9.7.0/configure.in.rh478718 2010-03-01 14:50:02.331207076 +0100 -+++ bind-9.7.0/configure.in 2010-03-01 14:50:21.501207488 +0100 -@@ -2540,6 +2540,10 @@ main() { +diff --git a/configure.in b/configure.in +index 896e81c1ce..73b1c8ccbb 100644 +--- a/configure.in ++++ b/configure.in +@@ -4275,6 +4275,10 @@ if test "yes" = "$use_atomic"; then AC_MSG_RESULT($arch) fi @@ -9,22 +10,42 @@ diff -up bind-9.7.0/configure.in.rh478718 bind-9.7.0/configure.in + AC_MSG_ERROR([XADDQ present but disabled by Fedora patch!]) +fi + - if test "$have_atomic" = "yes"; then + if test "yes" = "$have_atomic"; then AC_MSG_CHECKING([compiler support for inline assembly code]) -diff -up bind-9.7.0/lib/isc/include/isc/platform.h.in.rh478718 bind-9.7.0/lib/isc/include/isc/platform.h.in ---- bind-9.7.0/lib/isc/include/isc/platform.h.in.rh478718 2010-03-01 14:50:31.421207522 +0100 -+++ bind-9.7.0/lib/isc/include/isc/platform.h.in 2010-03-01 14:50:40.313707286 +0100 -@@ -255,7 +255,11 @@ +diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in +index 2ff522342f..58df86adb3 100644 +--- a/lib/isc/include/isc/platform.h.in ++++ b/lib/isc/include/isc/platform.h.in +@@ -289,19 +289,25 @@ * If the "xaddq" operation (64bit xadd) is available on this architecture, * ISC_PLATFORM_HAVEXADDQ will be defined. */ -@ISC_PLATFORM_HAVEXADDQ@ + + /* +- * If the 32-bit "atomic swap" operation is available on this +- * architecture, ISC_PLATFORM_HAVEATOMICSTORE" will be defined. ++ * If the 64-bit "atomic swap" operation is available on this ++ * architecture, ISC_PLATFORM_HAVEATOMICSTOREQ" will be defined. + */ +-@ISC_PLATFORM_HAVEATOMICSTORE@ ++ +#ifdef __x86_64__ +#define ISC_PLATFORM_HAVEXADDQ 1 ++#define ISC_PLATFORM_HAVEATOMICSTOREQ 1 +#else +#undef ISC_PLATFORM_HAVEXADDQ ++#undef ISC_PLATFORM_HAVEATOMICSTOREQ +#endif /* - * If the "atomic swap" operation is available on this architecture, +- * If the 64-bit "atomic swap" operation is available on this ++ * If the 32-bit "atomic swap" operation is available on this + * architecture, ISC_PLATFORM_HAVEATOMICSTORE" will be defined. + */ +-@ISC_PLATFORM_HAVEATOMICSTOREQ@ ++@ISC_PLATFORM_HAVEATOMICSTORE@ + + /* + * If the "compare-and-exchange" operation is available on this architecture, diff --git a/SOURCES/bind97-rh570851.patch b/SOURCES/bind97-rh570851.patch deleted file mode 100644 index e24b94c..0000000 --- a/SOURCES/bind97-rh570851.patch +++ /dev/null @@ -1,153 +0,0 @@ -diff -up bind-9.7.2b1/bin/dig/dighost.c.rh570851 bind-9.7.2b1/bin/dig/dighost.c ---- bind-9.7.2b1/bin/dig/dighost.c.rh570851 2010-08-10 12:55:14.219403986 +0200 -+++ bind-9.7.2b1/bin/dig/dighost.c 2010-08-10 12:56:40.716015777 +0200 -@@ -126,7 +126,8 @@ isc_boolean_t - usesearch = ISC_FALSE, - showsearch = ISC_FALSE, - qr = ISC_FALSE, -- is_dst_up = ISC_FALSE; -+ is_dst_up = ISC_FALSE, -+ verbose = ISC_FALSE; - in_port_t port = 53; - unsigned int timeout = 0; - unsigned int extrabytes; -@@ -1240,10 +1241,24 @@ setup_system(void) { - } - } - -+ if (lwconf->resdebug) { -+ verbose = ISC_TRUE; -+ debug("verbose is on"); -+ } - if (ndots == -1) { - ndots = lwconf->ndots; - debug("ndots is %d.", ndots); - } -+ if (lwconf->attempts) { -+ tries = lwconf->attempts + 1; -+ if (tries < 2) -+ tries = 2; -+ debug("tries is %d.", tries); -+ } -+ if (lwconf->timeout) { -+ timeout = lwconf->timeout; -+ debug("timeout is %d.", timeout); -+ } - - /* If user doesn't specify server use nameservers from resolv.conf. */ - if (ISC_LIST_EMPTY(server_list)) -diff -up bind-9.7.2b1/bin/dig/host.c.rh570851 bind-9.7.2b1/bin/dig/host.c ---- bind-9.7.2b1/bin/dig/host.c.rh570851 2010-08-10 12:57:16.032758098 +0200 -+++ bind-9.7.2b1/bin/dig/host.c 2010-08-10 13:02:12.848559845 +0200 -@@ -659,6 +659,7 @@ parse_args(isc_boolean_t is_batchfile, i - - lookup->servfail_stops = ISC_FALSE; - lookup->comments = ISC_FALSE; -+ short_form = !verbose; - - while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) { - switch (c) { -@@ -869,8 +870,8 @@ main(int argc, char **argv) { - result = isc_app_start(); - check_result(result, "isc_app_start"); - setup_libs(); -- parse_args(ISC_FALSE, argc, argv); - setup_system(); -+ parse_args(ISC_FALSE, argc, argv); - result = isc_app_onrun(mctx, global_task, onrun_callback, NULL); - check_result(result, "isc_app_onrun"); - isc_app_run(); -diff -up bind-9.7.2b1/bin/dig/include/dig/dig.h.rh570851 bind-9.7.2b1/bin/dig/include/dig/dig.h ---- bind-9.7.2b1/bin/dig/include/dig/dig.h.rh570851 2010-08-10 13:02:32.722244088 +0200 -+++ bind-9.7.2b1/bin/dig/include/dig/dig.h 2010-08-10 13:02:48.465158159 +0200 -@@ -278,6 +278,7 @@ extern isc_boolean_t debugging, memdebug - extern char *progname; - extern int tries; - extern int fatalexit; -+extern isc_boolean_t verbose; - #ifdef WITH_IDN - extern int idnoptions; - #endif -diff -up bind-9.7.2b1/lib/lwres/include/lwres/lwres.h.rh570851 bind-9.7.2b1/lib/lwres/include/lwres/lwres.h ---- bind-9.7.2b1/lib/lwres/include/lwres/lwres.h.rh570851 2010-08-10 13:04:40.465780506 +0200 -+++ bind-9.7.2b1/lib/lwres/include/lwres/lwres.h 2010-08-10 13:05:57.559867830 +0200 -@@ -243,6 +243,8 @@ typedef struct { - lwres_uint8_t resdebug; /*%< non-zero if 'options debug' set */ - lwres_uint8_t ndots; /*%< set to n in 'options ndots:n' */ - lwres_uint8_t no_tld_query; /*%< non-zero if 'options no_tld_query' */ -+ lwres_int32_t attempts; /*%< set to n in 'options attempts:n' */ -+ lwres_int32_t timeout; /*%< set to n in 'options timeout:n' */ - } lwres_conf_t; - - #define LWRES_ADDRTYPE_V4 0x00000001U /*%< ipv4 */ -diff -up bind-9.7.2b1/lib/lwres/lwconfig.c.rh570851 bind-9.7.2b1/lib/lwres/lwconfig.c ---- bind-9.7.2b1/lib/lwres/lwconfig.c.rh570851 2010-08-10 13:06:08.051778429 +0200 -+++ bind-9.7.2b1/lib/lwres/lwconfig.c 2010-08-10 13:09:53.972555776 +0200 -@@ -237,6 +237,8 @@ lwres_conf_init(lwres_context_t *ctx) { - confdata->resdebug = 0; - confdata->ndots = 1; - confdata->no_tld_query = 0; -+ confdata->attempts = 0; -+ confdata->timeout = 0; - - for (i = 0; i < LWRES_CONFMAXNAMESERVERS; i++) - lwres_resetaddr(&confdata->nameservers[i]); -@@ -289,6 +291,8 @@ lwres_conf_clear(lwres_context_t *ctx) { - confdata->resdebug = 0; - confdata->ndots = 1; - confdata->no_tld_query = 0; -+ confdata->attempts = 0; -+ confdata->timeout = 0; - } - - static lwres_result_t -@@ -530,6 +534,8 @@ static lwres_result_t - lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp) { - int delim; - long ndots; -+ long attempts; -+ long timeout; - char *p; - char word[LWRES_CONFMAXLINELEN]; - lwres_conf_t *confdata; -@@ -546,6 +552,8 @@ lwres_conf_parseoption(lwres_context_t * - confdata->resdebug = 1; - } else if (strcmp("no_tld_query", word) == 0) { - confdata->no_tld_query = 1; -+ } else if (strcmp("debug", word) == 0) { -+ confdata->resdebug = 1; - } else if (strncmp("ndots:", word, 6) == 0) { - ndots = strtol(word + 6, &p, 10); - if (*p != '\0') /* Bad string. */ -@@ -553,6 +561,18 @@ lwres_conf_parseoption(lwres_context_t * - if (ndots < 0 || ndots > 0xff) /* Out of range. */ - return (LWRES_R_FAILURE); - confdata->ndots = (lwres_uint8_t)ndots; -+ } else if (strncmp("timeout:", word, 8) == 0) { -+ timeout = strtol(word + 8, &p, 10); -+ if (*p != '\0') /* Bad string. */ -+ return (LWRES_R_FAILURE); -+ confdata->timeout = (lwres_int32_t)timeout; -+ } else if (strncmp("attempts:", word, 9) == 0) { -+ attempts = strtol(word + 9, &p, 10); -+ if (*p != '\0') /* Bad string. */ -+ return (LWRES_R_FAILURE); -+ if (attempts < 0) /* Out of range. */ -+ return (LWRES_R_FAILURE); -+ confdata->attempts = (lwres_int32_t)attempts; - } - - if (delim == EOF || delim == '\n') -@@ -716,6 +736,12 @@ lwres_conf_print(lwres_context_t *ctx, F - if (confdata->no_tld_query) - fprintf(fp, "options no_tld_query\n"); - -+ if (confdata->attempts) -+ fprintf(fp, "options attempts:%d\n", confdata->attempts); -+ -+ if (confdata->timeout) -+ fprintf(fp, "options timeout:%d\n", confdata->timeout); -+ - return (LWRES_R_SUCCESS); - } - diff --git a/SOURCES/bind97-rh693982.patch b/SOURCES/bind97-rh693982.patch deleted file mode 100644 index 57bf812..0000000 --- a/SOURCES/bind97-rh693982.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff -up bind-9.7.3-P3/bin/named/server.c.rh693982 bind-9.7.3-P3/bin/named/server.c ---- bind-9.7.3-P3/bin/named/server.c.rh693982 2011-08-12 17:18:55.611978110 +0200 -+++ bind-9.7.3-P3/bin/named/server.c 2011-08-12 17:19:36.009975303 +0200 -@@ -4444,15 +4444,6 @@ load_configuration(const char *filename, - ns_os_changeuser(); - - /* -- * Check that the working directory is writable. -- */ -- if (access(".", W_OK) != 0) { -- isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -- NS_LOGMODULE_SERVER, ISC_LOG_ERROR, -- "the working directory is not writable"); -- } -- -- /* - * Configure the logging system. - * - * Do this after changing UID to make sure that any log -@@ -4498,6 +4489,15 @@ load_configuration(const char *filename, - } - - /* -+ * Check that the working directory is writable. -+ */ -+ if (access(".", W_OK) != 0) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), -+ "the working directory is not writable"); -+ } -+ -+ /* - * Set the default value of the query logging flag depending - * whether a "queries" category has been defined. This is - * a disgusting hack, but we need to do this for BIND 8 diff --git a/SOURCES/bind98-rh735103.patch b/SOURCES/bind98-rh735103.patch deleted file mode 100644 index 77acfa8..0000000 --- a/SOURCES/bind98-rh735103.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff -up bind-9.8.1rc1/lib/isc/unix/socket.c.rh735103 bind-9.8.1rc1/lib/isc/unix/socket.c ---- bind-9.8.1rc1/lib/isc/unix/socket.c.rh735103 2011-07-29 04:19:20.000000000 +0200 -+++ bind-9.8.1rc1/lib/isc/unix/socket.c 2011-09-07 18:49:54.100215897 +0200 -@@ -57,6 +57,20 @@ - #include - #include - -+/* See task.c about the following definition: */ -+#ifdef BIND9 -+#ifdef ISC_PLATFORM_USETHREADS -+#define USE_WATCHER_THREAD -+#else -+#define USE_SHARED_MANAGER -+#endif /* ISC_PLATFORM_USETHREADS */ -+#else /* BIND9 */ -+#undef ISC_PLATFORM_HAVESYSUNH -+#undef ISC_PLATFORM_HAVEKQUEUE -+#undef ISC_PLATFORM_HAVEEPOLL -+#undef ISC_PLATFORM_HAVEDEVPOLL -+#endif /* BIND9 */ -+ - #ifdef ISC_PLATFORM_HAVESYSUNH - #include - #endif -@@ -76,15 +90,6 @@ - - #include "errno2result.h" - --/* See task.c about the following definition: */ --#ifdef BIND9 --#ifdef ISC_PLATFORM_USETHREADS --#define USE_WATCHER_THREAD --#else --#define USE_SHARED_MANAGER --#endif /* ISC_PLATFORM_USETHREADS */ --#endif /* BIND9 */ -- - #ifndef USE_WATCHER_THREAD - #include "socket_p.h" - #include "../task_p.h" diff --git a/SOURCES/bind99-CVE-2014-0591.patch b/SOURCES/bind99-CVE-2014-0591.patch deleted file mode 100644 index ba225b1..0000000 --- a/SOURCES/bind99-CVE-2014-0591.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff -pruN bind-9.9.4-P1/bin/named/query.c bind-9.9.4-P2/bin/named/query.c ---- bind-9.9.4-P1/bin/named/query.c 2013-10-16 01:04:32.000000000 +0200 -+++ bind-9.9.4-P2/bin/named/query.c 2013-12-20 01:28:28.000000000 +0100 -@@ -5260,8 +5260,7 @@ query_findclosestnsec3(dns_name_t *qname - dns_fixedname_t fixed; - dns_hash_t hash; - dns_name_t name; -- int order; -- unsigned int count; -+ unsigned int skip = 0, labels; - dns_rdata_nsec3_t nsec3; - dns_rdata_t rdata = DNS_RDATA_INIT; - isc_boolean_t optout; -@@ -5276,6 +5275,7 @@ query_findclosestnsec3(dns_name_t *qname - - dns_name_init(&name, NULL); - dns_name_clone(qname, &name); -+ labels = dns_name_countlabels(&name); - dns_clientinfomethods_init(&cm, ns_client_sourceip); - dns_clientinfo_init(&ci, client); - -@@ -5309,13 +5309,14 @@ query_findclosestnsec3(dns_name_t *qname - dns_rdata_reset(&rdata); - optout = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); - if (found != NULL && optout && -- dns_name_fullcompare(&name, dns_db_origin(db), &order, -- &count) == dns_namereln_subdomain) { -+ dns_name_issubdomain(&name, dns_db_origin(db))) -+ { - dns_rdataset_disassociate(rdataset); - if (dns_rdataset_isassociated(sigrdataset)) - dns_rdataset_disassociate(sigrdataset); -- count = dns_name_countlabels(&name) - 1; -- dns_name_getlabelsequence(&name, 1, count, &name); -+ skip++; -+ dns_name_getlabelsequence(qname, skip, labels - skip, -+ &name); - ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, - NS_LOGMODULE_QUERY, ISC_LOG_DEBUG(3), - "looking for closest provable encloser"); -@@ -5333,7 +5334,11 @@ query_findclosestnsec3(dns_name_t *qname - ns_client_log(client, DNS_LOGCATEGORY_DNSSEC, - NS_LOGMODULE_QUERY, ISC_LOG_WARNING, - "expected covering NSEC3, got an exact match"); -- if (found != NULL) -+ if (found == qname) { -+ if (skip != 0U) -+ dns_name_getlabelsequence(qname, skip, labels - skip, -+ found); -+ } else if (found != NULL) - dns_name_copy(&name, found, NULL); - return; - } diff --git a/SOURCES/bind99-CVE-2014-8500.patch b/SOURCES/bind99-CVE-2014-8500.patch deleted file mode 100644 index 1369769..0000000 --- a/SOURCES/bind99-CVE-2014-8500.patch +++ /dev/null @@ -1,924 +0,0 @@ -diff -up bind-9.9.4/bin/named/config.c.CVE-2014-8500 bind-9.9.4/bin/named/config.c ---- bind-9.9.4/bin/named/config.c.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/bin/named/config.c 2014-12-10 14:56:24.959552559 +0100 -@@ -160,6 +160,8 @@ options {\n\ - dnssec-accept-expired no;\n\ - clients-per-query 10;\n\ - max-clients-per-query 100;\n\ -+ max-recursion-depth 7;\n\ -+ max-recursion-queries 50;\n\ - zero-no-soa-ttl-cache no;\n\ - nsec3-test-zone no;\n\ - allow-new-zones no;\n\ -diff -up bind-9.9.4/bin/named/query.c.CVE-2014-8500 bind-9.9.4/bin/named/query.c ---- bind-9.9.4/bin/named/query.c.CVE-2014-8500 2014-12-10 14:56:24.945552543 +0100 -+++ bind-9.9.4/bin/named/query.c 2014-12-10 14:56:24.960552560 +0100 -@@ -3872,12 +3872,11 @@ query_recurse(ns_client_t *client, dns_r - peeraddr = &client->peeraddr; - else - peeraddr = NULL; -- result = dns_resolver_createfetch2(client->view->resolver, -+ result = dns_resolver_createfetch3(client->view->resolver, - qname, qtype, qdomain, nameservers, - NULL, peeraddr, client->message->id, -- client->query.fetchoptions, -- client->task, -- query_resume, client, -+ client->query.fetchoptions, 0, NULL, -+ client->task, query_resume, client, - rdataset, sigrdataset, - &client->query.fetch); - -diff -up bind-9.9.4/bin/named/server.c.CVE-2014-8500 bind-9.9.4/bin/named/server.c ---- bind-9.9.4/bin/named/server.c.CVE-2014-8500 2014-12-10 14:56:24.913552507 +0100 -+++ bind-9.9.4/bin/named/server.c 2014-12-10 14:56:24.961552561 +0100 -@@ -3205,6 +3205,16 @@ configure_view(dns_view_t *view, cfg_obj - cfg_obj_asuint32(obj), - max_clients_per_query); - -+ obj = NULL; -+ result = ns_config_get(maps, "max-recursion-depth", &obj); -+ INSIST(result == ISC_R_SUCCESS); -+ dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); -+ -+ obj = NULL; -+ result = ns_config_get(maps, "max-recursion-queries", &obj); -+ INSIST(result == ISC_R_SUCCESS); -+ dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); -+ - #ifdef ALLOW_FILTER_AAAA_ON_V4 - obj = NULL; - result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); -diff -up bind-9.9.4/doc/arm/Bv9ARM-book.xml.CVE-2014-8500 bind-9.9.4/doc/arm/Bv9ARM-book.xml ---- bind-9.9.4/doc/arm/Bv9ARM-book.xml.CVE-2014-8500 2014-12-10 14:56:24.957552556 +0100 -+++ bind-9.9.4/doc/arm/Bv9ARM-book.xml 2014-12-10 15:00:53.108931629 +0100 -@@ -4874,6 +4874,8 @@ badresp:1,adberr:0,findfail:0,valfail:0] - max-acache-size size_spec ; - clients-per-query number ; - max-clients-per-query number ; -+ max-recursion-depth number ; -+ max-recursion-queries number ; - masterfile-format (text|raw) ; - empty-server name ; - empty-contact name ; -@@ -8623,6 +8625,35 @@ avoid-v6-udp-ports { 40000; range 50000 - - - -+ -+ -+ max-recursion-depth -+ -+ -+ Sets the maximum number of levels of recursion -+ that are permitted at any one time while servicing -+ a recursive query. Resolving a name may require -+ looking up a name server address, which in turn -+ requires resolving another name, etc; if the number -+ of indirections exceeds this value, the recursive -+ query is terminated and returns SERVFAIL. The -+ default is 7. -+ -+ -+ -+ -+ -+ max-recursion-queries -+ -+ -+ Sets the maximum number of iterative queries that -+ may be sent while servicing a recursive query. -+ If more queries are sent, the recursive query -+ is terminated and returns SERVFAIL. The default -+ is 50. -+ -+ -+ - - - notify-delay -diff -up bind-9.9.4/doc/misc/options.CVE-2014-8500 bind-9.9.4/doc/misc/options ---- bind-9.9.4/doc/misc/options.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/doc/misc/options 2014-12-10 14:56:24.964552564 +0100 -@@ -162,6 +162,8 @@ options { - max-ixfr-log-size ; // obsolete - max-journal-size ; - max-ncache-ttl ; -+ max-recursion-depth ; -+ max-recursion-queries ; - max-refresh-time ; - max-retry-time ; - max-rsa-exponent-size ; -@@ -385,6 +387,8 @@ view { - max-ixfr-log-size ; // obsolete - max-journal-size ; - max-ncache-ttl ; -+ max-recursion-depth ; -+ max-recursion-queries ; - max-refresh-time ; - max-retry-time ; - max-transfer-idle-in ; -diff -up bind-9.9.4/lib/dns/adb.c.CVE-2014-8500 bind-9.9.4/lib/dns/adb.c ---- bind-9.9.4/lib/dns/adb.c.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/lib/dns/adb.c 2014-12-10 14:56:24.965552566 +0100 -@@ -201,6 +201,7 @@ struct dns_adbfetch { - unsigned int magic; - dns_fetch_t *fetch; - dns_rdataset_t rdataset; -+ unsigned int depth; - }; - - /*% -@@ -300,8 +301,7 @@ static inline isc_boolean_t dec_entry_re - static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); - static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); - static void clean_target(dns_adb_t *, dns_name_t *); --static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, -- unsigned int); -+static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int); - static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); - static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, - isc_stdtime_t); -@@ -309,6 +309,7 @@ static void cancel_fetches_at_name(dns_a - static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, - dns_rdatatype_t); - static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, -+ unsigned int, isc_counter_t *qc, - dns_rdatatype_t); - static inline void check_exit(dns_adb_t *); - static void destroy(dns_adb_t *); -@@ -2770,6 +2771,19 @@ dns_adb_createfind(dns_adb_t *adb, isc_t - isc_stdtime_t now, dns_name_t *target, - in_port_t port, dns_adbfind_t **findp) - { -+ return (dns_adb_createfind2(adb, task, action, arg, name, -+ qname, qtype, options, now, -+ target, port, 0, NULL, findp)); -+} -+ -+isc_result_t -+dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, -+ void *arg, dns_name_t *name, dns_name_t *qname, -+ dns_rdatatype_t qtype, unsigned int options, -+ isc_stdtime_t now, dns_name_t *target, -+ in_port_t port, unsigned int depth, isc_counter_t *qc, -+ dns_adbfind_t **findp) -+{ - dns_adbfind_t *find; - dns_adbname_t *adbname; - int bucket; -@@ -3000,7 +3014,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_t - * Start V4. - */ - if (WANT_INET(wanted_fetches) && -- fetch_name(adbname, start_at_zone, -+ fetch_name(adbname, start_at_zone, depth, qc, - dns_rdatatype_a) == ISC_R_SUCCESS) { - DP(DEF_LEVEL, - "dns_adb_createfind: started A fetch for name %p", -@@ -3011,7 +3025,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_t - * Start V6. - */ - if (WANT_INET6(wanted_fetches) && -- fetch_name(adbname, start_at_zone, -+ fetch_name(adbname, start_at_zone, depth, qc, - dns_rdatatype_aaaa) == ISC_R_SUCCESS) { - DP(DEF_LEVEL, - "dns_adb_createfind: " -@@ -3754,6 +3768,12 @@ fetch_callback(isc_task_t *task, isc_eve - DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", - buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", - dns_result_totext(dev->result)); -+ /* -+ * Don't record a failure unless this is the initial -+ * fetch of a chain. -+ */ -+ if (fetch->depth > 1) -+ goto out; - /* XXXMLG Don't pound on bad servers. */ - if (address_type == DNS_ADBFIND_INET) { - name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); -@@ -3791,9 +3811,8 @@ fetch_callback(isc_task_t *task, isc_eve - } - - static isc_result_t --fetch_name(dns_adbname_t *adbname, -- isc_boolean_t start_at_zone, -- dns_rdatatype_t type) -+fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, -+ unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type) - { - isc_result_t result; - dns_adbfetch_t *fetch = NULL; -@@ -3838,12 +3857,14 @@ fetch_name(dns_adbname_t *adbname, - result = ISC_R_NOMEMORY; - goto cleanup; - } -+ fetch->depth = depth; - -- result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, -- type, name, nameservers, NULL, -- options, adb->task, fetch_callback, -- adbname, &fetch->rdataset, NULL, -- &fetch->fetch); -+ result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name, -+ type, name, nameservers, NULL, -+ NULL, 0, options, depth, qc, -+ adb->task, fetch_callback, adbname, -+ &fetch->rdataset, NULL, -+ &fetch->fetch); - if (result != ISC_R_SUCCESS) - goto cleanup; - -diff -up bind-9.9.4/lib/dns/include/dns/adb.h.CVE-2014-8500 bind-9.9.4/lib/dns/include/dns/adb.h ---- bind-9.9.4/lib/dns/include/dns/adb.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/lib/dns/include/dns/adb.h 2014-12-10 14:56:24.965552566 +0100 -@@ -334,6 +334,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_t - dns_rdatatype_t qtype, unsigned int options, - isc_stdtime_t now, dns_name_t *target, - in_port_t port, dns_adbfind_t **find); -+isc_result_t -+dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, -+ void *arg, dns_name_t *name, dns_name_t *qname, -+ dns_rdatatype_t qtype, unsigned int options, -+ isc_stdtime_t now, dns_name_t *target, in_port_t port, -+ unsigned int depth, isc_counter_t *qc, -+ dns_adbfind_t **find); - /*%< - * Main interface for clients. The adb will look up the name given in - * "name" and will build up a list of found addresses, and perhaps start -diff -up bind-9.9.4/lib/dns/include/dns/resolver.h.CVE-2014-8500 bind-9.9.4/lib/dns/include/dns/resolver.h ---- bind-9.9.4/lib/dns/include/dns/resolver.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/lib/dns/include/dns/resolver.h 2014-12-10 14:56:24.965552566 +0100 -@@ -274,6 +274,18 @@ dns_resolver_createfetch2(dns_resolver_t - dns_rdataset_t *rdataset, - dns_rdataset_t *sigrdataset, - dns_fetch_t **fetchp); -+isc_result_t -+dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, -+ dns_rdatatype_t type, -+ dns_name_t *domain, dns_rdataset_t *nameservers, -+ dns_forwarders_t *forwarders, -+ isc_sockaddr_t *client, isc_uint16_t id, -+ unsigned int options, unsigned int depth, -+ isc_counter_t *qc, isc_task_t *task, -+ isc_taskaction_t action, void *arg, -+ dns_rdataset_t *rdataset, -+ dns_rdataset_t *sigrdataset, -+ dns_fetch_t **fetchp); - /*%< - * Recurse to answer a question. - * -@@ -573,6 +585,30 @@ dns_resolver_printbadcache(dns_resolver_ - * - * Requires: - * \li resolver to be valid. -+ */ -+ -+void -+dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth); -+unsigned int -+dns_resolver_getmaxdepth(dns_resolver_t *resolver); -+/*% -+ * Get and set how many NS indirections will be followed when looking for -+ * nameserver addresses. -+ * -+ * Requires: -+ * \li resolver to be valid. -+ */ -+ -+void -+dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries); -+unsigned int -+dns_resolver_getmaxqueries(dns_resolver_t *resolver); -+/*% -+ * Get and set how many iterative queries will be allowed before -+ * terminating a recursive query. -+ * -+ * Requires: -+ * \li resolver to be valid. - */ - - ISC_LANG_ENDDECLS -diff -up bind-9.9.4/lib/dns/resolver.c.CVE-2014-8500 bind-9.9.4/lib/dns/resolver.c ---- bind-9.9.4/lib/dns/resolver.c.CVE-2014-8500 2014-12-10 14:56:24.952552551 +0100 -+++ bind-9.9.4/lib/dns/resolver.c 2014-12-10 15:01:56.855970646 +0100 -@@ -21,6 +21,7 @@ - - #include - -+#include - #include - #include - #include -@@ -130,6 +131,16 @@ - #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ - #endif - -+/* The default maximum number of recursions to follow before giving up. */ -+#ifndef DEFAULT_RECURSION_DEPTH -+#define DEFAULT_RECURSION_DEPTH 7 -+#endif -+ -+/* The default maximum number of iterative queries to allow before giving up. */ -+#ifndef DEFAULT_MAX_QUERIES -+#define DEFAULT_MAX_QUERIES 50 -+#endif -+ - /*% - * Maximum EDNS0 input packet size. - */ -@@ -233,12 +244,13 @@ struct fetchctx { - isc_sockaddrlist_t edns; - isc_sockaddrlist_t edns512; - isc_sockaddrlist_t bad_edns; -- dns_validator_t *validator; -+ dns_validator_t * validator; - ISC_LIST(dns_validator_t) validators; - dns_db_t * cache; - dns_adb_t * adb; - isc_boolean_t ns_ttl_ok; - isc_uint32_t ns_ttl; -+ isc_counter_t * qc; - - /*% - * The number of events we're waiting for. -@@ -306,6 +318,7 @@ struct fetchctx { - isc_boolean_t timeout; - dns_adbaddrinfo_t *addrinfo; - isc_sockaddr_t *client; -+ unsigned int depth; - }; - - #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') -@@ -418,6 +431,8 @@ struct dns_resolver { - isc_timer_t * spillattimer; - isc_boolean_t zero_no_soa_ttl; - unsigned int query_timeout; -+ unsigned int maxdepth; -+ unsigned int maxqueries; - - /* Locked by lock. */ - unsigned int references; -@@ -1533,6 +1548,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddr - if (result != ISC_R_SUCCESS) - goto cleanup_dispatch; - } -+ - fctx->querysent++; - - ISC_LIST_APPEND(fctx->queries, query, link); -@@ -2186,9 +2202,9 @@ fctx_finddone(isc_task_t *task, isc_even - */ - INSIST(!SHUTTINGDOWN(fctx)); - fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; -- if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) -+ if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { - want_try = ISC_TRUE; -- else { -+ } else { - fctx->findfail++; - if (fctx->pending == 0) { - /* -@@ -2471,12 +2487,13 @@ findname(fetchctx_t *fctx, dns_name_t *n - * See what we know about this address. - */ - find = NULL; -- result = dns_adb_createfind(fctx->adb, -- res->buckets[fctx->bucketnum].task, -- fctx_finddone, fctx, name, -- &fctx->name, fctx->type, -- options, now, NULL, -- res->view->dstport, &find); -+ result = dns_adb_createfind2(fctx->adb, -+ res->buckets[fctx->bucketnum].task, -+ fctx_finddone, fctx, name, -+ &fctx->name, fctx->type, -+ options, now, NULL, -+ res->view->dstport, -+ fctx->depth + 1, fctx->qc, &find); - if (result != ISC_R_SUCCESS) { - if (result == DNS_R_ALIAS) { - /* -@@ -2584,6 +2601,14 @@ fctx_getaddresses(fetchctx_t *fctx, isc_ - - res = fctx->res; - -+ if (fctx->depth > res->maxdepth) { -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, -+ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), -+ "too much NS indirection resolving '%s'", -+ fctx->info); -+ return (DNS_R_SERVFAIL); -+ } -+ - /* - * Forwarders. - */ -@@ -3059,6 +3084,16 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t - } - } - -+ result = isc_counter_increment(fctx->qc); -+ if (result != ISC_R_SUCCESS) { -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, -+ DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), -+ "exceeded max queries resolving '%s'", -+ fctx->info); -+ fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); -+ return; -+ } -+ - result = fctx_query(fctx, addrinfo, fctx->options); - if (result != ISC_R_SUCCESS) - fctx_done(fctx, result, __LINE__); -@@ -3157,6 +3192,7 @@ fctx_destroy(fetchctx_t *fctx) { - isc_mem_put(fctx->mctx, sa, sizeof(*sa)); - } - -+ isc_counter_detach(&fctx->qc); - isc_timer_detach(&fctx->timer); - dns_message_destroy(&fctx->rmessage); - dns_message_destroy(&fctx->qmessage); -@@ -3485,7 +3521,8 @@ log_ns_ttl(fetchctx_t *fctx, const char - static isc_result_t - fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, - dns_name_t *domain, dns_rdataset_t *nameservers, -- unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp) -+ unsigned int options, unsigned int bucketnum, unsigned int depth, -+ isc_counter_t *qc, fetchctx_t **fctxp) - { - fetchctx_t *fctx; - isc_result_t result; -@@ -3507,6 +3544,21 @@ fctx_create(dns_resolver_t *res, dns_nam - fctx = isc_mem_get(mctx, sizeof(*fctx)); - if (fctx == NULL) - return (ISC_R_NOMEMORY); -+ -+ fctx->qc = NULL; -+ if (qc != NULL) { -+ isc_counter_attach(qc, &fctx->qc); -+ } else { -+ result = isc_counter_create(res->mctx, -+ res->maxqueries, &fctx->qc); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup_fetch; -+ } -+ -+ /* -+ * Make fctx->info point to a copy of a formatted string -+ * "name/type". -+ */ - dns_name_format(name, buf, sizeof(buf)); - dns_rdatatype_format(type, typebuf, sizeof(typebuf)); - strcat(buf, "/"); /* checked */ -@@ -3514,7 +3566,7 @@ fctx_create(dns_resolver_t *res, dns_nam - fctx->info = isc_mem_strdup(mctx, buf); - if (fctx->info == NULL) { - result = ISC_R_NOMEMORY; -- goto cleanup_fetch; -+ goto cleanup_counter; - } - FCTXTRACE("create"); - dns_name_init(&fctx->name, NULL); -@@ -3537,6 +3589,7 @@ fctx_create(dns_resolver_t *res, dns_nam - fctx->state = fetchstate_init; - fctx->want_shutdown = ISC_FALSE; - fctx->cloned = ISC_FALSE; -+ fctx->depth = depth; - ISC_LIST_INIT(fctx->queries); - ISC_LIST_INIT(fctx->finds); - ISC_LIST_INIT(fctx->altfinds); -@@ -3742,6 +3795,9 @@ fctx_create(dns_resolver_t *res, dns_nam - cleanup_info: - isc_mem_free(mctx, fctx->info); - -+ cleanup_counter: -+ isc_counter_detach(&fctx->qc); -+ - cleanup_fetch: - isc_mem_put(mctx, fctx, sizeof(*fctx)); - -@@ -5655,7 +5711,7 @@ noanswer_response(fetchctx_t *fctx, dns_ - char qbuf[DNS_NAME_FORMATSIZE]; - char nbuf[DNS_NAME_FORMATSIZE]; - char tbuf[DNS_RDATATYPE_FORMATSIZE]; -- dns_rdatatype_format(fctx->type, tbuf, -+ dns_rdatatype_format(type, tbuf, - sizeof(tbuf)); - dns_name_format(name, nbuf, - sizeof(nbuf)); -@@ -5664,7 +5720,7 @@ noanswer_response(fetchctx_t *fctx, dns_ - log_formerr(fctx, - "unrelated %s %s in " - "%s authority section", -- tbuf, qbuf, nbuf); -+ tbuf, nbuf, qbuf); - return (DNS_R_FORMERR); - } - if (type == dns_rdatatype_ns) { -@@ -7725,6 +7781,8 @@ dns_resolver_create(dns_view_t *view, - res->spillattimer = NULL; - res->zero_no_soa_ttl = ISC_FALSE; - res->query_timeout = DEFAULT_QUERY_TIMEOUT; -+ res->maxdepth = DEFAULT_RECURSION_DEPTH; -+ res->maxqueries = DEFAULT_MAX_QUERIES; - res->nbuckets = ntasks; - res->activebuckets = ntasks; - res->buckets = isc_mem_get(view->mctx, -@@ -8163,9 +8221,9 @@ dns_resolver_createfetch(dns_resolver_t - dns_rdataset_t *sigrdataset, - dns_fetch_t **fetchp) - { -- return (dns_resolver_createfetch2(res, name, type, domain, -+ return (dns_resolver_createfetch3(res, name, type, domain, - nameservers, forwarders, NULL, 0, -- options, task, action, arg, -+ options, 0, NULL, task, action, arg, - rdataset, sigrdataset, fetchp)); - } - -@@ -8181,6 +8239,25 @@ dns_resolver_createfetch2(dns_resolver_t - dns_rdataset_t *sigrdataset, - dns_fetch_t **fetchp) - { -+ return (dns_resolver_createfetch3(res, name, type, domain, -+ nameservers, forwarders, client, id, -+ options, 0, NULL, task, action, arg, -+ rdataset, sigrdataset, fetchp)); -+} -+ -+isc_result_t -+dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, -+ dns_rdatatype_t type, -+ dns_name_t *domain, dns_rdataset_t *nameservers, -+ dns_forwarders_t *forwarders, -+ isc_sockaddr_t *client, dns_messageid_t id, -+ unsigned int options, unsigned int depth, -+ isc_counter_t *qc, isc_task_t *task, -+ isc_taskaction_t action, void *arg, -+ dns_rdataset_t *rdataset, -+ dns_rdataset_t *sigrdataset, -+ dns_fetch_t **fetchp) -+{ - dns_fetch_t *fetch; - fetchctx_t *fctx = NULL; - isc_result_t result = ISC_R_SUCCESS; -@@ -8269,11 +8346,12 @@ dns_resolver_createfetch2(dns_resolver_t - - if (fctx == NULL) { - result = fctx_create(res, name, type, domain, nameservers, -- options, bucketnum, &fctx); -+ options, bucketnum, depth, qc, &fctx); - if (result != ISC_R_SUCCESS) - goto unlock; - new_fctx = ISC_TRUE; -- } -+ } else if (fctx->depth > depth) -+ fctx->depth = depth; - - result = fctx_join(fctx, task, client, id, action, arg, - rdataset, sigrdataset, fetch); -@@ -9045,3 +9123,27 @@ dns_resolver_settimeout(dns_resolver_t * - - resolver->query_timeout = seconds; - } -+ -+void -+dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) { -+ REQUIRE(VALID_RESOLVER(resolver)); -+ resolver->maxdepth = maxdepth; -+} -+ -+unsigned int -+dns_resolver_getmaxdepth(dns_resolver_t *resolver) { -+ REQUIRE(VALID_RESOLVER(resolver)); -+ return (resolver->maxdepth); -+} -+ -+void -+dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) { -+ REQUIRE(VALID_RESOLVER(resolver)); -+ resolver->maxqueries = queries; -+} -+ -+unsigned int -+dns_resolver_getmaxqueries(dns_resolver_t *resolver) { -+ REQUIRE(VALID_RESOLVER(resolver)); -+ return (resolver->maxqueries); -+} -diff -up bind-9.9.4/lib/export/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/export/isc/Makefile.in ---- bind-9.9.4/lib/export/isc/Makefile.in.CVE-2014-8500 2014-12-10 14:56:24.907552500 +0100 -+++ bind-9.9.4/lib/export/isc/Makefile.in 2014-12-10 14:56:24.967552568 +0100 -@@ -63,7 +63,7 @@ WIN32OBJS = win32/condition.@O@ win32/d - # Alphabetically - OBJS = @ISC_EXTRA_OBJS@ \ - assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \ -- base64.@O@ buffer.@O@ bufferlist.@O@ \ -+ base64.@O@ buffer.@O@ bufferlist.@O@ counter.@O@ \ - error.@O@ event.@O@ \ - hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ - inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ -@@ -85,7 +85,7 @@ ISCDRIVERSRCS = mem.c task.c lib.c timer - - SRCS = @ISC_EXTRA_SRCS@ \ - assertions.c backtrace.c backtrace-emptytbl.c base32.c \ -- base64.c buffer.c bufferlist.c \ -+ base64.c buffer.c bufferlist.c counter.c \ - error.c event.c \ - hash.c hex.c hmacmd5.c hmacsha.c \ - inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ -diff -up bind-9.9.4/lib/isccfg/namedconf.c.CVE-2014-8500 bind-9.9.4/lib/isccfg/namedconf.c ---- bind-9.9.4/lib/isccfg/namedconf.c.CVE-2014-8500 2014-12-10 14:56:24.969552570 +0100 -+++ bind-9.9.4/lib/isccfg/namedconf.c 2014-12-10 15:04:14.636091707 +0100 -@@ -1421,6 +1421,8 @@ view_clauses[] = { - { "max-cache-ttl", &cfg_type_uint32, 0 }, - { "max-clients-per-query", &cfg_type_uint32, 0 }, - { "max-ncache-ttl", &cfg_type_uint32, 0 }, -+ { "max-recursion-depth", &cfg_type_uint32, 0 }, -+ { "max-recursion-queries", &cfg_type_uint32, 0 }, - { "max-udp-size", &cfg_type_uint32, 0 }, - { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, - { "minimal-responses", &cfg_type_boolean, 0 }, -diff -up bind-9.9.4/lib/isc/counter.c.CVE-2014-8500 bind-9.9.4/lib/isc/counter.c ---- bind-9.9.4/lib/isc/counter.c.CVE-2014-8500 2014-12-10 14:56:24.968552569 +0100 -+++ bind-9.9.4/lib/isc/counter.c 2014-12-10 14:56:24.968552569 +0100 -@@ -0,0 +1,138 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define COUNTER_MAGIC ISC_MAGIC('C', 'n', 't', 'r') -+#define VALID_COUNTER(r) ISC_MAGIC_VALID(r, COUNTER_MAGIC) -+ -+struct isc_counter { -+ unsigned int magic; -+ isc_mem_t *mctx; -+ isc_mutex_t lock; -+ unsigned int references; -+ unsigned int limit; -+ unsigned int used; -+}; -+ -+isc_result_t -+isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) { -+ isc_result_t result; -+ isc_counter_t *counter; -+ -+ REQUIRE(counterp != NULL && *counterp == NULL); -+ -+ counter = isc_mem_get(mctx, sizeof(*counter)); -+ if (counter == NULL) -+ return (ISC_R_NOMEMORY); -+ -+ result = isc_mutex_init(&counter->lock); -+ if (result != ISC_R_SUCCESS) { -+ isc_mem_put(mctx, counter, sizeof(*counter)); -+ return (result); -+ } -+ -+ counter->mctx = NULL; -+ isc_mem_attach(mctx, &counter->mctx); -+ -+ counter->references = 1; -+ counter->limit = limit; -+ counter->used = 0; -+ -+ counter->magic = COUNTER_MAGIC; -+ *counterp = counter; -+ return (ISC_R_SUCCESS); -+} -+ -+isc_result_t -+isc_counter_increment(isc_counter_t *counter) { -+ isc_result_t result = ISC_R_SUCCESS; -+ -+ LOCK(&counter->lock); -+ counter->used++; -+ if (counter->limit != 0 && counter->used >= counter->limit) -+ result = ISC_R_QUOTA; -+ UNLOCK(&counter->lock); -+ -+ return (result); -+} -+ -+unsigned int -+isc_counter_used(isc_counter_t *counter) { -+ REQUIRE(VALID_COUNTER(counter)); -+ -+ return (counter->used); -+} -+ -+void -+isc_counter_setlimit(isc_counter_t *counter, int limit) { -+ REQUIRE(VALID_COUNTER(counter)); -+ -+ LOCK(&counter->lock); -+ counter->limit = limit; -+ UNLOCK(&counter->lock); -+} -+ -+void -+isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) { -+ REQUIRE(VALID_COUNTER(source)); -+ REQUIRE(targetp != NULL && *targetp == NULL); -+ -+ LOCK(&source->lock); -+ source->references++; -+ INSIST(source->references > 0); -+ UNLOCK(&source->lock); -+ -+ *targetp = source; -+} -+ -+static void -+destroy(isc_counter_t *counter) { -+ counter->magic = 0; -+ isc_mutex_destroy(&counter->lock); -+ isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter)); -+} -+ -+void -+isc_counter_detach(isc_counter_t **counterp) { -+ isc_counter_t *counter; -+ isc_boolean_t want_destroy = ISC_FALSE; -+ -+ REQUIRE(counterp != NULL && *counterp != NULL); -+ counter = *counterp; -+ REQUIRE(VALID_COUNTER(counter)); -+ -+ *counterp = NULL; -+ -+ LOCK(&counter->lock); -+ INSIST(counter->references > 0); -+ counter->references--; -+ if (counter->references == 0) -+ want_destroy = ISC_TRUE; -+ UNLOCK(&counter->lock); -+ -+ if (want_destroy) -+ destroy(counter); -+} -diff -up bind-9.9.4/lib/isc/include/isc/counter.h.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/counter.h ---- bind-9.9.4/lib/isc/include/isc/counter.h.CVE-2014-8500 2014-12-10 14:56:24.968552569 +0100 -+++ bind-9.9.4/lib/isc/include/isc/counter.h 2014-12-10 14:56:24.968552569 +0100 -@@ -0,0 +1,90 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef ISC_COUNTER_H -+#define ISC_COUNTER_H 1 -+ -+/***** -+ ***** Module Info -+ *****/ -+ -+/*! \file isc/counter.h -+ * -+ * \brief The isc_counter_t object is a simplified version of the -+ * isc_quota_t object; it tracks the consumption of limited -+ * resources, returning an error condition when the quota is -+ * exceeded. However, unlike isc_quota_t, attaching and detaching -+ * from a counter object does not increment or decrement the counter. -+ */ -+ -+/*** -+ *** Imports. -+ ***/ -+ -+#include -+#include -+#include -+ -+/***** -+ ***** Types. -+ *****/ -+ -+ISC_LANG_BEGINDECLS -+ -+isc_result_t -+isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp); -+/*%< -+ * Allocate and initialize a counter object. -+ */ -+ -+isc_result_t -+isc_counter_increment(isc_counter_t *counter); -+/*%< -+ * Increment the counter. -+ * -+ * If the counter limit is nonzero and has been reached, then -+ * return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is -+ * incremented regardless of return value.) -+ */ -+ -+unsigned int -+isc_counter_used(isc_counter_t *counter); -+/*%< -+ * Return the current counter value. -+ */ -+ -+void -+isc_counter_setlimit(isc_counter_t *counter, int limit); -+/*%< -+ * Set the counter limit. -+ */ -+ -+void -+isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp); -+/*%< -+ * Attach to a counter object, increasing its reference counter. -+ */ -+ -+void -+isc_counter_detach(isc_counter_t **counterp); -+/*%< -+ * Detach (and destroy if reference counter has dropped to zero) -+ * a counter object. -+ */ -+ -+ISC_LANG_ENDDECLS -+ -+#endif /* ISC_COUNTER_H */ -diff -up bind-9.9.4/lib/isc/include/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/Makefile.in ---- bind-9.9.4/lib/isc/include/isc/Makefile.in.CVE-2014-8500 2014-12-10 15:02:34.811005903 +0100 -+++ bind-9.9.4/lib/isc/include/isc/Makefile.in 2014-12-10 15:03:01.099030322 +0100 -@@ -27,7 +27,7 @@ top_srcdir = @top_srcdir@ - # install target below. - # - HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ -- buffer.h bufferlist.h commandline.h entropy.h error.h event.h \ -+ buffer.h bufferlist.h commandline.h counter.h entropy.h error.h event.h \ - eventclass.h file.h formatcheck.h fsaccess.h \ - hash.h heap.h hex.h hmacmd5.h hmacsha.h \ - httpd.h \ -diff -up bind-9.9.4/lib/isc/include/isc/types.h.CVE-2014-8500 bind-9.9.4/lib/isc/include/isc/types.h ---- bind-9.9.4/lib/isc/include/isc/types.h.CVE-2014-8500 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/lib/isc/include/isc/types.h 2014-12-10 14:56:24.968552569 +0100 -@@ -50,6 +50,7 @@ typedef struct isc_buffer isc_buffer_t; - typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */ - typedef struct isc_constregion isc_constregion_t; /*%< Const region */ - typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */ -+typedef struct isc_counter isc_counter_t; /*%< Counter */ - typedef struct isc_entropy isc_entropy_t; /*%< Entropy */ - typedef struct isc_entropysource isc_entropysource_t; /*%< Entropy Source */ - typedef struct isc_event isc_event_t; /*%< Event */ -diff -up bind-9.9.4/lib/isc/Makefile.in.CVE-2014-8500 bind-9.9.4/lib/isc/Makefile.in ---- bind-9.9.4/lib/isc/Makefile.in.CVE-2014-8500 2014-12-10 14:56:24.860552447 +0100 -+++ bind-9.9.4/lib/isc/Makefile.in 2014-12-10 14:56:24.968552569 +0100 -@@ -53,7 +53,7 @@ WIN32OBJS = win32/condition.@O@ win32/d - OBJS = @ISC_EXTRA_OBJS@ \ - assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \ - bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ -- error.@O@ event.@O@ \ -+ counter.@O@ error.@O@ event.@O@ \ - hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ - httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \ - lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ -@@ -70,8 +70,8 @@ SYMTBLOBJS = backtrace-emptytbl.@O@ - # Alphabetically - SRCS = @ISC_EXTRA_SRCS@ \ - assertions.c backtrace.c base32.c base64.c bitstring.c \ -- buffer.c bufferlist.c commandline.c error.c event.c \ -- heap.c hex.c hmacmd5.c hmacsha.c \ -+ buffer.c bufferlist.c commandline.c counter.c \ -+ error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \ - httpd.c inet_aton.c iterated_hash.c \ - lex.c lfsr.c lib.c log.c \ - md5.c mem.c mutexblock.c \ diff --git a/SOURCES/bind99-CVE-2015-1349.patch b/SOURCES/bind99-CVE-2015-1349.patch deleted file mode 100644 index e484587..0000000 --- a/SOURCES/bind99-CVE-2015-1349.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff -up bind-9.9.4/lib/dns/zone.c.CVE-2015-1349 bind-9.9.4/lib/dns/zone.c ---- bind-9.9.4/lib/dns/zone.c.CVE-2015-1349 2015-03-02 11:18:36.138872044 +0100 -+++ bind-9.9.4/lib/dns/zone.c 2015-03-02 11:20:15.941032102 +0100 -@@ -8456,6 +8456,12 @@ keyfetch_done(isc_task_t *task, isc_even - namebuf, tag); - trustkey = ISC_TRUE; - } -+ } else { -+ /* -+ * No previously known key, and the key is not -+ * secure, so skip it. -+ */ -+ continue; - } - - /* Delete old version */ -@@ -8504,7 +8510,7 @@ keyfetch_done(isc_task_t *task, isc_even - trust_key(zone, keyname, &dnskey, mctx); - } - -- if (!deletekey) -+ if (secure && !deletekey) - set_refreshkeytimer(zone, &keydata, now); - } - diff --git a/SOURCES/bind99-CVE-2015-4620.patch b/SOURCES/bind99-CVE-2015-4620.patch deleted file mode 100644 index b0468be..0000000 --- a/SOURCES/bind99-CVE-2015-4620.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/lib/dns/validator.c b/lib/dns/validator.c ---- a/lib/dns/validator.c -+++ b/lib/dns/validator.c -@@ -1422,7 +1422,6 @@ compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) { - */ - static isc_boolean_t - isselfsigned(dns_validator_t *val) { -- dns_fixedname_t fixed; - dns_rdataset_t *rdataset, *sigrdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_t sigrdata = DNS_RDATA_INIT; -@@ -1478,8 +1477,7 @@ isselfsigned(dns_validator_t *val) { - result = dns_dnssec_verify3(name, rdataset, dstkey, - ISC_TRUE, - val->view->maxbits, -- mctx, &sigrdata, -- dns_fixedname_name(&fixed)); -+ mctx, &sigrdata, NULL); - dst_key_free(&dstkey); - if (result != ISC_R_SUCCESS) - continue; diff --git a/SOURCES/bind99-CVE-2015-5477.patch b/SOURCES/bind99-CVE-2015-5477.patch deleted file mode 100644 index c3a6e29..0000000 --- a/SOURCES/bind99-CVE-2015-5477.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -up bind-9.9.4/lib/dns/tkey.c.CVE-2015-5477 bind-9.9.4/lib/dns/tkey.c ---- bind-9.9.4/lib/dns/tkey.c.CVE-2015-5477 2015-07-27 22:36:02.318505839 +0200 -+++ bind-9.9.4/lib/dns/tkey.c 2015-07-27 22:36:39.764698712 +0200 -@@ -650,6 +650,7 @@ dns_tkey_processquery(dns_message_t *msg - * Try the answer section, since that's where Win2000 - * puts it. - */ -+ name = NULL; - if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname, - dns_rdatatype_tkey, 0, &name, - &tkeyset) != ISC_R_SUCCESS) { diff --git a/SOURCES/bind99-CVE-2015-5722.patch b/SOURCES/bind99-CVE-2015-5722.patch deleted file mode 100644 index bb240ac..0000000 --- a/SOURCES/bind99-CVE-2015-5722.patch +++ /dev/null @@ -1,449 +0,0 @@ -diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c -index 7a56c79..3ac01a8 100644 ---- a/lib/dns/hmac_link.c -+++ b/lib/dns/hmac_link.c -@@ -76,7 +76,7 @@ hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) { - hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t)); - if (hmacmd5ctx == NULL) - return (ISC_R_NOMEMORY); -- isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH); -+ isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_MD5_BLOCK_LENGTH); - dctx->ctxdata.hmacmd5ctx = hmacmd5ctx; - return (ISC_R_SUCCESS); - } -@@ -139,7 +139,7 @@ hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) { - else if (hkey1 == NULL || hkey2 == NULL) - return (ISC_FALSE); - -- if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH)) -+ if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_MD5_BLOCK_LENGTH)) - return (ISC_TRUE); - else - return (ISC_FALSE); -@@ -150,17 +150,17 @@ hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) { - isc_buffer_t b; - isc_result_t ret; - unsigned int bytes; -- unsigned char data[ISC_SHA1_BLOCK_LENGTH]; -+ unsigned char data[ISC_MD5_BLOCK_LENGTH]; - - UNUSED(callback); - - bytes = (key->key_size + 7) / 8; -- if (bytes > ISC_SHA1_BLOCK_LENGTH) { -- bytes = ISC_SHA1_BLOCK_LENGTH; -- key->key_size = ISC_SHA1_BLOCK_LENGTH * 8; -+ if (bytes > ISC_MD5_BLOCK_LENGTH) { -+ bytes = ISC_MD5_BLOCK_LENGTH; -+ key->key_size = ISC_MD5_BLOCK_LENGTH * 8; - } - -- memset(data, 0, ISC_SHA1_BLOCK_LENGTH); -+ memset(data, 0, ISC_MD5_BLOCK_LENGTH); - ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0)); - - if (ret != ISC_R_SUCCESS) -@@ -169,7 +169,7 @@ hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) { - isc_buffer_init(&b, data, bytes); - isc_buffer_add(&b, bytes); - ret = hmacmd5_fromdns(key, &b); -- memset(data, 0, ISC_SHA1_BLOCK_LENGTH); -+ memset(data, 0, ISC_MD5_BLOCK_LENGTH); - - return (ret); - } -@@ -223,7 +223,7 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) { - - memset(hkey->key, 0, sizeof(hkey->key)); - -- if (r.length > ISC_SHA1_BLOCK_LENGTH) { -+ if (r.length > ISC_MD5_BLOCK_LENGTH) { - isc_md5_init(&md5ctx); - isc_md5_update(&md5ctx, r.base, r.length); - isc_md5_final(&md5ctx, hkey->key); -@@ -237,6 +237,8 @@ hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) { - key->key_size = keylen * 8; - key->keydata.hmacmd5 = hkey; - -+ isc_buffer_forward(data, r.length); -+ - return (ISC_R_SUCCESS); - } - -@@ -518,6 +520,8 @@ hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) { - key->key_size = keylen * 8; - key->keydata.hmacsha1 = hkey; - -+ isc_buffer_forward(data, r.length); -+ - return (ISC_R_SUCCESS); - } - -@@ -804,6 +808,8 @@ hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) { - key->key_size = keylen * 8; - key->keydata.hmacsha224 = hkey; - -+ isc_buffer_forward(data, r.length); -+ - return (ISC_R_SUCCESS); - } - -@@ -1090,6 +1096,8 @@ hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) { - key->key_size = keylen * 8; - key->keydata.hmacsha256 = hkey; - -+ isc_buffer_forward(data, r.length); -+ - return (ISC_R_SUCCESS); - } - -@@ -1376,6 +1384,8 @@ hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) { - key->key_size = keylen * 8; - key->keydata.hmacsha384 = hkey; - -+ isc_buffer_forward(data, r.length); -+ - return (ISC_R_SUCCESS); - } - -@@ -1662,6 +1672,8 @@ hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) { - key->key_size = keylen * 8; - key->keydata.hmacsha512 = hkey; - -+ isc_buffer_forward(data, r.length); -+ - return (ISC_R_SUCCESS); - } - -diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h -index bdbd269..37853aa 100644 ---- a/lib/dns/include/dst/dst.h -+++ b/lib/dns/include/dst/dst.h -@@ -69,6 +69,7 @@ typedef struct dst_context dst_context_t; - #define DST_ALG_HMACSHA256 163 /* XXXMPA */ - #define DST_ALG_HMACSHA384 164 /* XXXMPA */ - #define DST_ALG_HMACSHA512 165 /* XXXMPA */ -+#define DST_ALG_INDIRECT 252 - #define DST_ALG_PRIVATE 254 - #define DST_ALG_EXPAND 255 - #define DST_MAX_ALGS 255 -diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c -index bcb3d05..3114954 100644 ---- a/lib/dns/ncache.c -+++ b/lib/dns/ncache.c -@@ -614,13 +614,11 @@ dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, - dns_name_fromregion(&tname, &remaining); - INSIST(remaining.length >= tname.length); - isc_buffer_forward(&source, tname.length); -- remaining.length -= tname.length; -- remaining.base += tname.length; -+ isc_region_consume(&remaining, tname.length); - - INSIST(remaining.length >= 2); - type = isc_buffer_getuint16(&source); -- remaining.length -= 2; -- remaining.base += 2; -+ isc_region_consume(&remaining, 2); - - if (type != dns_rdatatype_rrsig || - !dns_name_equal(&tname, name)) { -@@ -632,8 +630,7 @@ dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name, - INSIST(remaining.length >= 1); - trust = isc_buffer_getuint8(&source); - INSIST(trust <= dns_trust_ultimate); -- remaining.length -= 1; -- remaining.base += 1; -+ isc_region_consume(&remaining, 1); - - raw = remaining.base; - count = raw[0] * 256 + raw[1]; -diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c -index 55752da..f0cee8d 100644 ---- a/lib/dns/openssldh_link.c -+++ b/lib/dns/openssldh_link.c -@@ -266,8 +266,10 @@ openssldh_destroy(dst_key_t *key) { - - static void - uint16_toregion(isc_uint16_t val, isc_region_t *region) { -- *region->base++ = (val & 0xff00) >> 8; -- *region->base++ = (val & 0x00ff); -+ *region->base = (val & 0xff00) >> 8; -+ isc_region_consume(region, 1); -+ *region->base = (val & 0x00ff); -+ isc_region_consume(region, 1); - } - - static isc_uint16_t -@@ -278,7 +280,8 @@ uint16_fromregion(isc_region_t *region) { - val = ((unsigned int)(cp[0])) << 8; - val |= ((unsigned int)(cp[1])); - -- region->base += 2; -+ isc_region_consume(region, 2); -+ - return (val); - } - -@@ -319,16 +322,16 @@ openssldh_todns(const dst_key_t *key, isc_buffer_t *data) { - } - else - BN_bn2bin(dh->p, r.base); -- r.base += plen; -+ isc_region_consume(&r, plen); - - uint16_toregion(glen, &r); - if (glen > 0) - BN_bn2bin(dh->g, r.base); -- r.base += glen; -+ isc_region_consume(&r, glen); - - uint16_toregion(publen, &r); - BN_bn2bin(dh->pub_key, r.base); -- r.base += publen; -+ isc_region_consume(&r, publen); - - isc_buffer_add(data, dnslen); - -@@ -369,10 +372,12 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { - return (DST_R_INVALIDPUBLICKEY); - } - if (plen == 1 || plen == 2) { -- if (plen == 1) -- special = *r.base++; -- else -+ if (plen == 1) { -+ special = *r.base; -+ isc_region_consume(&r, 1); -+ } else { - special = uint16_fromregion(&r); -+ } - switch (special) { - case 1: - dh->p = &bn768; -@@ -387,10 +392,9 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { - DH_free(dh); - return (DST_R_INVALIDPUBLICKEY); - } -- } -- else { -+ } else { - dh->p = BN_bin2bn(r.base, plen, NULL); -- r.base += plen; -+ isc_region_consume(&r, plen); - } - - /* -@@ -421,15 +425,14 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { - return (DST_R_INVALIDPUBLICKEY); - } - } -- } -- else { -+ } else { - if (glen == 0) { - DH_free(dh); - return (DST_R_INVALIDPUBLICKEY); - } - dh->g = BN_bin2bn(r.base, glen, NULL); - } -- r.base += glen; -+ isc_region_consume(&r, glen); - - if (r.length < 2) { - DH_free(dh); -@@ -441,7 +444,7 @@ openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) { - return (DST_R_INVALIDPUBLICKEY); - } - dh->pub_key = BN_bin2bn(r.base, publen, NULL); -- r.base += publen; -+ isc_region_consume(&r, publen); - - key->key_size = BN_num_bits(dh->p); - -diff --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c -index fd6e91e..8e16557 100644 ---- a/lib/dns/openssldsa_link.c -+++ b/lib/dns/openssldsa_link.c -@@ -137,6 +135,7 @@ openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { - DSA *dsa = key->keydata.dsa; - isc_region_t r; - DSA_SIG *dsasig; -+ unsigned int klen; - #if USE_EVP - EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; - EVP_PKEY *pkey; -@@ -209,11 +209,17 @@ openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { - "DSA_do_sign", - DST_R_SIGNFAILURE)); - #endif -- *r.base++ = (key->key_size - 512)/64; -+ -+ klen = (key->key_size - 512)/64; -+ if (klen > 255) -+ return (ISC_R_FAILURE); -+ *r.base = klen; -+ isc_region_consume(&r, 1); -+ - BN_bn2bin_fixed(dsasig->r, r.base, ISC_SHA1_DIGESTLENGTH); -- r.base += ISC_SHA1_DIGESTLENGTH; -+ isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH); - BN_bn2bin_fixed(dsasig->s, r.base, ISC_SHA1_DIGESTLENGTH); -- r.base += ISC_SHA1_DIGESTLENGTH; -+ isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH); - DSA_SIG_free(dsasig); - isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1); - -@@ -446,15 +452,16 @@ openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) { - if (r.length < (unsigned int) dnslen) - return (ISC_R_NOSPACE); - -- *r.base++ = t; -+ *r.base = t; -+ isc_region_consume(&r, 1); - BN_bn2bin_fixed(dsa->q, r.base, ISC_SHA1_DIGESTLENGTH); -- r.base += ISC_SHA1_DIGESTLENGTH; -+ isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH); - BN_bn2bin_fixed(dsa->p, r.base, key->key_size/8); -- r.base += p_bytes; -+ isc_region_consume(&r, p_bytes); - BN_bn2bin_fixed(dsa->g, r.base, key->key_size/8); -- r.base += p_bytes; -+ isc_region_consume(&r, p_bytes); - BN_bn2bin_fixed(dsa->pub_key, r.base, key->key_size/8); -- r.base += p_bytes; -+ isc_region_consume(&r, p_bytes); - - isc_buffer_add(data, dnslen); - -@@ -479,29 +486,30 @@ openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - return (ISC_R_NOMEMORY); - dsa->flags &= ~DSA_FLAG_CACHE_MONT_P; - -- t = (unsigned int) *r.base++; -+ t = (unsigned int) *r.base; -+ isc_region_consume(&r, 1); - if (t > 8) { - DSA_free(dsa); - return (DST_R_INVALIDPUBLICKEY); - } - p_bytes = 64 + 8 * t; - -- if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) { -+ if (r.length < ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) { - DSA_free(dsa); - return (DST_R_INVALIDPUBLICKEY); - } - - dsa->q = BN_bin2bn(r.base, ISC_SHA1_DIGESTLENGTH, NULL); -- r.base += ISC_SHA1_DIGESTLENGTH; -+ isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH); - - dsa->p = BN_bin2bn(r.base, p_bytes, NULL); -- r.base += p_bytes; -+ isc_region_consume(&r, p_bytes); - - dsa->g = BN_bin2bn(r.base, p_bytes, NULL); -- r.base += p_bytes; -+ isc_region_consume(&r, p_bytes); - - dsa->pub_key = BN_bin2bn(r.base, p_bytes, NULL); -- r.base += p_bytes; -+ isc_region_consume(&r, p_bytes); - - key->key_size = p_bytes * 8; - -diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c -index c64cc55..40c612b 100644 ---- a/lib/dns/opensslecdsa_link.c -+++ b/lib/dns/opensslecdsa_link.c -@@ -159,9 +157,9 @@ opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { - "ECDSA_do_sign", - DST_R_SIGNFAILURE)); - BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2); -- r.base += siglen / 2; -+ isc_region_consume(&r, siglen / 2); - BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2); -- r.base += siglen / 2; -+ isc_region_consume(&r, siglen / 2); - ECDSA_SIG_free(ecdsasig); - isc_buffer_add(sig, siglen); - ret = ISC_R_SUCCESS; -diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c -index 1edeb8d..53c6d4b 100644 ---- a/lib/dns/opensslrsa_link.c -+++ b/lib/dns/opensslrsa_link.c -@@ -965,6 +965,7 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - RSA *rsa; - isc_region_t r; - unsigned int e_bytes; -+ unsigned int length; - #if USE_EVP - EVP_PKEY *pkey; - #endif -@@ -972,6 +973,7 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - isc_buffer_remainingregion(data, &r); - if (r.length == 0) - return (ISC_R_SUCCESS); -+ length = r.length; - - rsa = RSA_new(); - if (rsa == NULL) -@@ -982,17 +984,18 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - RSA_free(rsa); - return (DST_R_INVALIDPUBLICKEY); - } -- e_bytes = *r.base++; -- r.length--; -+ e_bytes = *r.base; -+ isc_region_consume(&r, 1); - - if (e_bytes == 0) { - if (r.length < 2) { - RSA_free(rsa); - return (DST_R_INVALIDPUBLICKEY); - } -- e_bytes = ((*r.base++) << 8); -- e_bytes += *r.base++; -- r.length -= 2; -+ e_bytes = (*r.base) << 8; -+ isc_region_consume(&r, 1); -+ e_bytes += *r.base; -+ isc_region_consume(&r, 1); - } - - if (r.length < e_bytes) { -@@ -1000,14 +1003,13 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { - return (DST_R_INVALIDPUBLICKEY); - } - rsa->e = BN_bin2bn(r.base, e_bytes, NULL); -- r.base += e_bytes; -- r.length -= e_bytes; -+ isc_region_consume(&r, e_bytes); - - rsa->n = BN_bin2bn(r.base, r.length, NULL); - - key->key_size = BN_num_bits(rsa->n); - -- isc_buffer_forward(data, r.length); -+ isc_buffer_forward(data, length); - - #if USE_EVP - pkey = EVP_PKEY_new(); -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 2004b0b..c7971b1 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -8959,6 +8959,12 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name, - - REQUIRE(VALID_RESOLVER(resolver)); - -+ /* -+ * DH is unsupported for DNSKEYs, see RFC 4034 sec. A.1. -+ */ -+ if ((alg == DST_ALG_DH) || (alg == DST_ALG_INDIRECT)) -+ return (ISC_FALSE); -+ - #if USE_ALGLOCK - RWLOCK(&resolver->alglock, isc_rwlocktype_read); - #endif - diff --git a/SOURCES/bind99-CVE-2015-8000.patch b/SOURCES/bind99-CVE-2015-8000.patch deleted file mode 100644 index c7247f5..0000000 --- a/SOURCES/bind99-CVE-2015-8000.patch +++ /dev/null @@ -1,179 +0,0 @@ -diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h -index a6862fa..d999e75 100644 ---- a/lib/dns/include/dns/message.h -+++ b/lib/dns/include/dns/message.h -@@ -210,6 +210,8 @@ struct dns_message { - unsigned int verify_attempted : 1; - unsigned int free_query : 1; - unsigned int free_saved : 1; -+ unsigned int tkey : 1; -+ unsigned int rdclass_set : 1; - - unsigned int opt_reserved; - unsigned int sig_reserved; -@@ -1374,6 +1376,15 @@ dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt, - * \li other. - */ - -+void -+dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass); -+/*%< -+ * Set the expected class of records in the response. -+ * -+ * Requires: -+ * \li msg be a valid message with parsing intent. -+ */ -+ - ISC_LANG_ENDDECLS - - #endif /* DNS_MESSAGE_H */ -diff --git a/lib/dns/message.c b/lib/dns/message.c -index 53efc5a..73def73 100644 ---- a/lib/dns/message.c -+++ b/lib/dns/message.c -@@ -436,6 +436,8 @@ msginit(dns_message_t *m) { - m->saved.base = NULL; - m->saved.length = 0; - m->free_saved = 0; -+ m->tkey = 0; -+ m->rdclass_set = 0; - m->querytsig = NULL; - } - -@@ -1086,13 +1088,19 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - * If this class is different than the one we already read, - * this is an error. - */ -- if (msg->state == DNS_SECTION_ANY) { -- msg->state = DNS_SECTION_QUESTION; -+ if (msg->rdclass_set == 0) { - msg->rdclass = rdclass; -+ msg->rdclass_set = 1; - } else if (msg->rdclass != rdclass) - DO_FORMERR; - - /* -+ * Is this a TKEY query? -+ */ -+ if (rdtype == dns_rdatatype_tkey) -+ msg->tkey = 1; -+ -+ /* - * Can't ask the same question twice. - */ - result = dns_message_find(name, rdclass, rdtype, 0, NULL); -@@ -1236,12 +1244,12 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - * If there was no question section, we may not yet have - * established a class. Do so now. - */ -- if (msg->state == DNS_SECTION_ANY && -+ if (msg->rdclass_set == 0 && - rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ - rdtype != dns_rdatatype_tsig && /* class is ANY */ - rdtype != dns_rdatatype_tkey) { /* class is undefined */ - msg->rdclass = rdclass; -- msg->state = DNS_SECTION_QUESTION; -+ msg->rdclass_set = 1; - } - - /* -@@ -1251,7 +1259,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - if (msg->opcode != dns_opcode_update - && rdtype != dns_rdatatype_tsig - && rdtype != dns_rdatatype_opt -- && rdtype != dns_rdatatype_dnskey /* in a TKEY query */ -+ && rdtype != dns_rdatatype_key /* in a TKEY query */ - && rdtype != dns_rdatatype_sig /* SIG(0) */ - && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */ - && msg->rdclass != dns_rdataclass_any -@@ -1259,6 +1267,16 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - DO_FORMERR; - - /* -+ * If this is not a TKEY query/response then the KEY -+ * record's class needs to match. -+ */ -+ if (msg->opcode != dns_opcode_update && !msg->tkey && -+ rdtype == dns_rdatatype_key && -+ msg->rdclass != dns_rdataclass_any && -+ msg->rdclass != rdclass) -+ DO_FORMERR; -+ -+ /* - * Special type handling for TSIG, OPT, and TKEY. - */ - if (rdtype == dns_rdatatype_tsig) { -@@ -1372,6 +1390,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - skip_name_search = ISC_TRUE; - skip_type_search = ISC_TRUE; - issigzero = ISC_TRUE; -+ } else { -+ if (msg->rdclass != dns_rdataclass_any && -+ msg->rdclass != rdclass) -+ DO_FORMERR; - } - } else - covers = 0; -@@ -1610,6 +1632,7 @@ dns_message_parse(dns_message_t *msg, isc_buffer_t *source, - msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); - - msg->header_ok = 1; -+ msg->state = DNS_SECTION_QUESTION; - - /* - * -1 means no EDNS. -@@ -3550,3 +3573,15 @@ dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp, - dns_message_puttemprdatalist(message, &rdatalist); - return (result); - } -+ -+void -+dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass) { -+ -+ REQUIRE(DNS_MESSAGE_VALID(msg)); -+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); -+ REQUIRE(msg->state == DNS_SECTION_ANY); -+ REQUIRE(msg->rdclass_set == 0); -+ -+ msg->rdclass = rdclass; -+ msg->rdclass_set = 1; -+} -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index aa23b11..d220986 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -6964,6 +6964,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - goto done; - } - -+ dns_message_setclass(message, fctx->res->rdclass); -+ - result = dns_message_parse(message, &devent->buffer, 0); - if (result != ISC_R_SUCCESS) { - switch (result) { -@@ -7036,6 +7038,12 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - */ - log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx); - -+ if (message->rdclass != fctx->res->rdclass) { -+ resend = ISC_TRUE; -+ FCTXTRACE("bad class"); -+ goto done; -+ } -+ - /* - * Process receive opt record. - */ -diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c -index 9ad8960..938373a 100644 ---- a/lib/dns/xfrin.c -+++ b/lib/dns/xfrin.c -@@ -1241,6 +1241,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { - msg->tsigctx = xfr->tsigctx; - xfr->tsigctx = NULL; - -+ dns_message_setclass(msg, xfr->rdclass); -+ - if (xfr->nmsg > 0) - msg->tcp_continuation = 1; - diff --git a/SOURCES/bind99-CVE-2015-8704.patch b/SOURCES/bind99-CVE-2015-8704.patch deleted file mode 100644 index 4aa41f2..0000000 --- a/SOURCES/bind99-CVE-2015-8704.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c -index eb927b9..df35025 100644 ---- a/lib/dns/rdata/in_1/apl_42.c -+++ b/lib/dns/rdata/in_1/apl_42.c -@@ -116,7 +116,7 @@ totext_in_apl(ARGS_TOTEXT) { - isc_uint8_t len; - isc_boolean_t neg; - unsigned char buf[16]; -- char txt[sizeof(" !64000")]; -+ char txt[sizeof(" !64000:")]; - const char *sep = ""; - int n; - -@@ -140,7 +140,7 @@ totext_in_apl(ARGS_TOTEXT) { - isc_region_consume(&sr, 1); - INSIST(len <= sr.length); - n = snprintf(txt, sizeof(txt), "%s%s%u:", sep, -- neg ? "!": "", afi); -+ neg ? "!" : "", afi); - INSIST(n < (int)sizeof(txt)); - RETERR(str_totext(txt, target)); - switch (afi) { diff --git a/SOURCES/bind99-CVE-2016-1285-CVE-2016-1286.patch b/SOURCES/bind99-CVE-2016-1285-CVE-2016-1286.patch deleted file mode 100644 index 920825b..0000000 --- a/SOURCES/bind99-CVE-2016-1285-CVE-2016-1286.patch +++ /dev/null @@ -1,431 +0,0 @@ -diff --git a/bin/named/control.c b/bin/named/control.c -index fabe442..06eadce 100644 ---- a/bin/named/control.c -+++ b/bin/named/control.c -@@ -69,7 +69,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { - #endif - - data = isccc_alist_lookup(message, "_data"); -- if (data == NULL) { -+ if (!isccc_alist_alistp(data)) { - /* - * No data section. - */ -diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c -index c46a6e1..ef32790 100644 ---- a/bin/named/controlconf.c -+++ b/bin/named/controlconf.c -@@ -396,7 +396,7 @@ control_recvmessage(isc_task_t *task, isc_event_t *event) { - * Limit exposure to replay attacks. - */ - _ctrl = isccc_alist_lookup(request, "_ctrl"); -- if (_ctrl == NULL) { -+ if (!isccc_alist_alistp(_ctrl)) { - log_invalid(&conn->ccmsg, ISC_R_FAILURE); - goto cleanup_request; - } -diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c -index ba2c3f6..9a007e2 100644 ---- a/bin/rndc/rndc.c -+++ b/bin/rndc/rndc.c -@@ -252,8 +252,8 @@ rndc_recvdone(isc_task_t *task, isc_event_t *event) { - DO("parse message", isccc_cc_fromwire(&source, &response, &secret)); - - data = isccc_alist_lookup(response, "_data"); -- if (data == NULL) -- fatal("no data section in response"); -+ if (!isccc_alist_alistp(data)) -+ fatal("bad or missing data section in response"); - result = isccc_cc_lookupstring(data, "err", &errormsg); - if (result == ISC_R_SUCCESS) { - failed = ISC_TRUE; -@@ -316,8 +316,8 @@ rndc_recvnonce(isc_task_t *task, isc_event_t *event) { - DO("parse message", isccc_cc_fromwire(&source, &response, &secret)); - - _ctrl = isccc_alist_lookup(response, "_ctrl"); -- if (_ctrl == NULL) -- fatal("_ctrl section missing"); -+ if (!isccc_alist_alistp(_ctrl)) -+ fatal("bad or missing ctrl section in response"); - nonce = 0; - if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS) - nonce = 0; -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index d220986..8696b15 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -5408,14 +5408,11 @@ cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) { - } - - static inline isc_result_t --dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname, -- dns_name_t *oname, dns_fixedname_t *fixeddname) -+dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, -+ unsigned int nlabels, dns_fixedname_t *fixeddname) - { - isc_result_t result; - dns_rdata_t rdata = DNS_RDATA_INIT; -- unsigned int nlabels; -- int order; -- dns_namereln_t namereln; - dns_rdata_dname_t dname; - dns_fixedname_t prefix; - -@@ -5430,21 +5427,6 @@ dname_target(fetchctx_t *fctx, dns_rdataset_t *rdataset, dns_name_t *qname, - if (result != ISC_R_SUCCESS) - return (result); - -- /* -- * Get the prefix of qname. -- */ -- namereln = dns_name_fullcompare(qname, oname, &order, &nlabels); -- if (namereln != dns_namereln_subdomain) { -- char qbuf[DNS_NAME_FORMATSIZE]; -- char obuf[DNS_NAME_FORMATSIZE]; -- -- dns_rdata_freestruct(&dname); -- dns_name_format(qname, qbuf, sizeof(qbuf)); -- dns_name_format(oname, obuf, sizeof(obuf)); -- log_formerr(fctx, "unrelated DNAME in answer: " -- "%s is not in %s", qbuf, obuf); -- return (DNS_R_FORMERR); -- } - dns_fixedname_init(&prefix); - dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL); - dns_fixedname_init(fixeddname); -@@ -6057,13 +6039,13 @@ static isc_result_t - answer_response(fetchctx_t *fctx) { - isc_result_t result; - dns_message_t *message; -- dns_name_t *name, *qname, tname, *ns_name; -+ dns_name_t *name, *dname = NULL, *qname, tname, *ns_name; - dns_rdataset_t *rdataset, *ns_rdataset; - isc_boolean_t done, external, chaining, aa, found, want_chaining; - isc_boolean_t have_answer, found_cname, found_type, wanted_chaining; - unsigned int aflag; - dns_rdatatype_t type; -- dns_fixedname_t dname, fqname; -+ dns_fixedname_t fdname, fqname; - dns_view_t *view; - - FCTXTRACE("answer_response"); -@@ -6091,10 +6073,15 @@ answer_response(fetchctx_t *fctx) { - view = fctx->res->view; - result = dns_message_firstname(message, DNS_SECTION_ANSWER); - while (!done && result == ISC_R_SUCCESS) { -+ dns_namereln_t namereln; -+ int order; -+ unsigned int nlabels; -+ - name = NULL; - dns_message_currentname(message, DNS_SECTION_ANSWER, &name); - external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); -- if (dns_name_equal(name, qname)) { -+ namereln = dns_name_fullcompare(qname, name, &order, &nlabels); -+ if (namereln == dns_namereln_equal) { - wanted_chaining = ISC_FALSE; - for (rdataset = ISC_LIST_HEAD(name->list); - rdataset != NULL; -@@ -6219,10 +6206,11 @@ answer_response(fetchctx_t *fctx) { - */ - INSIST(!external); - if (aflag == -- DNS_RDATASETATTR_ANSWER) -+ DNS_RDATASETATTR_ANSWER) { - have_answer = ISC_TRUE; -- name->attributes |= -- DNS_NAMEATTR_ANSWER; -+ name->attributes |= -+ DNS_NAMEATTR_ANSWER; -+ } - rdataset->attributes |= aflag; - if (aa) - rdataset->trust = -@@ -6277,6 +6265,8 @@ answer_response(fetchctx_t *fctx) { - if (wanted_chaining) - chaining = ISC_TRUE; - } else { -+ dns_rdataset_t *dnameset = NULL; -+ - /* - * Look for a DNAME (or its SIG). Anything else is - * ignored. -@@ -6284,32 +6274,56 @@ answer_response(fetchctx_t *fctx) { - wanted_chaining = ISC_FALSE; - for (rdataset = ISC_LIST_HEAD(name->list); - rdataset != NULL; -- rdataset = ISC_LIST_NEXT(rdataset, link)) { -- isc_boolean_t found_dname = ISC_FALSE; -- dns_name_t *dname_name; -+ rdataset = ISC_LIST_NEXT(rdataset, link)) -+ { -+ /* -+ * Only pass DNAME or RRSIG(DNAME). -+ */ -+ if (rdataset->type != dns_rdatatype_dname && -+ (rdataset->type != dns_rdatatype_rrsig || -+ rdataset->covers != dns_rdatatype_dname)) -+ continue; -+ -+ /* -+ * If we're not chaining, then the DNAME and -+ * its signature should not be external. -+ */ -+ if (!chaining && external) { -+ char qbuf[DNS_NAME_FORMATSIZE]; -+ char obuf[DNS_NAME_FORMATSIZE]; -+ -+ dns_name_format(name, qbuf, -+ sizeof(qbuf)); -+ dns_name_format(&fctx->domain, obuf, -+ sizeof(obuf)); -+ log_formerr(fctx, "external DNAME or " -+ "RRSIG covering DNAME " -+ "in answer: %s is " -+ "not in %s", qbuf, obuf); -+ return (DNS_R_FORMERR); -+ } -+ -+ if (namereln != dns_namereln_subdomain) { -+ char qbuf[DNS_NAME_FORMATSIZE]; -+ char obuf[DNS_NAME_FORMATSIZE]; -+ -+ dns_name_format(qname, qbuf, -+ sizeof(qbuf)); -+ dns_name_format(name, obuf, -+ sizeof(obuf)); -+ log_formerr(fctx, "unrelated DNAME " -+ "in answer: %s is " -+ "not in %s", qbuf, obuf); -+ return (DNS_R_FORMERR); -+ } - -- found = ISC_FALSE; - aflag = 0; - if (rdataset->type == dns_rdatatype_dname) { -- /* -- * We're looking for something else, -- * but we found a DNAME. -- * -- * If we're not chaining, then the -- * DNAME should not be external. -- */ -- if (!chaining && external) { -- log_formerr(fctx, -- "external DNAME"); -- return (DNS_R_FORMERR); -- } -- found = ISC_TRUE; - want_chaining = ISC_TRUE; - POST(want_chaining); - aflag = DNS_RDATASETATTR_ANSWER; -- result = dname_target(fctx, rdataset, -- qname, name, -- &dname); -+ result = dname_target(rdataset, qname, -+ nlabels, &fdname); - if (result == ISC_R_NOSPACE) { - /* - * We can't construct the -@@ -6321,90 +6335,73 @@ answer_response(fetchctx_t *fctx) { - } else if (result != ISC_R_SUCCESS) - return (result); - else -- found_dname = ISC_TRUE; -+ dnameset = rdataset; - -- dname_name = dns_fixedname_name(&dname); -+ dname = dns_fixedname_name(&fdname); - if (!is_answertarget_allowed(view, -- qname, -- rdataset->type, -- dname_name, -- &fctx->domain)) { -+ qname, rdataset->type, -+ dname, &fctx->domain)) { - return (DNS_R_SERVFAIL); - } -- } else if (rdataset->type == dns_rdatatype_rrsig -- && rdataset->covers == -- dns_rdatatype_dname) { -+ } else { - /* - * We've found a signature that - * covers the DNAME. - */ -- found = ISC_TRUE; - aflag = DNS_RDATASETATTR_ANSWERSIG; - } - -- if (found) { -+ /* -+ * We've found an answer to our -+ * question. -+ */ -+ name->attributes |= DNS_NAMEATTR_CACHE; -+ rdataset->attributes |= DNS_RDATASETATTR_CACHE; -+ rdataset->trust = dns_trust_answer; -+ if (!chaining) { - /* -- * We've found an answer to our -- * question. -+ * This data is "the" answer to -+ * our question only if we're -+ * not chaining. - */ -- name->attributes |= -- DNS_NAMEATTR_CACHE; -- rdataset->attributes |= -- DNS_RDATASETATTR_CACHE; -- rdataset->trust = dns_trust_answer; -- if (!chaining) { -- /* -- * This data is "the" answer -- * to our question only if -- * we're not chaining. -- */ -- INSIST(!external); -- if (aflag == -- DNS_RDATASETATTR_ANSWER) -- have_answer = ISC_TRUE; -+ INSIST(!external); -+ if (aflag == DNS_RDATASETATTR_ANSWER) { -+ have_answer = ISC_TRUE; - name->attributes |= - DNS_NAMEATTR_ANSWER; -- rdataset->attributes |= aflag; -- if (aa) -- rdataset->trust = -- dns_trust_authanswer; -- } else if (external) { -- rdataset->attributes |= -- DNS_RDATASETATTR_EXTERNAL; -- } -- -- /* -- * DNAME chaining. -- */ -- if (found_dname) { -- /* -- * Copy the dname into the -- * qname fixed name. -- * -- * Although we check for -- * failure of the copy -- * operation, in practice it -- * should never fail since -- * we already know that the -- * result fits in a fixedname. -- */ -- dns_fixedname_init(&fqname); -- result = dns_name_copy( -- dns_fixedname_name(&dname), -- dns_fixedname_name(&fqname), -- NULL); -- if (result != ISC_R_SUCCESS) -- return (result); -- wanted_chaining = ISC_TRUE; -- name->attributes |= -- DNS_NAMEATTR_CHAINING; -- rdataset->attributes |= -- DNS_RDATASETATTR_CHAINING; -- qname = dns_fixedname_name( -- &fqname); - } -+ rdataset->attributes |= aflag; -+ if (aa) -+ rdataset->trust = -+ dns_trust_authanswer; -+ } else if (external) { -+ rdataset->attributes |= -+ DNS_RDATASETATTR_EXTERNAL; - } - } -+ -+ /* -+ * DNAME chaining. -+ */ -+ if (dnameset != NULL) { -+ /* -+ * Copy the dname into the qname fixed name. -+ * -+ * Although we check for failure of the copy -+ * operation, in practice it should never fail -+ * since we already know that the result fits -+ * in a fixedname. -+ */ -+ dns_fixedname_init(&fqname); -+ qname = dns_fixedname_name(&fqname); -+ result = dns_name_copy(dname, qname, NULL); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ wanted_chaining = ISC_TRUE; -+ name->attributes |= DNS_NAMEATTR_CHAINING; -+ dnameset->attributes |= -+ DNS_RDATASETATTR_CHAINING; -+ } - if (wanted_chaining) - chaining = ISC_TRUE; - } -diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c -index ae5391a..10e5dc9 100644 ---- a/lib/isccc/cc.c -+++ b/lib/isccc/cc.c -@@ -286,10 +286,10 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, - * Extract digest. - */ - _auth = isccc_alist_lookup(alist, "_auth"); -- if (_auth == NULL) -+ if (!isccc_alist_alistp(_auth)) - return (ISC_R_FAILURE); - hmd5 = isccc_alist_lookup(_auth, "hmd5"); -- if (hmd5 == NULL) -+ if (!isccc_sexpr_binaryp(hmd5)) - return (ISC_R_FAILURE); - /* - * Compute digest. -@@ -543,7 +543,7 @@ isccc_cc_createack(isccc_sexpr_t *message, isc_boolean_t ok, - REQUIRE(ackp != NULL && *ackp == NULL); - - _ctrl = isccc_alist_lookup(message, "_ctrl"); -- if (_ctrl == NULL || -+ if (!isccc_alist_alistp(_ctrl) || - isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS || - isccc_cc_lookupuint32(_ctrl, "_tim", &t) != ISC_R_SUCCESS) - return (ISC_R_FAILURE); -@@ -588,7 +588,7 @@ isccc_cc_isack(isccc_sexpr_t *message) - isccc_sexpr_t *_ctrl; - - _ctrl = isccc_alist_lookup(message, "_ctrl"); -- if (_ctrl == NULL) -+ if (!isccc_alist_alistp(_ctrl)) - return (ISC_FALSE); - if (isccc_cc_lookupstring(_ctrl, "_ack", NULL) == ISC_R_SUCCESS) - return (ISC_TRUE); -@@ -601,7 +601,7 @@ isccc_cc_isreply(isccc_sexpr_t *message) - isccc_sexpr_t *_ctrl; - - _ctrl = isccc_alist_lookup(message, "_ctrl"); -- if (_ctrl == NULL) -+ if (!isccc_alist_alistp(_ctrl)) - return (ISC_FALSE); - if (isccc_cc_lookupstring(_ctrl, "_rpl", NULL) == ISC_R_SUCCESS) - return (ISC_TRUE); -@@ -621,7 +621,7 @@ isccc_cc_createresponse(isccc_sexpr_t *message, isccc_time_t now, - - _ctrl = isccc_alist_lookup(message, "_ctrl"); - _data = isccc_alist_lookup(message, "_data"); -- if (_ctrl == NULL || _data == NULL || -+ if (!isccc_alist_alistp(_ctrl) || !isccc_alist_alistp(_data) || - isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS || - isccc_cc_lookupstring(_data, "type", &type) != ISC_R_SUCCESS) - return (ISC_R_FAILURE); -@@ -810,7 +810,7 @@ isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message, - isccc_sexpr_t *_ctrl; - - _ctrl = isccc_alist_lookup(message, "_ctrl"); -- if (_ctrl == NULL || -+ if (!isccc_alist_alistp(_ctrl) || - isccc_cc_lookupstring(_ctrl, "_ser", &_ser) != ISC_R_SUCCESS || - isccc_cc_lookupstring(_ctrl, "_tim", &_tim) != ISC_R_SUCCESS) - return (ISC_R_FAILURE); diff --git a/SOURCES/bind99-CVE-2016-2775.patch b/SOURCES/bind99-CVE-2016-2775.patch deleted file mode 100644 index bc5ac47..0000000 --- a/SOURCES/bind99-CVE-2016-2775.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 062b04898be720ed0855efc192847fcbc667b3e1 Mon Sep 17 00:00:00 2001 -From: Mark Andrews -Date: Thu, 7 Jul 2016 12:52:47 +1000 -Subject: [PATCH] 4406. [bug] getrrsetbyname with a non absolute - name could trigger a infinite recursion bug in lwresd - and named with lwres configured if when combined - with a search list entry the resulting name is - too long. [RT #42694] - -(cherry picked from commit 38cc2d14e218e536e0102fa70deef99461354232) ---- - bin/named/lwdgrbn.c | 16 ++++++++++------ - bin/tests/system/lwresd/lwtest.c | 8 ++++++++ - 2 files changed, 18 insertions(+), 6 deletions(-) - -diff --git a/bin/named/lwdgrbn.c b/bin/named/lwdgrbn.c -index 584ab25..37211eb 100644 ---- a/bin/named/lwdgrbn.c -+++ b/bin/named/lwdgrbn.c -@@ -403,14 +403,18 @@ start_lookup(ns_lwdclient_t *client) { - INSIST(client->lookup == NULL); - - dns_fixedname_init(&absname); -- result = ns_lwsearchctx_current(&client->searchctx, -- dns_fixedname_name(&absname)); -+ - /* -- * This will return failure if relative name + suffix is too long. -- * In this case, just go on to the next entry in the search path. -+ * Perform search across all search domains until success -+ * is returned. Return in case of failure. - */ -- if (result != ISC_R_SUCCESS) -- start_lookup(client); -+ while (ns_lwsearchctx_current(&client->searchctx, -+ dns_fixedname_name(&absname)) != ISC_R_SUCCESS) { -+ if (ns_lwsearchctx_next(&client->searchctx) != ISC_R_SUCCESS) { -+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE); -+ return; -+ } -+ } - - result = dns_lookup_create(cm->mctx, - dns_fixedname_name(&absname), -diff --git a/bin/tests/system/lwresd/lwtest.c b/bin/tests/system/lwresd/lwtest.c -index 02647cb..c2be95d 100644 ---- a/bin/tests/system/lwresd/lwtest.c -+++ b/bin/tests/system/lwresd/lwtest.c -@@ -768,6 +768,14 @@ main(void) { - test_getrrsetbyname("e.example1.", 1, 46, 2, 0, 1); - test_getrrsetbyname("", 1, 1, 0, 0, 0); - -+ test_getrrsetbyname("123456789.123456789.123456789.123456789." -+ "123456789.123456789.123456789.123456789." -+ "123456789.123456789.123456789.123456789." -+ "123456789.123456789.123456789.123456789." -+ "123456789.123456789.123456789.123456789." -+ "123456789.123456789.123456789.123456789." -+ "123456789", 1, 1, 0, 0, 0); -+ - if (fails == 0) - printf("I:ok\n"); - return (fails); --- -2.7.4 - diff --git a/SOURCES/bind99-CVE-2016-2776.patch b/SOURCES/bind99-CVE-2016-2776.patch deleted file mode 100644 index 6a02094..0000000 --- a/SOURCES/bind99-CVE-2016-2776.patch +++ /dev/null @@ -1,89 +0,0 @@ -diff --git a/lib/dns/message.c b/lib/dns/message.c -index 73def73..3d2de4f 100644 ---- a/lib/dns/message.c -+++ b/lib/dns/message.c -@@ -1736,7 +1736,7 @@ dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, - if (r.length < DNS_MESSAGE_HEADERLEN) - return (ISC_R_NOSPACE); - -- if (r.length < msg->reserved) -+ if (r.length - DNS_MESSAGE_HEADERLEN < msg->reserved) - return (ISC_R_NOSPACE); - - /* -@@ -1863,8 +1863,29 @@ norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options) - - return (ISC_TRUE); - } -- - #endif -+ -+static isc_result_t -+renderset(dns_rdataset_t *rdataset, dns_name_t *owner_name, -+ dns_compress_t *cctx, isc_buffer_t *target, -+ unsigned int reserved, unsigned int options, unsigned int *countp) -+{ -+ isc_result_t result; -+ -+ /* -+ * Shrink the space in the buffer by the reserved amount. -+ */ -+ if (target->length - target->used < reserved) -+ return (ISC_R_NOSPACE); -+ -+ target->length -= reserved; -+ result = dns_rdataset_towire(rdataset, owner_name, -+ cctx, target, options, countp); -+ target->length += reserved; -+ -+ return (result); -+} -+ - isc_result_t - dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, - unsigned int options) -@@ -1907,6 +1928,8 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, - /* - * Shrink the space in the buffer by the reserved amount. - */ -+ if (msg->buffer->length - msg->buffer->used < msg->reserved) -+ return (ISC_R_NOSPACE); - msg->buffer->length -= msg->reserved; - - total = 0; -@@ -2183,9 +2206,8 @@ dns_message_renderend(dns_message_t *msg) { - * Render. - */ - count = 0; -- result = dns_rdataset_towire(msg->opt, dns_rootname, -- msg->cctx, msg->buffer, 0, -- &count); -+ result = renderset(msg->opt, dns_rootname, msg->cctx, -+ msg->buffer, msg->reserved, 0, &count); - msg->counts[DNS_SECTION_ADDITIONAL] += count; - if (result != ISC_R_SUCCESS) - return (result); -@@ -2201,9 +2223,8 @@ dns_message_renderend(dns_message_t *msg) { - if (result != ISC_R_SUCCESS) - return (result); - count = 0; -- result = dns_rdataset_towire(msg->tsig, msg->tsigname, -- msg->cctx, msg->buffer, 0, -- &count); -+ result = renderset(msg->tsig, msg->tsigname, msg->cctx, -+ msg->buffer, msg->reserved, 0, &count); - msg->counts[DNS_SECTION_ADDITIONAL] += count; - if (result != ISC_R_SUCCESS) - return (result); -@@ -2224,9 +2245,8 @@ dns_message_renderend(dns_message_t *msg) { - * the owner name of a SIG(0) is irrelevant, and will not - * be set in a message being rendered. - */ -- result = dns_rdataset_towire(msg->sig0, dns_rootname, -- msg->cctx, msg->buffer, 0, -- &count); -+ result = renderset(msg->sig0, dns_rootname, msg->cctx, -+ msg->buffer, msg->reserved, 0, &count); - msg->counts[DNS_SECTION_ADDITIONAL] += count; - if (result != ISC_R_SUCCESS) - return (result); diff --git a/SOURCES/bind99-CVE-2016-8864.patch b/SOURCES/bind99-CVE-2016-8864.patch deleted file mode 100644 index 5e54f08..0000000 --- a/SOURCES/bind99-CVE-2016-8864.patch +++ /dev/null @@ -1,174 +0,0 @@ -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 5ef2dd6..1b987dd 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -526,7 +526,9 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name, - valarg->addrinfo = addrinfo; - - if (!ISC_LIST_EMPTY(fctx->validators)) -- INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0); -+ valoptions |= DNS_VALIDATOR_DEFER; -+ else -+ valoptions &= ~DNS_VALIDATOR_DEFER; - - result = dns_validator_create(fctx->res->view, name, type, rdataset, - sigrdataset, fctx->rmessage, -@@ -4872,13 +4874,6 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, - rdataset, - sigrdataset, - valoptions, task); -- /* -- * Defer any further validations. -- * This prevents multiple validators -- * from manipulating fctx->rmessage -- * simultaneously. -- */ -- valoptions |= DNS_VALIDATOR_DEFER; - } - } else if (CHAINING(rdataset)) { - if (rdataset->type == dns_rdatatype_cname) -@@ -4984,6 +4979,11 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, - eresult == DNS_R_NCACHENXRRSET); - } - event->result = eresult; -+ if (adbp != NULL && *adbp != NULL) { -+ if (anodep != NULL && *anodep != NULL) -+ dns_db_detachnode(*adbp, anodep); -+ dns_db_detach(adbp); -+ } - dns_db_attach(fctx->cache, adbp); - dns_db_transfernode(fctx->cache, &node, anodep); - clone_results(fctx); -@@ -5231,6 +5231,11 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, - fctx->attributes |= FCTX_ATTR_HAVEANSWER; - if (event != NULL) { - event->result = eresult; -+ if (adbp != NULL && *adbp != NULL) { -+ if (anodep != NULL && *anodep != NULL) -+ dns_db_detachnode(*adbp, anodep); -+ dns_db_detach(adbp); -+ } - dns_db_attach(fctx->cache, adbp); - dns_db_transfernode(fctx->cache, &node, anodep); - clone_results(fctx); -@@ -6039,13 +6044,15 @@ static isc_result_t - answer_response(fetchctx_t *fctx) { - isc_result_t result; - dns_message_t *message; -- dns_name_t *name, *dname = NULL, *qname, tname, *ns_name; -+ dns_name_t *name, *dname = NULL, *qname, *dqname, tname, *ns_name; -+ dns_name_t *cname = NULL; - dns_rdataset_t *rdataset, *ns_rdataset; - isc_boolean_t done, external, chaining, aa, found, want_chaining; -- isc_boolean_t have_answer, found_cname, found_type, wanted_chaining; -+ isc_boolean_t have_answer, found_cname, found_dname, found_type; -+ isc_boolean_t wanted_chaining; - unsigned int aflag; - dns_rdatatype_t type; -- dns_fixedname_t fdname, fqname; -+ dns_fixedname_t fdname, fqname, fqdname; - dns_view_t *view; - - FCTXTRACE("answer_response"); -@@ -6059,6 +6066,7 @@ answer_response(fetchctx_t *fctx) { - - done = ISC_FALSE; - found_cname = ISC_FALSE; -+ found_dname = ISC_FALSE; - found_type = ISC_FALSE; - chaining = ISC_FALSE; - have_answer = ISC_FALSE; -@@ -6068,12 +6076,13 @@ answer_response(fetchctx_t *fctx) { - aa = ISC_TRUE; - else - aa = ISC_FALSE; -- qname = &fctx->name; -+ dqname = qname = &fctx->name; - type = fctx->type; - view = fctx->res->view; -+ dns_fixedname_init(&fqdname); - result = dns_message_firstname(message, DNS_SECTION_ANSWER); - while (!done && result == ISC_R_SUCCESS) { -- dns_namereln_t namereln; -+ dns_namereln_t namereln, dnamereln; - int order; - unsigned int nlabels; - -@@ -6081,6 +6090,8 @@ answer_response(fetchctx_t *fctx) { - dns_message_currentname(message, DNS_SECTION_ANSWER, &name); - external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); - namereln = dns_name_fullcompare(qname, name, &order, &nlabels); -+ dnamereln = dns_name_fullcompare(dqname, name, &order, -+ &nlabels); - if (namereln == dns_namereln_equal) { - wanted_chaining = ISC_FALSE; - for (rdataset = ISC_LIST_HEAD(name->list); -@@ -6205,9 +6216,16 @@ answer_response(fetchctx_t *fctx) { - * a CNAME or DNAME). - */ - INSIST(!external); -- if (aflag == -- DNS_RDATASETATTR_ANSWER) { -+ if ((rdataset->type != -+ dns_rdatatype_cname) || -+ !found_dname || -+ (aflag == -+ DNS_RDATASETATTR_ANSWER)) -+ { - have_answer = ISC_TRUE; -+ if (rdataset->type == -+ dns_rdatatype_cname) -+ cname = name; - name->attributes |= - DNS_NAMEATTR_ANSWER; - } -@@ -6303,11 +6321,11 @@ answer_response(fetchctx_t *fctx) { - return (DNS_R_FORMERR); - } - -- if (namereln != dns_namereln_subdomain) { -+ if (dnamereln != dns_namereln_subdomain) { - char qbuf[DNS_NAME_FORMATSIZE]; - char obuf[DNS_NAME_FORMATSIZE]; - -- dns_name_format(qname, qbuf, -+ dns_name_format(dqname, qbuf, - sizeof(qbuf)); - dns_name_format(name, obuf, - sizeof(obuf)); -@@ -6322,7 +6340,7 @@ answer_response(fetchctx_t *fctx) { - want_chaining = ISC_TRUE; - POST(want_chaining); - aflag = DNS_RDATASETATTR_ANSWER; -- result = dname_target(rdataset, qname, -+ result = dname_target(rdataset, dqname, - nlabels, &fdname); - if (result == ISC_R_NOSPACE) { - /* -@@ -6339,10 +6357,13 @@ answer_response(fetchctx_t *fctx) { - - dname = dns_fixedname_name(&fdname); - if (!is_answertarget_allowed(view, -- qname, rdataset->type, -- dname, &fctx->domain)) { -+ dqname, rdataset->type, -+ dname, &fctx->domain)) -+ { - return (DNS_R_SERVFAIL); - } -+ dqname = dns_fixedname_name(&fqdname); -+ dns_name_copy(dname, dqname, NULL); - } else { - /* - * We've found a signature that -@@ -6367,6 +6388,10 @@ answer_response(fetchctx_t *fctx) { - INSIST(!external); - if (aflag == DNS_RDATASETATTR_ANSWER) { - have_answer = ISC_TRUE; -+ found_dname = ISC_TRUE; -+ if (cname != NULL) -+ cname->attributes &= -+ ~DNS_NAMEATTR_ANSWER; - name->attributes |= - DNS_NAMEATTR_ANSWER; - } diff --git a/SOURCES/bind99-CVE-2016-9131.patch b/SOURCES/bind99-CVE-2016-9131.patch deleted file mode 100644 index 29e381c..0000000 --- a/SOURCES/bind99-CVE-2016-9131.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 2bc4461..d9de369 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -6533,6 +6533,19 @@ answer_response(fetchctx_t *fctx) { - log_formerr(fctx, "NSEC3 in answer"); - return (DNS_R_FORMERR); - } -+ if (rdataset->type == dns_rdatatype_tkey) { -+ /* -+ * TKEY is not a valid record in a -+ * response to any query we can make. -+ */ -+ log_formerr(fctx, "TKEY in answer"); -+ return (DNS_R_FORMERR); -+ } -+ if (rdataset->rdclass != fctx->res->rdclass) { -+ log_formerr(fctx, "Mismatched class " -+ "in answer"); -+ return (DNS_R_FORMERR); -+ } - - /* - * Apply filters, if given, on answers to reject -@@ -6719,6 +6732,12 @@ answer_response(fetchctx_t *fctx) { - rdataset != NULL; - rdataset = ISC_LIST_NEXT(rdataset, link)) - { -+ if (rdataset->rdclass != fctx->res->rdclass) { -+ log_formerr(fctx, "Mismatched class " -+ "in answer"); -+ return (DNS_R_FORMERR); -+ } -+ - /* - * Only pass DNAME or RRSIG(DNAME). - */ diff --git a/SOURCES/bind99-CVE-2016-9147.patch b/SOURCES/bind99-CVE-2016-9147.patch deleted file mode 100644 index 221ff94..0000000 --- a/SOURCES/bind99-CVE-2016-9147.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 9ad5f81..ffdde5e 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -6229,15 +6229,19 @@ answer_response(fetchctx_t *fctx) { - * a CNAME or DNAME). - */ - INSIST(!external); -- if ((rdataset->type != -- dns_rdatatype_cname) || -- !found_dname || -- (aflag == -- DNS_RDATASETATTR_ANSWER)) -+ /* -+ * Don't use found_cname here -+ * as we have just set it -+ * above. -+ */ -+ if (cname == NULL && -+ !found_dname && -+ aflag == -+ DNS_RDATASETATTR_ANSWER) - { - have_answer = ISC_TRUE; -- if (rdataset->type == -- dns_rdatatype_cname) -+ if (found_cname && -+ cname == NULL) - cname = name; - name->attributes |= - DNS_NAMEATTR_ANSWER; diff --git a/SOURCES/bind99-CVE-2016-9444.patch b/SOURCES/bind99-CVE-2016-9444.patch deleted file mode 100644 index 17ee09f..0000000 --- a/SOURCES/bind99-CVE-2016-9444.patch +++ /dev/null @@ -1,147 +0,0 @@ -diff --git a/lib/dns/message.c b/lib/dns/message.c -index 869d258..c1f9498 100644 ---- a/lib/dns/message.c -+++ b/lib/dns/message.c -@@ -1150,6 +1150,63 @@ update(dns_section_t section, dns_rdataclass_t rdclass) { - return (ISC_FALSE); - } - -+/* -+ * Check to confirm that all DNSSEC records (DS, NSEC, NSEC3) have -+ * covering RRSIGs. -+ */ -+static isc_boolean_t -+auth_signed(dns_namelist_t *section) { -+ dns_name_t *name; -+ -+ for (name = ISC_LIST_HEAD(*section); -+ name != NULL; -+ name = ISC_LIST_NEXT(name, link)) -+ { -+ int auth_dnssec = 0, auth_rrsig = 0; -+ dns_rdataset_t *rds; -+ -+ for (rds = ISC_LIST_HEAD(name->list); -+ rds != NULL; -+ rds = ISC_LIST_NEXT(rds, link)) -+ { -+ switch (rds->type) { -+ case dns_rdatatype_ds: -+ auth_dnssec |= 0x1; -+ break; -+ case dns_rdatatype_nsec: -+ auth_dnssec |= 0x2; -+ break; -+ case dns_rdatatype_nsec3: -+ auth_dnssec |= 0x4; -+ break; -+ case dns_rdatatype_rrsig: -+ break; -+ default: -+ continue; -+ } -+ -+ switch (rds->covers) { -+ case dns_rdatatype_ds: -+ auth_rrsig |= 0x1; -+ break; -+ case dns_rdatatype_nsec: -+ auth_rrsig |= 0x2; -+ break; -+ case dns_rdatatype_nsec3: -+ auth_rrsig |= 0x4; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ if (auth_dnssec != auth_rrsig) -+ return (ISC_FALSE); -+ } -+ -+ return (ISC_TRUE); -+} -+ - static isc_result_t - getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - dns_section_t sectionid, unsigned int options) -@@ -1175,12 +1232,12 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); - seen_problem = ISC_FALSE; - -+ section = &msg->sections[sectionid]; -+ - for (count = 0; count < msg->counts[sectionid]; count++) { - int recstart = source->current; - isc_boolean_t skip_name_search, skip_type_search; - -- section = &msg->sections[sectionid]; -- - skip_name_search = ISC_FALSE; - skip_type_search = ISC_FALSE; - free_rdataset = ISC_FALSE; -@@ -1354,7 +1411,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - goto cleanup; - rdata->rdclass = rdclass; - issigzero = ISC_FALSE; -- if (rdtype == dns_rdatatype_rrsig && -+ if (rdtype == dns_rdatatype_rrsig && - rdata->flags == 0) { - covers = dns_rdata_covers(rdata); - if (covers == 0) -@@ -1565,6 +1622,19 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - INSIST(free_rdataset == ISC_FALSE); - } - -+ /* -+ * If any of DS, NSEC or NSEC3 appeared in the -+ * authority section of a query response without -+ * a covering RRSIG, FORMERR -+ */ -+ if (sectionid == DNS_SECTION_AUTHORITY && -+ msg->opcode == dns_opcode_query && -+ ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) && -+ ((msg->flags & DNS_MESSAGEFLAG_TC) == 0) && -+ !preserve_order && -+ !auth_signed(section)) -+ DO_FORMERR; -+ - if (seen_problem) - return (DNS_R_RECOVERABLE); - return (ISC_R_SUCCESS); -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 2bc4461..e5600a3 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -5194,13 +5194,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, - rdataset->type, - &noqname); - if (tresult == ISC_R_SUCCESS && -- noqname != NULL) { -- tresult = -- dns_rdataset_addnoqname( -+ noqname != NULL) -+ (void) dns_rdataset_addnoqname( - rdataset, noqname); -- RUNTIME_CHECK(tresult == -- ISC_R_SUCCESS); -- } - } - addedrdataset = ardataset; - result = dns_db_addrdataset(fctx->cache, node, -@@ -5330,11 +5326,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, - tresult = findnoqname(fctx, name, - rdataset->type, &noqname); - if (tresult == ISC_R_SUCCESS && -- noqname != NULL) { -- tresult = dns_rdataset_addnoqname( -- rdataset, noqname); -- RUNTIME_CHECK(tresult == ISC_R_SUCCESS); -- } -+ noqname != NULL) -+ (void) dns_rdataset_addnoqname( -+ rdataset, noqname); - } - - /* diff --git a/SOURCES/bind99-CVE-2017-3135.patch b/SOURCES/bind99-CVE-2017-3135.patch deleted file mode 100644 index 2c43c67..0000000 --- a/SOURCES/bind99-CVE-2017-3135.patch +++ /dev/null @@ -1,193 +0,0 @@ -From f05af77f32742b8e601d766e1f2fe6a480c7e735 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Wed, 8 Feb 2017 12:23:20 +0100 -Subject: [PATCH] 4557. [security] Combining dns64 and rpz can result in - dereferencing a NULL pointer (read). (CVE-2017-3135) - [RT#44434] - ---- - bin/named/query.c | 59 +++++++++++++++++++++++++----------------------------- - lib/dns/message.c | 6 +++--- - lib/dns/rdataset.c | 1 + - 3 files changed, 31 insertions(+), 35 deletions(-) - -diff --git a/bin/named/query.c b/bin/named/query.c -index 1975dfc..f60078b 100644 ---- a/bin/named/query.c -+++ b/bin/named/query.c -@@ -5591,9 +5591,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - dns_rpz_st_t *rpz_st; - isc_boolean_t resuming; - int line = -1; -- isc_boolean_t dns64_exclude, dns64; -+ isc_boolean_t dns64_exclude, dns64, rpz; - dns_clientinfomethods_t cm; - dns_clientinfo_t ci; -+ dns_name_t *rpzqname; - - CTRACE("query_find"); - -@@ -5619,7 +5620,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - zone = NULL; - need_wildcardproof = ISC_FALSE; - empty_wild = ISC_FALSE; -- dns64_exclude = dns64 = ISC_FALSE; -+ dns64_exclude = dns64 = rpz = ISC_FALSE; - options = 0; - resuming = ISC_FALSE; - is_zone = ISC_FALSE; -@@ -5736,6 +5737,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - authoritative = ISC_FALSE; - version = NULL; - need_wildcardproof = ISC_FALSE; -+ rpz = ISC_FALSE; - - if (client->view->checknames && - !dns_rdata_checkowner(client->query.qname, -@@ -5860,11 +5862,29 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - } - - /* -- * Now look for an answer in the database. -+ * Now look for an answer in the database. If this is a dns64 -+ * AAAA lookup on a rpz database adjust the qname. - */ -- result = dns_db_findext(db, client->query.qname, version, type, -+ if (dns64 && rpz) -+ rpzqname = client->query.rpz_st->qname; -+ else -+ rpzqname = client->query.qname; -+ -+ result = dns_db_findext(db, rpzqname, version, type, - client->query.dboptions, client->now, - &node, fname, &cm, &ci, rdataset, sigrdataset); -+ /* -+ * Fixup fname and sigrdataset. -+ */ -+ if (dns64 && rpz) { -+ isc_result_t rresult; -+ -+ rresult = dns_name_copy(client->query.qname, fname, NULL); -+ RUNTIME_CHECK(rresult == ISC_R_SUCCESS); -+ if (sigrdataset != NULL && -+ dns_rdataset_isassociated(sigrdataset)) -+ dns_rdataset_disassociate(sigrdataset); -+ } - - resume: - CTRACE("query_find: resume"); -@@ -6067,9 +6087,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - switch (rpz_st->m.policy) { - case DNS_RPZ_POLICY_NXDOMAIN: - result = DNS_R_NXDOMAIN; -+ rpz = ISC_TRUE; - break; - case DNS_RPZ_POLICY_NODATA: - result = DNS_R_NXRRSET; -+ rpz = ISC_TRUE; - break; - case DNS_RPZ_POLICY_RECORD: - result = rpz_st->m.result; -@@ -6089,6 +6111,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - rdataset->ttl = ISC_MIN(rdataset->ttl, - rpz_st->m.ttl); - } -+ rpz = ISC_TRUE; - break; - case DNS_RPZ_POLICY_WILDCNAME: - result = dns_rdataset_first(rdataset); -@@ -6130,7 +6153,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC | - DNS_MESSAGEFLAG_AD); - query_putrdataset(client, &sigrdataset); -- rpz_st->q.is_zone = is_zone; - is_zone = ISC_TRUE; - rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy, - rpz_st->m.type, zone, rpz_st->qname); -@@ -6509,15 +6531,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - rdataset = NULL; - sigrdataset = NULL; - type = qtype = dns_rdatatype_a; -- rpz_st = client->query.rpz_st; -- if (rpz_st != NULL) { -- /* -- * Arrange for RPZ rewriting of any A records. -- */ -- if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) -- is_zone = rpz_st->q.is_zone; -- rpz_st_clear(client); -- } - dns64 = ISC_TRUE; - goto db_find; - } -@@ -6786,15 +6799,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - sigrdataset = NULL; - fname = NULL; - type = qtype = dns_rdatatype_a; -- rpz_st = client->query.rpz_st; -- if (rpz_st != NULL) { -- /* -- * Arrange for RPZ rewriting of any A records. -- */ -- if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) -- is_zone = rpz_st->q.is_zone; -- rpz_st_clear(client); -- } - dns64 = ISC_TRUE; - goto db_find; - } -@@ -7296,15 +7300,6 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - rdataset = NULL; - sigrdataset = NULL; - type = qtype = dns_rdatatype_a; -- rpz_st = client->query.rpz_st; -- if (rpz_st != NULL) { -- /* -- * Arrange for RPZ rewriting of any A records. -- */ -- if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) -- is_zone = rpz_st->q.is_zone; -- rpz_st_clear(client); -- } - dns64_exclude = dns64 = ISC_TRUE; - goto db_find; - } -diff --git a/lib/dns/message.c b/lib/dns/message.c -index 884107e..1417067 100644 ---- a/lib/dns/message.c -+++ b/lib/dns/message.c -@@ -1234,8 +1234,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - { - isc_region_t r; - unsigned int count, rdatalen; -- dns_name_t *name; -- dns_name_t *name2; -+ dns_name_t *name = NULL; -+ dns_name_t *name2 = NULL; - dns_offsets_t *offsets; - dns_rdataset_t *rdataset; - dns_rdatalist_t *rdatalist; -@@ -1245,7 +1245,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, - dns_rdata_t *rdata; - dns_ttl_t ttl; - dns_namelist_t *section; -- isc_boolean_t free_name, free_rdataset; -+ isc_boolean_t free_name = ISC_FALSE, free_rdataset = ISC_FALSE; - isc_boolean_t preserve_order, best_effort, seen_problem; - isc_boolean_t issigzero; - -diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c -index 026d771..483ddfb 100644 ---- a/lib/dns/rdataset.c -+++ b/lib/dns/rdataset.c -@@ -336,6 +336,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, - */ - - REQUIRE(DNS_RDATASET_VALID(rdataset)); -+ REQUIRE(rdataset->methods != NULL); - REQUIRE(countp != NULL); - REQUIRE((order == NULL) == (order_arg == NULL)); - REQUIRE(cctx != NULL && cctx->mctx != NULL); --- -2.9.3 - diff --git a/SOURCES/bind99-CVE-2017-3136.patch b/SOURCES/bind99-CVE-2017-3136.patch deleted file mode 100644 index f83f93e..0000000 --- a/SOURCES/bind99-CVE-2017-3136.patch +++ /dev/null @@ -1,26 +0,0 @@ -From d4d151cf34fab415e2823deada3433df7f475c71 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= -Date: Tue, 11 Apr 2017 16:19:08 +0200 -Subject: [PATCH 1/3] 4575. [security] DNS64 with "break-dnssec yes;" - can result in an assertion failure. (CVE-2017-3136) - [RT #44653] - ---- - bin/named/query.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/bin/named/query.c b/bin/named/query.c -index f60078b..6e988f5 100644 ---- a/bin/named/query.c -+++ b/bin/named/query.c -@@ -7324,6 +7324,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) - result = query_dns64(client, &fname, rdataset, - sigrdataset, dbuf, - DNS_SECTION_ANSWER); -+ noqname = NULL; - dns_rdataset_disassociate(rdataset); - dns_message_puttemprdataset(client->message, &rdataset); - if (result == ISC_R_NOMORE) { --- -2.9.3 - diff --git a/SOURCES/bind99-CVE-2017-3137.patch b/SOURCES/bind99-CVE-2017-3137.patch deleted file mode 100644 index a0d97e5..0000000 --- a/SOURCES/bind99-CVE-2017-3137.patch +++ /dev/null @@ -1,1126 +0,0 @@ -From 93aec4d3d80a0d1cdb6553f70f35a2e2cb1fbaa8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= -Date: Tue, 11 Apr 2017 16:19:51 +0200 -Subject: [PATCH 2/3] 4578. [security] Some chaining (CNAME or DNAME) - responses to upstream queries could trigger assertion - failures. (CVE-2017-3137) [RT #44734] - -(including part of commit fea8a9d) ---- - bin/tests/system/dname/ans3/ans.pl | 16 +- - bin/tests/system/dname/ns1/root.db | 2 +- - bin/tests/system/dname/ns2/example.db | 3 +- - bin/tests/system/dname/tests.sh | 17 +- - lib/dns/name.c | 2 - - lib/dns/resolver.c | 850 +++++++++++++--------------------- - 6 files changed, 349 insertions(+), 541 deletions(-) - -diff --git a/bin/tests/system/dname/ans3/ans.pl b/bin/tests/system/dname/ans3/ans.pl -index 271fc7d..af338fe 100644 ---- a/bin/tests/system/dname/ans3/ans.pl -+++ b/bin/tests/system/dname/ans3/ans.pl -@@ -1,10 +1,18 @@ - #!/usr/bin/env perl - # --# Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC") -+# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") - # --# This Source Code Form is subject to the terms of the Mozilla Public --# License, v. 2.0. If a copy of the MPL was not distributed with this --# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. - - use strict; - use warnings; -diff --git a/bin/tests/system/dname/ns1/root.db b/bin/tests/system/dname/ns1/root.db -index 2e84ae0..3d55ace 100644 ---- a/bin/tests/system/dname/ns1/root.db -+++ b/bin/tests/system/dname/ns1/root.db -@@ -1,4 +1,4 @@ --; Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") -+; Copyright (C) 2011, 2017 Internet Systems Consortium, Inc. ("ISC") - ; - ; Permission to use, copy, modify, and/or distribute this software for any - ; purpose with or without fee is hereby granted, provided that the above -diff --git a/bin/tests/system/dname/ns2/example.db b/bin/tests/system/dname/ns2/example.db -index 4289134..c0193de 100644 ---- a/bin/tests/system/dname/ns2/example.db -+++ b/bin/tests/system/dname/ns2/example.db -@@ -1,4 +1,4 @@ --; Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") -+; Copyright (C) 2011, 2017 Internet Systems Consortium, Inc. ("ISC") - ; - ; Permission to use, copy, modify, and/or distribute this software for any - ; purpose with or without fee is hereby granted, provided that the above -@@ -29,6 +29,7 @@ a.short A 10.0.0.1 - short-dname DNAME short - a.longlonglonglonglonglonglonglonglonglonglonglonglong A 10.0.0.2 - long-dname DNAME longlonglonglonglonglonglonglonglonglonglonglonglong -+toolong-dname DNAME longlonglonglonglonglonglonglonglonglonglonglonglong - cname CNAME a.cnamedname - cnamedname DNAME target - a.target A 10.0.0.3 -diff --git a/bin/tests/system/dname/tests.sh b/bin/tests/system/dname/tests.sh -index 6dc9e88..1487bd9 100644 ---- a/bin/tests/system/dname/tests.sh -+++ b/bin/tests/system/dname/tests.sh -@@ -1,6 +1,6 @@ - #!/bin/sh - # --# Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") -+# Copyright (C) 2011, 2012, 2017 Internet Systems Consortium, Inc. ("ISC") - # - # Permission to use, copy, modify, and/or distribute this software for any - # purpose with or without fee is hereby granted, provided that the above -@@ -57,10 +57,19 @@ grep "status: YXDOMAIN" dig.out.ns2.toolong > /dev/null || ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` - --echo "I:checking (too) long dname from recursive" -+echo "I:checking (too) long dname from recursive with cached DNAME" - ret=0 --$DIG 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.long-dname.example @10.53.0.4 a -p 5300 > dig.out.ns4.toolong || ret=1 --grep "status: YXDOMAIN" dig.out.ns4.toolong > /dev/null || ret=1 -+$DIG 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.long-dname.example @10.53.0.4 a -p 5300 > dig.out.ns4.cachedtoolong || ret=1 -+grep "status: YXDOMAIN" dig.out.ns4.cachedtoolong > /dev/null || ret=1 -+grep '^long-dname\.example\..*DNAME.*long' dig.out.ns4.cachedtoolong > /dev/null || ret=1 -+if [ $ret != 0 ]; then echo "I:failed"; fi -+status=`expr $status + $ret` -+ -+echo "I:checking (too) long dname from recursive without cached DNAME" -+ret=0 -+$DIG 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglong.toolong-dname.example @10.53.0.4 a -p 5300 > dig.out.ns4.uncachedtoolong || ret=1 -+grep "status: YXDOMAIN" dig.out.ns4.uncachedtoolong > /dev/null || ret=1 -+grep '^toolong-dname\.example\..*DNAME.*long' dig.out.ns4.uncachedtoolong > /dev/null || ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` - -diff --git a/lib/dns/name.c b/lib/dns/name.c -index 93173ee..d02e713 100644 ---- a/lib/dns/name.c -+++ b/lib/dns/name.c -@@ -2119,11 +2119,9 @@ dns_name_split(dns_name_t *name, unsigned int suffixlabels, - REQUIRE(prefix != NULL || suffix != NULL); - REQUIRE(prefix == NULL || - (VALID_NAME(prefix) && -- prefix->buffer != NULL && - BINDABLE(prefix))); - REQUIRE(suffix == NULL || - (VALID_NAME(suffix) && -- suffix->buffer != NULL && - BINDABLE(suffix))); - - splitlabel = name->labels - suffixlabels; -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index c3607fa..860a792 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -3817,6 +3817,7 @@ is_lame(fetchctx_t *fctx) { - isc_result_t result; - - if (message->rcode != dns_rcode_noerror && -+ message->rcode != dns_rcode_yxdomain && - message->rcode != dns_rcode_nxdomain) - return (ISC_FALSE); - -@@ -5386,79 +5387,6 @@ chase_additional(fetchctx_t *fctx) { - goto again; - } - --static inline isc_result_t --cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) { -- isc_result_t result; -- dns_rdata_t rdata = DNS_RDATA_INIT; -- dns_rdata_cname_t cname; -- -- result = dns_rdataset_first(rdataset); -- if (result != ISC_R_SUCCESS) -- return (result); -- dns_rdataset_current(rdataset, &rdata); -- result = dns_rdata_tostruct(&rdata, &cname, NULL); -- if (result != ISC_R_SUCCESS) -- return (result); -- dns_name_init(tname, NULL); -- dns_name_clone(&cname.cname, tname); -- dns_rdata_freestruct(&cname); -- -- return (ISC_R_SUCCESS); --} -- --/*% -- * Construct the synthesised CNAME from the existing QNAME and -- * the DNAME RR and store it in 'target'. -- */ --static inline isc_result_t --dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, -- unsigned int nlabels, dns_name_t *target) --{ -- isc_result_t result; -- dns_rdata_t rdata = DNS_RDATA_INIT; -- dns_rdata_dname_t dname; -- dns_fixedname_t prefix; -- -- /* -- * Get the target name of the DNAME. -- */ -- result = dns_rdataset_first(rdataset); -- if (result != ISC_R_SUCCESS) -- return (result); -- dns_rdataset_current(rdataset, &rdata); -- result = dns_rdata_tostruct(&rdata, &dname, NULL); -- if (result != ISC_R_SUCCESS) -- return (result); -- -- dns_fixedname_init(&prefix); -- dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL); -- result = dns_name_concatenate(dns_fixedname_name(&prefix), -- &dname.dname, target, NULL); -- dns_rdata_freestruct(&dname); -- return (result); --} -- --/*% -- * Check if it was possible to construct 'qname' from 'lastcname' -- * and 'rdataset'. -- */ --static inline isc_result_t --fromdname(dns_rdataset_t *rdataset, dns_name_t *lastcname, -- unsigned int nlabels, const dns_name_t *qname) --{ -- dns_fixedname_t fixed; -- isc_result_t result; -- dns_name_t *target; -- -- dns_fixedname_init(&fixed); -- target = dns_fixedname_name(&fixed); -- result = dname_target(rdataset, lastcname, nlabels, target); -- if (result != ISC_R_SUCCESS || !dns_name_equal(qname, target)) -- return (ISC_R_NOTFOUND); -- -- return (ISC_R_SUCCESS); --} -- - static isc_boolean_t - is_answeraddress_allowed(dns_view_t *view, dns_name_t *name, - dns_rdataset_t *rdataset) -@@ -5534,9 +5462,8 @@ is_answeraddress_allowed(dns_view_t *view, dns_name_t *name, - } - - static isc_boolean_t --is_answertarget_allowed(dns_view_t *view, dns_name_t *name, -- dns_rdatatype_t type, dns_name_t *tname, -- dns_name_t *domain) -+is_answertarget_allowed(fetchctx_t *fctx, dns_name_t *qname, dns_name_t *rname, -+ dns_rdataset_t *rdataset, isc_boolean_t *chainingp) - { - isc_result_t result; - dns_rbtnode_t *node = NULL; -@@ -5544,8 +5471,57 @@ is_answertarget_allowed(dns_view_t *view, dns_name_t *name, - char tnamebuf[DNS_NAME_FORMATSIZE]; - char classbuf[64]; - char typebuf[64]; -+ dns_name_t *tname = NULL; -+ dns_rdata_cname_t cname; -+ dns_rdata_dname_t dname; -+ dns_view_t *view = fctx->res->view; -+ dns_rdata_t rdata = DNS_RDATA_INIT; -+ unsigned int nlabels; -+ dns_fixedname_t fixed; -+ dns_name_t prefix; -+ -+ REQUIRE(rdataset != NULL); -+ REQUIRE(rdataset->type == dns_rdatatype_cname || -+ rdataset->type == dns_rdatatype_dname); -+ -+ /* -+ * By default, we allow any target name. -+ * If newqname != NULL we also need to extract the newqname. -+ */ -+ if (chainingp == NULL && view->denyanswernames == NULL) -+ return (ISC_TRUE); -+ -+ result = dns_rdataset_first(rdataset); -+ RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ dns_rdataset_current(rdataset, &rdata); -+ switch (rdataset->type) { -+ case dns_rdatatype_cname: -+ result = dns_rdata_tostruct(&rdata, &cname, NULL); -+ RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ tname = &cname.cname; -+ break; -+ case dns_rdatatype_dname: -+ result = dns_rdata_tostruct(&rdata, &dname, NULL); -+ RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ dns_name_init(&prefix, NULL); -+ dns_fixedname_init(&fixed); -+ tname = dns_fixedname_name(&fixed); -+ nlabels = dns_name_countlabels(qname) - -+ dns_name_countlabels(rname); -+ dns_name_split(qname, nlabels, &prefix, NULL); -+ result = dns_name_concatenate(&prefix, &dname.dname, tname, -+ NULL); -+ if (result == DNS_R_NAMETOOLONG) -+ return (ISC_TRUE); -+ RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ break; -+ default: -+ INSIST(0); -+ } -+ -+ if (chainingp != NULL) -+ *chainingp = ISC_TRUE; - -- /* By default, we allow any target name. */ - if (view->denyanswernames == NULL) - return (ISC_TRUE); - -@@ -5554,8 +5530,8 @@ is_answertarget_allowed(dns_view_t *view, dns_name_t *name, - * or partially, allow it. - */ - if (view->answernames_exclude != NULL) { -- result = dns_rbt_findnode(view->answernames_exclude, name, NULL, -- &node, NULL, 0, NULL, NULL); -+ result = dns_rbt_findnode(view->answernames_exclude, qname, -+ NULL, &node, NULL, 0, NULL, NULL); - if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) - return (ISC_TRUE); - } -@@ -5563,7 +5539,7 @@ is_answertarget_allowed(dns_view_t *view, dns_name_t *name, - /* - * If the target name is a subdomain of the search domain, allow it. - */ -- if (dns_name_issubdomain(tname, domain)) -+ if (dns_name_issubdomain(tname, &fctx->domain)) - return (ISC_TRUE); - - /* -@@ -5572,9 +5548,9 @@ is_answertarget_allowed(dns_view_t *view, dns_name_t *name, - result = dns_rbt_findnode(view->denyanswernames, tname, NULL, &node, - NULL, 0, NULL, NULL); - if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { -- dns_name_format(name, qnamebuf, sizeof(qnamebuf)); -+ dns_name_format(qname, qnamebuf, sizeof(qnamebuf)); - dns_name_format(tname, tnamebuf, sizeof(tnamebuf)); -- dns_rdatatype_format(type, typebuf, sizeof(typebuf)); -+ dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); - dns_rdataclass_format(view->rdclass, classbuf, - sizeof(classbuf)); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, -@@ -6057,473 +6033,301 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, - return (ISC_R_SUCCESS); - } - -+static isc_boolean_t -+validinanswer(dns_rdataset_t *rdataset, fetchctx_t *fctx) { -+ if (rdataset->type == dns_rdatatype_nsec3) { -+ /* -+ * NSEC3 records are not allowed to -+ * appear in the answer section. -+ */ -+ log_formerr(fctx, "NSEC3 in answer"); -+ return (ISC_FALSE); -+ } -+ if (rdataset->type == dns_rdatatype_tkey) { -+ /* -+ * TKEY is not a valid record in a -+ * response to any query we can make. -+ */ -+ log_formerr(fctx, "TKEY in answer"); -+ return (ISC_FALSE); -+ } -+ if (rdataset->rdclass != fctx->res->rdclass) { -+ log_formerr(fctx, "Mismatched class in answer"); -+ return (ISC_FALSE); -+ } -+ return (ISC_TRUE); -+} -+ - static isc_result_t - answer_response(fetchctx_t *fctx) { - isc_result_t result; -- dns_message_t *message; -- dns_name_t *name, *dname = NULL, *qname, tname, *ns_name; -- dns_name_t *cname = NULL, *lastcname = NULL; -- dns_rdataset_t *rdataset, *ns_rdataset; -- isc_boolean_t done, external, aa, found, want_chaining; -- isc_boolean_t have_answer, found_cname, found_dname, found_type; -- isc_boolean_t wanted_chaining; -- unsigned int aflag, chaining; -+ dns_message_t *message = NULL; -+ dns_name_t *name = NULL, *qname = NULL, *ns_name = NULL; -+ dns_name_t *aname = NULL, *cname = NULL, *dname = NULL; -+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; -+ dns_rdataset_t *ardataset = NULL, *crdataset = NULL; -+ dns_rdataset_t *drdataset = NULL, *ns_rdataset = NULL; -+ isc_boolean_t done = ISC_FALSE, aa; -+ unsigned int dname_labels, domain_labels; -+ isc_boolean_t chaining = ISC_FALSE; - dns_rdatatype_t type; -- dns_fixedname_t fdname, fqname; -- dns_view_t *view; -+ dns_view_t *view = NULL; -+ dns_trust_t trust; -+ -+ REQUIRE(VALID_FCTX(fctx)); - - FCTXTRACE("answer_response"); - - message = fctx->rmessage; -+ qname = &fctx->name; -+ view = fctx->res->view; -+ type = fctx->type; - - /* -- * Examine the answer section, marking those rdatasets which are -- * part of the answer and should be cached. -+ * There can be multiple RRSIG and SIG records at a name so -+ * we treat these types as a subset of ANY. - */ -+ if (type == dns_rdatatype_rrsig || type == dns_rdatatype_sig) { -+ type = dns_rdatatype_any; -+ } - -- done = ISC_FALSE; -- found_cname = ISC_FALSE; -- found_dname = ISC_FALSE; -- found_type = ISC_FALSE; -- have_answer = ISC_FALSE; -- want_chaining = ISC_FALSE; -- chaining = 0; -- POST(want_chaining); -- if ((message->flags & DNS_MESSAGEFLAG_AA) != 0) -- aa = ISC_TRUE; -- else -- aa = ISC_FALSE; -- qname = &fctx->name; -- type = fctx->type; -- view = fctx->res->view; -- result = dns_message_firstname(message, DNS_SECTION_ANSWER); -- while (!done && result == ISC_R_SUCCESS) { -- dns_namereln_t namereln, lastreln; -- int order, lastorder; -- unsigned int nlabels, lastnlabels; -+ /* -+ * Bigger than any valid DNAME label count. -+ */ -+ dname_labels = dns_name_countlabels(qname); -+ domain_labels = dns_name_countlabels(&fctx->domain); -+ -+ /* -+ * Perform a single pass looking for the answer, cname or covering -+ * dname. -+ */ -+ for (result = dns_message_firstname(message, DNS_SECTION_ANSWER); -+ result == ISC_R_SUCCESS; -+ result = dns_message_nextname(message, DNS_SECTION_ANSWER)) -+ { -+ int order; -+ unsigned int nlabels; -+ dns_namereln_t namereln; - - name = NULL; - dns_message_currentname(message, DNS_SECTION_ANSWER, &name); -- external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); - namereln = dns_name_fullcompare(qname, name, &order, &nlabels); -- -- if (namereln == dns_namereln_equal) { -- wanted_chaining = ISC_FALSE; -+ switch (namereln) { -+ case dns_namereln_equal: - for (rdataset = ISC_LIST_HEAD(name->list); - rdataset != NULL; -- rdataset = ISC_LIST_NEXT(rdataset, link)) { -- found = ISC_FALSE; -- want_chaining = ISC_FALSE; -- aflag = 0; -- if (rdataset->type == dns_rdatatype_nsec3) { -- /* -- * NSEC3 records are not allowed to -- * appear in the answer section. -- */ -- log_formerr(fctx, "NSEC3 in answer"); -- return (DNS_R_FORMERR); -- } -- if (rdataset->type == dns_rdatatype_tkey) { -- /* -- * TKEY is not a valid record in a -- * response to any query we can make. -- */ -- log_formerr(fctx, "TKEY in answer"); -- return (DNS_R_FORMERR); -- } -- if (rdataset->rdclass != fctx->res->rdclass) { -- log_formerr(fctx, "Mismatched class " -- "in answer"); -- return (DNS_R_FORMERR); -- } -- -- /* -- * Apply filters, if given, on answers to reject -- * a malicious attempt of rebinding. -- */ -- if ((rdataset->type == dns_rdatatype_a || -- rdataset->type == dns_rdatatype_aaaa) && -- !is_answeraddress_allowed(view, name, -- rdataset)) { -- return (DNS_R_SERVFAIL); -- } -- -- if (rdataset->type == type && !found_cname) { -- /* -- * We've found an ordinary answer. -- */ -- found = ISC_TRUE; -- found_type = ISC_TRUE; -- done = ISC_TRUE; -- aflag = DNS_RDATASETATTR_ANSWER; -- } else if (type == dns_rdatatype_any) { -- /* -- * We've found an answer matching -- * an ANY query. There may be -- * more. -- */ -- found = ISC_TRUE; -- aflag = DNS_RDATASETATTR_ANSWER; -- } else if (rdataset->type == dns_rdatatype_rrsig -- && rdataset->covers == type -- && !found_cname) { -- /* -- * We've found a signature that -- * covers the type we're looking for. -- */ -- found = ISC_TRUE; -- found_type = ISC_TRUE; -- aflag = DNS_RDATASETATTR_ANSWERSIG; -- } else if (rdataset->type == -- dns_rdatatype_cname -- && !found_type) { -- /* -- * We're looking for something else, -- * but we found a CNAME. -- * -- * Getting a CNAME response for some -- * query types is an error, see -- * RFC 4035, Section 2.5. -- */ -- if (type == dns_rdatatype_rrsig || -- type == dns_rdatatype_key || -- type == dns_rdatatype_nsec) { -- char buf[DNS_RDATATYPE_FORMATSIZE]; -- dns_rdatatype_format(fctx->type, -- buf, sizeof(buf)); -- log_formerr(fctx, -- "CNAME response " -- "for %s RR", buf); -- return (DNS_R_FORMERR); -- } -- found = ISC_TRUE; -- found_cname = ISC_TRUE; -- want_chaining = ISC_TRUE; -- aflag = DNS_RDATASETATTR_ANSWER; -- result = cname_target(rdataset, -- &tname); -- if (result != ISC_R_SUCCESS) -- return (result); -- /* Apply filters on the target name. */ -- if (!is_answertarget_allowed(view, -- name, -- rdataset->type, -- &tname, -- &fctx->domain)) { -- return (DNS_R_SERVFAIL); -+ rdataset = ISC_LIST_NEXT(rdataset, link)) -+ { -+ if (rdataset->type == type || -+ type == dns_rdatatype_any) -+ { -+ aname = name; -+ if (type != dns_rdatatype_any) { -+ ardataset = rdataset; - } -- lastcname = name; -- } else if (rdataset->type == dns_rdatatype_rrsig -- && rdataset->covers == -- dns_rdatatype_cname -- && !found_type) { -- /* -- * We're looking for something else, -- * but we found a SIG CNAME. -- */ -- found = ISC_TRUE; -- found_cname = ISC_TRUE; -- aflag = DNS_RDATASETATTR_ANSWERSIG; -+ break; - } -- -- if (found) { -- /* -- * We've found an answer to our -- * question. -- */ -- name->attributes |= -- DNS_NAMEATTR_CACHE; -- rdataset->attributes |= -- DNS_RDATASETATTR_CACHE; -- rdataset->trust = dns_trust_answer; -- if (chaining == 0) { -- /* -- * This data is "the" answer -- * to our question only if -- * we're not chaining (i.e. -- * if we haven't followed -- * a CNAME or DNAME). -- */ -- INSIST(!external); -- /* -- * Don't use found_cname here -- * as we have just set it -- * above. -- */ -- if (cname == NULL && -- !found_dname && -- aflag == -- DNS_RDATASETATTR_ANSWER) -- { -- have_answer = ISC_TRUE; -- if (found_cname && -- cname == NULL) -- cname = name; -- name->attributes |= -- DNS_NAMEATTR_ANSWER; -- } -- rdataset->attributes |= aflag; -- if (aa) -- rdataset->trust = -- dns_trust_authanswer; -- } else if (external) { -- /* -- * This data is outside of -- * our query domain, and -- * may not be cached. -- */ -- rdataset->attributes |= -- DNS_RDATASETATTR_EXTERNAL; -- } -- -- /* -- * Mark any additional data related -- * to this rdataset. -- */ -- (void)dns_rdataset_additionaldata( -- rdataset, -- check_related, -- fctx); -- -- /* -- * CNAME chaining. -- */ -- if (want_chaining) { -- wanted_chaining = ISC_TRUE; -- name->attributes |= -- DNS_NAMEATTR_CHAINING; -- rdataset->attributes |= -- DNS_RDATASETATTR_CHAINING; -- qname = &tname; -- } -+ if (rdataset->type == dns_rdatatype_cname) { -+ cname = name; -+ crdataset = rdataset; -+ break; - } -- /* -- * We could add an "else" clause here and -- * log that we're ignoring this rdataset. -- */ - } -+ break; -+ -+ case dns_namereln_subdomain: - /* -- * If wanted_chaining is true, we've done -- * some chaining as the result of processing -- * this node, and thus we need to set -- * chaining to true. -- * -- * We don't set chaining inside of the -- * rdataset loop because doing that would -- * cause us to ignore the signatures of -- * CNAMEs. -+ * In-scope DNAME records must have at least -+ * as many labels as the domain being queried. -+ * They also must be less that qname's labels -+ * and any previously found dname. - */ -- if (wanted_chaining && chaining < 2U) -- chaining++; -- } else { -- dns_rdataset_t *dnameset = NULL; -- isc_boolean_t synthcname = ISC_FALSE; -- -- if (lastcname != NULL) { -- lastreln = dns_name_fullcompare(lastcname, -- name, -- &lastorder, -- &lastnlabels); -- if (lastreln == dns_namereln_subdomain && -- lastnlabels == dns_name_countlabels(name)) -- synthcname = ISC_TRUE; -+ if (nlabels >= dname_labels || nlabels < domain_labels) -+ { -+ continue; - } - - /* -- * Look for a DNAME (or its SIG). Anything else is -- * ignored. -+ * We are looking for the shortest DNAME if there -+ * are multiple ones (which there shouldn't be). - */ -- wanted_chaining = ISC_FALSE; - for (rdataset = ISC_LIST_HEAD(name->list); - rdataset != NULL; - rdataset = ISC_LIST_NEXT(rdataset, link)) - { -- if (rdataset->rdclass != fctx->res->rdclass) { -- log_formerr(fctx, "Mismatched class " -- "in answer"); -- return (DNS_R_FORMERR); -- } -- -- /* -- * Only pass DNAME or RRSIG(DNAME). -- */ -- if (rdataset->type != dns_rdatatype_dname && -- (rdataset->type != dns_rdatatype_rrsig || -- rdataset->covers != dns_rdatatype_dname)) -+ if (rdataset->type != dns_rdatatype_dname) { - continue; -- -- /* -- * If we're not chaining, then the DNAME and -- * its signature should not be external. -- */ -- if (chaining == 0 && external) { -- char qbuf[DNS_NAME_FORMATSIZE]; -- char obuf[DNS_NAME_FORMATSIZE]; -- -- dns_name_format(name, qbuf, -- sizeof(qbuf)); -- dns_name_format(&fctx->domain, obuf, -- sizeof(obuf)); -- log_formerr(fctx, "external DNAME or " -- "RRSIG covering DNAME " -- "in answer: %s is " -- "not in %s", qbuf, obuf); -- return (DNS_R_FORMERR); -- } -- -- /* -- * If DNAME + synthetic CNAME then the -- * namereln is dns_namereln_subdomain. -- */ -- if (namereln != dns_namereln_subdomain && -- !synthcname) -- { -- char qbuf[DNS_NAME_FORMATSIZE]; -- char obuf[DNS_NAME_FORMATSIZE]; -- -- dns_name_format(qname, qbuf, -- sizeof(qbuf)); -- dns_name_format(name, obuf, -- sizeof(obuf)); -- log_formerr(fctx, "unrelated DNAME " -- "in answer: %s is " -- "not in %s", qbuf, obuf); -- return (DNS_R_FORMERR); - } -+ dname = name; -+ drdataset = rdataset; -+ dname_labels = nlabels; -+ break; -+ } -+ break; -+ default: -+ break; -+ } -+ } - -- aflag = 0; -- if (rdataset->type == dns_rdatatype_dname) { -- want_chaining = ISC_TRUE; -- POST(want_chaining); -- aflag = DNS_RDATASETATTR_ANSWER; -- dns_fixedname_init(&fdname); -- dname = dns_fixedname_name(&fdname); -- if (synthcname) { -- result = fromdname(rdataset, -- lastcname, -- lastnlabels, -- qname); -- } else { -- result = dname_target(rdataset, -- qname, -- nlabels, -- dname); -- } -- if (result == ISC_R_NOSPACE) { -- /* -- * We can't construct the -- * DNAME target. Do not -- * try to continue. -- */ -- want_chaining = ISC_FALSE; -- POST(want_chaining); -- } else if (result != ISC_R_SUCCESS) -- return (result); -- else -- dnameset = rdataset; -+ if (dname != NULL) { -+ aname = NULL; -+ ardataset = NULL; -+ cname = NULL; -+ crdataset = NULL; -+ } else if (aname != NULL) { -+ cname = NULL; -+ crdataset = NULL; -+ } - -- if (!synthcname && -- !is_answertarget_allowed(view, -- qname, rdataset->type, -- dname, &fctx->domain)) -- { -- return (DNS_R_SERVFAIL); -- } -- } else { -- /* -- * We've found a signature that -- * covers the DNAME. -- */ -- aflag = DNS_RDATASETATTR_ANSWERSIG; -- } -+ aa = ISC_TF((message->flags & DNS_MESSAGEFLAG_AA) != 0); -+ trust = aa ? dns_trust_authanswer : dns_trust_answer; - -- /* -- * We've found an answer to our -- * question. -- */ -- name->attributes |= DNS_NAMEATTR_CACHE; -- rdataset->attributes |= DNS_RDATASETATTR_CACHE; -- rdataset->trust = dns_trust_answer; -- /* -- * If we are not chaining or the first CNAME -- * is a synthesised CNAME before the DNAME. -- */ -- if ((chaining == 0) || -- (chaining == 1U && synthcname)) -- { -- /* -- * This data is "the" answer to -- * our question only if we're -- * not chaining. -- */ -- INSIST(!external); -- if (aflag == DNS_RDATASETATTR_ANSWER) { -- have_answer = ISC_TRUE; -- found_dname = ISC_TRUE; -- if (cname != NULL && -- synthcname) -- { -- cname->attributes &= -- ~DNS_NAMEATTR_ANSWER; -- } -- name->attributes |= -- DNS_NAMEATTR_ANSWER; -- } -- rdataset->attributes |= aflag; -- if (aa) -- rdataset->trust = -- dns_trust_authanswer; -- } else if (external) { -- rdataset->attributes |= -- DNS_RDATASETATTR_EXTERNAL; -- } -+ if (aname != NULL && type == dns_rdatatype_any) { -+ for (rdataset = ISC_LIST_HEAD(aname->list); -+ rdataset != NULL; -+ rdataset = ISC_LIST_NEXT(rdataset, link)) -+ { -+ if (!validinanswer(rdataset, fctx)) { -+ return (DNS_R_FORMERR); - } -- -- /* -- * DNAME chaining. -- */ -- if (dnameset != NULL) { -- if (!synthcname) { -- /* -- * Copy the dname into the qname fixed -- * name. -- * -- * Although we check for failure of the -- * copy operation, in practice it -- * should never fail since we already -- * know that the result fits in a -- * fixedname. -- */ -- dns_fixedname_init(&fqname); -- qname = dns_fixedname_name(&fqname); -- result = dns_name_copy(dname, qname, -- NULL); -- if (result != ISC_R_SUCCESS) -- return (result); -- } -- wanted_chaining = ISC_TRUE; -- name->attributes |= DNS_NAMEATTR_CHAINING; -- dnameset->attributes |= -- DNS_RDATASETATTR_CHAINING; -+ if ((fctx->type == dns_rdatatype_sig || -+ fctx->type == dns_rdatatype_rrsig) && -+ rdataset->type != fctx->type) -+ { -+ continue; - } -- /* -- * Ensure that we can't ever get chaining == 1 -- * above if we have processed a DNAME. -- */ -- if (wanted_chaining && chaining < 2U) -- chaining += 2; -+ if ((rdataset->type == dns_rdatatype_a || -+ rdataset->type == dns_rdatatype_aaaa) && -+ !is_answeraddress_allowed(view, aname, rdataset)) -+ { -+ return (DNS_R_SERVFAIL); -+ } -+ if ((rdataset->type == dns_rdatatype_cname || -+ rdataset->type == dns_rdatatype_dname) && -+ !is_answertarget_allowed(fctx, qname, aname, -+ rdataset, NULL)) -+ { -+ return (DNS_R_SERVFAIL); -+ } -+ aname->attributes |= DNS_NAMEATTR_CACHE; -+ aname->attributes |= DNS_NAMEATTR_ANSWER; -+ rdataset->attributes |= DNS_RDATASETATTR_ANSWER; -+ rdataset->attributes |= DNS_RDATASETATTR_CACHE; -+ rdataset->trust = trust; -+ (void)dns_rdataset_additionaldata(rdataset, -+ check_related, -+ fctx); - } -- result = dns_message_nextname(message, DNS_SECTION_ANSWER); -- } -- if (result == ISC_R_NOMORE) -- result = ISC_R_SUCCESS; -- if (result != ISC_R_SUCCESS) -- return (result); -- -- /* -- * We should have found an answer. -- */ -- if (!have_answer) { -+ } else if (aname != NULL) { -+ if (!validinanswer(ardataset, fctx)) -+ return (DNS_R_FORMERR); -+ if ((ardataset->type == dns_rdatatype_a || -+ ardataset->type == dns_rdatatype_aaaa) && -+ !is_answeraddress_allowed(view, aname, ardataset)) { -+ return (DNS_R_SERVFAIL); -+ } -+ if ((ardataset->type == dns_rdatatype_cname || -+ ardataset->type == dns_rdatatype_dname) && -+ !is_answertarget_allowed(fctx, qname, aname, ardataset, -+ NULL)) -+ { -+ return (DNS_R_SERVFAIL); -+ } -+ aname->attributes |= DNS_NAMEATTR_CACHE; -+ aname->attributes |= DNS_NAMEATTR_ANSWER; -+ ardataset->attributes |= DNS_RDATASETATTR_ANSWER; -+ ardataset->attributes |= DNS_RDATASETATTR_CACHE; -+ ardataset->trust = trust; -+ (void)dns_rdataset_additionaldata(ardataset, check_related, -+ fctx); -+ for (sigrdataset = ISC_LIST_HEAD(aname->list); -+ sigrdataset != NULL; -+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) { -+ if (!validinanswer(sigrdataset, fctx)) -+ return (DNS_R_FORMERR); -+ if (sigrdataset->type != dns_rdatatype_rrsig || -+ sigrdataset->covers != type) -+ continue; -+ sigrdataset->attributes |= DNS_RDATASETATTR_ANSWERSIG; -+ sigrdataset->attributes |= DNS_RDATASETATTR_CACHE; -+ sigrdataset->trust = trust; -+ break; -+ } -+ } else if (cname != NULL) { -+ if (!validinanswer(crdataset, fctx)) { -+ return (DNS_R_FORMERR); -+ } -+ if (type == dns_rdatatype_rrsig || type == dns_rdatatype_key || -+ type == dns_rdatatype_nsec) -+ { -+ char buf[DNS_RDATATYPE_FORMATSIZE]; -+ dns_rdatatype_format(type, buf, sizeof(buf)); -+ log_formerr(fctx, "CNAME response for %s RR", buf); -+ return (DNS_R_FORMERR); -+ } -+ if (!is_answertarget_allowed(fctx, qname, cname, crdataset, -+ NULL)) -+ { -+ return (DNS_R_SERVFAIL); -+ } -+ cname->attributes |= DNS_NAMEATTR_CACHE; -+ cname->attributes |= DNS_NAMEATTR_ANSWER; -+ cname->attributes |= DNS_NAMEATTR_CHAINING; -+ crdataset->attributes |= DNS_RDATASETATTR_ANSWER; -+ crdataset->attributes |= DNS_RDATASETATTR_CACHE; -+ crdataset->attributes |= DNS_RDATASETATTR_CHAINING; -+ crdataset->trust = trust; -+ for (sigrdataset = ISC_LIST_HEAD(cname->list); -+ sigrdataset != NULL; -+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) -+ { -+ if (!validinanswer(sigrdataset, fctx)) { -+ return (DNS_R_FORMERR); -+ } -+ if (sigrdataset->type != dns_rdatatype_rrsig || -+ sigrdataset->covers != dns_rdatatype_cname) -+ { -+ continue; -+ } -+ sigrdataset->attributes |= DNS_RDATASETATTR_ANSWERSIG; -+ sigrdataset->attributes |= DNS_RDATASETATTR_CACHE; -+ sigrdataset->trust = trust; -+ break; -+ } -+ chaining = ISC_TRUE; -+ } else if (dname != NULL) { -+ if (!validinanswer(drdataset, fctx)) { -+ return (DNS_R_FORMERR); -+ } -+ if (!is_answertarget_allowed(fctx, qname, dname, drdataset, -+ &chaining)) { -+ return (DNS_R_SERVFAIL); -+ } -+ dname->attributes |= DNS_NAMEATTR_CACHE; -+ dname->attributes |= DNS_NAMEATTR_ANSWER; -+ dname->attributes |= DNS_NAMEATTR_CHAINING; -+ drdataset->attributes |= DNS_RDATASETATTR_ANSWER; -+ drdataset->attributes |= DNS_RDATASETATTR_CACHE; -+ drdataset->attributes |= DNS_RDATASETATTR_CHAINING; -+ drdataset->trust = trust; -+ for (sigrdataset = ISC_LIST_HEAD(dname->list); -+ sigrdataset != NULL; -+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) -+ { -+ if (!validinanswer(sigrdataset, fctx)) { -+ return (DNS_R_FORMERR); -+ } -+ if (sigrdataset->type != dns_rdatatype_rrsig || -+ sigrdataset->covers != dns_rdatatype_dname) -+ { -+ continue; -+ } -+ sigrdataset->attributes |= DNS_RDATASETATTR_ANSWERSIG; -+ sigrdataset->attributes |= DNS_RDATASETATTR_CACHE; -+ sigrdataset->trust = trust; -+ break; -+ } -+ } else { - log_formerr(fctx, "reply has no answer"); - return (DNS_R_FORMERR); - } -@@ -6536,14 +6340,8 @@ answer_response(fetchctx_t *fctx) { - /* - * Did chaining end before we got the final answer? - */ -- if (chaining != 0) { -- /* -- * Yes. This may be a negative reply, so hand off -- * authority section processing to the noanswer code. -- * If it isn't a noanswer response, no harm will be -- * done. -- */ -- return (noanswer_response(fctx, qname, 0)); -+ if (chaining) { -+ return (ISC_R_SUCCESS); - } - - /* -@@ -6562,11 +6360,9 @@ answer_response(fetchctx_t *fctx) { - * We expect there to be only one owner name for all the rdatasets - * in this section, and we expect that it is not external. - */ -- done = ISC_FALSE; -- ns_name = NULL; -- ns_rdataset = NULL; - result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); - while (!done && result == ISC_R_SUCCESS) { -+ isc_boolean_t external; - name = NULL; - dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); - external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); -@@ -6585,12 +6381,13 @@ answer_response(fetchctx_t *fctx) { - DNS_NAMEATTR_CACHE; - rdataset->attributes |= - DNS_RDATASETATTR_CACHE; -- if (aa && chaining == 0) -+ if (aa && !chaining) { - rdataset->trust = - dns_trust_authauthority; -- else -+ } else { - rdataset->trust = - dns_trust_additional; -+ } - - if (rdataset->type == dns_rdatatype_ns) - { -@@ -7249,6 +7046,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - * Is the remote server broken, or does it dislike us? - */ - if (message->rcode != dns_rcode_noerror && -+ message->rcode != dns_rcode_yxdomain && - message->rcode != dns_rcode_nxdomain) { - if (((message->rcode == dns_rcode_formerr || - message->rcode == dns_rcode_notimp) || -@@ -7293,13 +7091,6 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - log_formerr(fctx, "server sent FORMERR"); - result = DNS_R_FORMERR; - } -- } else if (message->rcode == dns_rcode_yxdomain) { -- /* -- * DNAME mapping failed because the new name -- * was too long. There's no chance of success -- * for this fetch. -- */ -- result = DNS_R_YXDOMAIN; - } else if (message->rcode == dns_rcode_badvers) { - unsigned int flags, mask; - unsigned int version; -@@ -7404,6 +7195,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - */ - if (message->counts[DNS_SECTION_ANSWER] > 0 && - (message->rcode == dns_rcode_noerror || -+ message->rcode == dns_rcode_yxdomain || - message->rcode == dns_rcode_nxdomain)) { - /* - * [normal case] --- -2.9.3 - diff --git a/SOURCES/bind99-CVE-2017-3142+3143.patch b/SOURCES/bind99-CVE-2017-3142+3143.patch deleted file mode 100644 index a0190f4..0000000 --- a/SOURCES/bind99-CVE-2017-3142+3143.patch +++ /dev/null @@ -1,497 +0,0 @@ -diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c -index 00a0080..336c4da 100644 ---- a/lib/dns/dnssec.c -+++ b/lib/dns/dnssec.c -@@ -982,6 +982,8 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, - mctx = msg->mctx; - - msg->verify_attempted = 1; -+ msg->verified_sig = 0; -+ msg->sig0status = dns_tsigerror_badsig; - - if (is_response(msg)) { - if (msg->query.base == NULL) -@@ -1076,6 +1078,7 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, - } - - msg->verified_sig = 1; -+ msg->sig0status = dns_rcode_noerror; - - dst_context_destroy(&ctx); - dns_rdata_freestruct(&sig); -diff --git a/lib/dns/message.c b/lib/dns/message.c -index 1417067..0621175 100644 ---- a/lib/dns/message.c -+++ b/lib/dns/message.c -@@ -3052,12 +3052,19 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer) { - - result = dns_rdata_tostruct(&rdata, &tsig, NULL); - INSIST(result == ISC_R_SUCCESS); -- if (msg->tsigstatus != dns_rcode_noerror) -+ if (msg->verified_sig && -+ msg->tsigstatus == dns_rcode_noerror && -+ tsig.error == dns_rcode_noerror) -+ { -+ result = ISC_R_SUCCESS; -+ } else if ((!msg->verified_sig) || -+ (msg->tsigstatus != dns_rcode_noerror)) -+ { - result = DNS_R_TSIGVERIFYFAILURE; -- else if (tsig.error != dns_rcode_noerror) -+ } else { -+ INSIST(tsig.error != dns_rcode_noerror); - result = DNS_R_TSIGERRORSET; -- else -- result = ISC_R_SUCCESS; -+ } - dns_rdata_freestruct(&tsig); - - if (msg->tsigkey == NULL) { -diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c -index 3239bff..7b91d1e 100644 ---- a/lib/dns/tsig.c -+++ b/lib/dns/tsig.c -@@ -941,11 +941,20 @@ dns_tsig_sign(dns_message_t *msg) { - isc_buffer_putuint48(&otherbuf, tsig.timesigned); - } - -- if (key->key != NULL && tsig.error != dns_tsigerror_badsig) { -+ if ((key->key != NULL) && -+ (tsig.error != dns_tsigerror_badsig) && -+ (tsig.error != dns_tsigerror_badkey)) -+ { - unsigned char header[DNS_MESSAGE_HEADERLEN]; - isc_buffer_t headerbuf; - isc_uint16_t digestbits; - -+ /* -+ * If it is a response, we assume that the request MAC -+ * has validated at this point. This is why we include a -+ * MAC length > 0 in the reply. -+ */ -+ - ret = dst_context_create3(key->key, mctx, - DNS_LOGCATEGORY_DNSSEC, - ISC_TRUE, &ctx); -@@ -953,7 +962,7 @@ dns_tsig_sign(dns_message_t *msg) { - return (ret); - - /* -- * If this is a response, digest the query signature. -+ * If this is a response, digest the request's MAC. - */ - if (response) { - dns_rdata_t querytsigrdata = DNS_RDATA_INIT; -@@ -1083,6 +1092,17 @@ dns_tsig_sign(dns_message_t *msg) { - dst_context_destroy(&ctx); - digestbits = dst_key_getbits(key->key); - if (digestbits != 0) { -+ /* -+ * XXXRAY: Is this correct? What is the -+ * expected behavior when digestbits is not an -+ * integral multiple of 8? It looks like bytes -+ * should either be (digestbits/8) or -+ * (digestbits+7)/8. -+ * -+ * In any case, for current algorithms, -+ * digestbits are an integral multiple of 8, so -+ * it has the same effect as (digestbits/8). -+ */ - unsigned int bytes = (digestbits + 1) / 8; - if (response && bytes < querytsig.siglen) - bytes = querytsig.siglen; -@@ -1196,6 +1216,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey)); - - msg->verify_attempted = 1; -+ msg->verified_sig = 0; -+ msg->tsigstatus = dns_tsigerror_badsig; - - if (msg->tcp_continuation) { - if (tsigkey == NULL || msg->querytsig == NULL) -@@ -1294,19 +1316,6 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - key = tsigkey->key; - - /* -- * Is the time ok? -- */ -- if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { -- msg->tsigstatus = dns_tsigerror_badtime; -- tsig_log(msg->tsigkey, 2, "signature has expired"); -- return (DNS_R_CLOCKSKEW); -- } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { -- msg->tsigstatus = dns_tsigerror_badtime; -- tsig_log(msg->tsigkey, 2, "signature is in the future"); -- return (DNS_R_CLOCKSKEW); -- } -- -- /* - * Check digest length. - */ - alg = dst_key_alg(key); -@@ -1315,31 +1324,19 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - return (ret); - if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || - alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || -- alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) { -- isc_uint16_t digestbits = dst_key_getbits(key); -+ alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) -+ { - if (tsig.siglen > siglen) { -- tsig_log(msg->tsigkey, 2, "signature length to big"); -+ tsig_log(msg->tsigkey, 2, "signature length too big"); - return (DNS_R_FORMERR); - } - if (tsig.siglen > 0 && -- (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) { -+ (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) -+ { - tsig_log(msg->tsigkey, 2, - "signature length below minimum"); - return (DNS_R_FORMERR); - } -- if (tsig.siglen > 0 && digestbits != 0 && -- tsig.siglen < ((digestbits + 1) / 8)) { -- msg->tsigstatus = dns_tsigerror_badtrunc; -- tsig_log(msg->tsigkey, 2, -- "truncated signature length too small"); -- return (DNS_R_TSIGVERIFYFAILURE); -- } -- if (tsig.siglen > 0 && digestbits == 0 && -- tsig.siglen < siglen) { -- msg->tsigstatus = dns_tsigerror_badtrunc; -- tsig_log(msg->tsigkey, 2, "signature length too small"); -- return (DNS_R_TSIGVERIFYFAILURE); -- } - } - - if (tsig.siglen > 0) { -@@ -1451,34 +1448,92 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - - ret = dst_context_verify(ctx, &sig_r); - if (ret == DST_R_VERIFYFAILURE) { -- msg->tsigstatus = dns_tsigerror_badsig; - ret = DNS_R_TSIGVERIFYFAILURE; - tsig_log(msg->tsigkey, 2, - "signature failed to verify(1)"); - goto cleanup_context; -- } else if (ret != ISC_R_SUCCESS) -+ } else if (ret != ISC_R_SUCCESS) { - goto cleanup_context; -- -- dst_context_destroy(&ctx); -+ } - } else if (tsig.error != dns_tsigerror_badsig && - tsig.error != dns_tsigerror_badkey) { -- msg->tsigstatus = dns_tsigerror_badsig; - tsig_log(msg->tsigkey, 2, "signature was empty"); - return (DNS_R_TSIGVERIFYFAILURE); - } - -- msg->tsigstatus = dns_rcode_noerror; -+ /* -+ * Here at this point, the MAC has been verified. Even if any of -+ * the following code returns a TSIG error, the reply will be -+ * signed and WILL always include the request MAC in the digest -+ * computation. -+ */ -+ -+ /* -+ * Is the time ok? -+ */ -+ if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { -+ msg->tsigstatus = dns_tsigerror_badtime; -+ tsig_log(msg->tsigkey, 2, "signature has expired"); -+ ret = DNS_R_CLOCKSKEW; -+ goto cleanup_context; -+ } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { -+ msg->tsigstatus = dns_tsigerror_badtime; -+ tsig_log(msg->tsigkey, 2, "signature is in the future"); -+ ret = DNS_R_CLOCKSKEW; -+ goto cleanup_context; -+ } -+ -+ if ( -+#ifndef PK11_MD5_DISABLE -+ alg == DST_ALG_HMACMD5 || -+#endif -+ alg == DST_ALG_HMACSHA1 || -+ alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || -+ alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) -+ { -+ isc_uint16_t digestbits = dst_key_getbits(key); -+ -+ /* -+ * XXXRAY: Is this correct? What is the expected -+ * behavior when digestbits is not an integral multiple -+ * of 8? It looks like bytes should either be -+ * (digestbits/8) or (digestbits+7)/8. -+ * -+ * In any case, for current algorithms, digestbits are -+ * an integral multiple of 8, so it has the same effect -+ * as (digestbits/8). -+ */ -+ if (tsig.siglen > 0 && digestbits != 0 && -+ tsig.siglen < ((digestbits + 1) / 8)) -+ { -+ msg->tsigstatus = dns_tsigerror_badtrunc; -+ tsig_log(msg->tsigkey, 2, -+ "truncated signature length too small"); -+ ret = DNS_R_TSIGVERIFYFAILURE; -+ goto cleanup_context; -+ } -+ if (tsig.siglen > 0 && digestbits == 0 && -+ tsig.siglen < siglen) -+ { -+ msg->tsigstatus = dns_tsigerror_badtrunc; -+ tsig_log(msg->tsigkey, 2, "signature length too small"); -+ ret = DNS_R_TSIGVERIFYFAILURE; -+ goto cleanup_context; -+ } -+ } - - if (tsig.error != dns_rcode_noerror) { -+ msg->tsigstatus = tsig.error; - if (tsig.error == dns_tsigerror_badtime) -- return (DNS_R_CLOCKSKEW); -+ ret = DNS_R_CLOCKSKEW; - else -- return (DNS_R_TSIGERRORSET); -+ ret = DNS_R_TSIGERRORSET; -+ goto cleanup_context; - } - -+ msg->tsigstatus = dns_rcode_noerror; - msg->verified_sig = 1; -- -- return (ISC_R_SUCCESS); -+ ret = ISC_R_SUCCESS; - - cleanup_context: - if (ctx != NULL) -@@ -1503,6 +1558,8 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - isc_uint16_t addcount, id; - isc_boolean_t has_tsig = ISC_FALSE; - isc_mem_t *mctx; -+ unsigned int siglen; -+ unsigned int alg; - - REQUIRE(source != NULL); - REQUIRE(msg != NULL); -@@ -1510,12 +1567,16 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - REQUIRE(msg->tcp_continuation == 1); - REQUIRE(msg->querytsig != NULL); - -+ msg->verified_sig = 0; -+ msg->tsigstatus = dns_tsigerror_badsig; -+ - if (!is_response(msg)) - return (DNS_R_EXPECTEDRESPONSE); - - mctx = msg->mctx; - - tsigkey = dns_message_gettsigkey(msg); -+ key = tsigkey->key; - - /* - * Extract and parse the previous TSIG -@@ -1548,7 +1609,8 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - * Do the key name and algorithm match that of the query? - */ - if (!dns_name_equal(keyname, &tsigkey->name) || -- !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) { -+ !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) -+ { - msg->tsigstatus = dns_tsigerror_badkey; - ret = DNS_R_TSIGVERIFYFAILURE; - tsig_log(msg->tsigkey, 2, -@@ -1557,27 +1619,40 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - } - - /* -- * Is the time ok? -+ * Check digest length. - */ -- isc_stdtime_get(&now); -- -- if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { -- msg->tsigstatus = dns_tsigerror_badtime; -- tsig_log(msg->tsigkey, 2, "signature has expired"); -- ret = DNS_R_CLOCKSKEW; -- goto cleanup_querystruct; -- } else if (now + msg->timeadjust < -- tsig.timesigned - tsig.fudge) { -- msg->tsigstatus = dns_tsigerror_badtime; -- tsig_log(msg->tsigkey, 2, -- "signature is in the future"); -- ret = DNS_R_CLOCKSKEW; -+ alg = dst_key_alg(key); -+ ret = dst_key_sigsize(key, &siglen); -+ if (ret != ISC_R_SUCCESS) - goto cleanup_querystruct; -+ if ( -+#ifndef PK11_MD5_DISABLE -+ alg == DST_ALG_HMACMD5 || -+#endif -+ alg == DST_ALG_HMACSHA1 || -+ alg == DST_ALG_HMACSHA224 || -+ alg == DST_ALG_HMACSHA256 || -+ alg == DST_ALG_HMACSHA384 || -+ alg == DST_ALG_HMACSHA512) -+ { -+ if (tsig.siglen > siglen) { -+ tsig_log(tsigkey, 2, -+ "signature length too big"); -+ ret = DNS_R_FORMERR; -+ goto cleanup_querystruct; -+ } -+ if (tsig.siglen > 0 && -+ (tsig.siglen < 10 || -+ tsig.siglen < ((siglen + 1) / 2))) -+ { -+ tsig_log(tsigkey, 2, -+ "signature length below minimum"); -+ ret = DNS_R_FORMERR; -+ goto cleanup_querystruct; -+ } - } - } - -- key = tsigkey->key; -- - if (msg->tsigctx == NULL) { - ret = dst_context_create3(key, mctx, - DNS_LOGCATEGORY_DNSSEC, -@@ -1670,10 +1745,12 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - sig_r.length = tsig.siglen; - if (tsig.siglen == 0) { - if (tsig.error != dns_rcode_noerror) { -- if (tsig.error == dns_tsigerror_badtime) -+ msg->tsigstatus = tsig.error; -+ if (tsig.error == dns_tsigerror_badtime) { - ret = DNS_R_CLOCKSKEW; -- else -+ } else { - ret = DNS_R_TSIGERRORSET; -+ } - } else { - tsig_log(msg->tsigkey, 2, - "signature is empty"); -@@ -1684,29 +1761,111 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - - ret = dst_context_verify(msg->tsigctx, &sig_r); - if (ret == DST_R_VERIFYFAILURE) { -- msg->tsigstatus = dns_tsigerror_badsig; - tsig_log(msg->tsigkey, 2, - "signature failed to verify(2)"); - ret = DNS_R_TSIGVERIFYFAILURE; - goto cleanup_context; -+ } else if (ret != ISC_R_SUCCESS) { -+ goto cleanup_context; - } -- else if (ret != ISC_R_SUCCESS) -+ -+ /* -+ * Here at this point, the MAC has been verified. Even -+ * if any of the following code returns a TSIG error, -+ * the reply will be signed and WILL always include the -+ * request MAC in the digest computation. -+ */ -+ -+ /* -+ * Is the time ok? -+ */ -+ isc_stdtime_get(&now); -+ -+ if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { -+ msg->tsigstatus = dns_tsigerror_badtime; -+ tsig_log(msg->tsigkey, 2, "signature has expired"); -+ ret = DNS_R_CLOCKSKEW; -+ goto cleanup_context; -+ } else if (now + msg->timeadjust < -+ tsig.timesigned - tsig.fudge) -+ { -+ msg->tsigstatus = dns_tsigerror_badtime; -+ tsig_log(msg->tsigkey, 2, -+ "signature is in the future"); -+ ret = DNS_R_CLOCKSKEW; - goto cleanup_context; -+ } - -- dst_context_destroy(&msg->tsigctx); -+ alg = dst_key_alg(key); -+ ret = dst_key_sigsize(key, &siglen); -+ if (ret != ISC_R_SUCCESS) -+ goto cleanup_context; -+ if ( -+#ifndef PK11_MD5_DISABLE -+ alg == DST_ALG_HMACMD5 || -+#endif -+ alg == DST_ALG_HMACSHA1 || -+ alg == DST_ALG_HMACSHA224 || -+ alg == DST_ALG_HMACSHA256 || -+ alg == DST_ALG_HMACSHA384 || -+ alg == DST_ALG_HMACSHA512) -+ { -+ isc_uint16_t digestbits = dst_key_getbits(key); -+ -+ /* -+ * XXXRAY: Is this correct? What is the -+ * expected behavior when digestbits is not an -+ * integral multiple of 8? It looks like bytes -+ * should either be (digestbits/8) or -+ * (digestbits+7)/8. -+ * -+ * In any case, for current algorithms, -+ * digestbits are an integral multiple of 8, so -+ * it has the same effect as (digestbits/8). -+ */ -+ if (tsig.siglen > 0 && digestbits != 0 && -+ tsig.siglen < ((digestbits + 1) / 8)) -+ { -+ msg->tsigstatus = dns_tsigerror_badtrunc; -+ tsig_log(msg->tsigkey, 2, -+ "truncated signature length " -+ "too small"); -+ ret = DNS_R_TSIGVERIFYFAILURE; -+ goto cleanup_context; -+ } -+ if (tsig.siglen > 0 && digestbits == 0 && -+ tsig.siglen < siglen) -+ { -+ msg->tsigstatus = dns_tsigerror_badtrunc; -+ tsig_log(msg->tsigkey, 2, -+ "signature length too small"); -+ ret = DNS_R_TSIGVERIFYFAILURE; -+ goto cleanup_context; -+ } -+ } -+ -+ if (tsig.error != dns_rcode_noerror) { -+ msg->tsigstatus = tsig.error; -+ if (tsig.error == dns_tsigerror_badtime) -+ ret = DNS_R_CLOCKSKEW; -+ else -+ ret = DNS_R_TSIGERRORSET; -+ goto cleanup_context; -+ } - } - - msg->tsigstatus = dns_rcode_noerror; -- return (ISC_R_SUCCESS); -+ msg->verified_sig = 1; -+ ret = ISC_R_SUCCESS; - - cleanup_context: -- dst_context_destroy(&msg->tsigctx); -+ if (msg->tsigctx != NULL) -+ dst_context_destroy(&msg->tsigctx); - - cleanup_querystruct: - dns_rdata_freestruct(&querytsig); - - return (ret); -- - } - - isc_result_t diff --git a/SOURCES/bind99-CVE-2017-3145.patch b/SOURCES/bind99-CVE-2017-3145.patch deleted file mode 100644 index 167f277..0000000 --- a/SOURCES/bind99-CVE-2017-3145.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 4d73fed57703f561aefd545eda0f3f2c5e69a547 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= -Date: Tue, 16 Jan 2018 09:50:45 +0100 -Subject: [PATCH] 4858. [security] Addresses could be referenced after - being freed in resolver.c, causing an assertion failure. - (CVE-2017-3145) [RT #46839] - ---- - lib/dns/resolver.c | 37 +++++++++++++++++++++++-------------- - 1 file changed, 23 insertions(+), 14 deletions(-) - -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 860a792..619646f 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -751,7 +751,7 @@ fctx_stoptimer(fetchctx_t *fctx) { - * cannot fail in that case. - */ - result = isc_timer_reset(fctx->timer, isc_timertype_inactive, -- NULL, NULL, ISC_TRUE); -+ NULL, NULL, ISC_TRUE); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_timer_reset(): %s", -@@ -759,7 +759,6 @@ fctx_stoptimer(fetchctx_t *fctx) { - } - } - -- - static inline isc_result_t - fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) { - /* -@@ -992,7 +991,8 @@ fctx_cleanupfinds(fetchctx_t *fctx) { - - for (find = ISC_LIST_HEAD(fctx->finds); - find != NULL; -- find = next_find) { -+ find = next_find) -+ { - next_find = ISC_LIST_NEXT(find, publink); - ISC_LIST_UNLINK(fctx->finds, find, publink); - dns_adb_destroyfind(&find); -@@ -1008,7 +1008,8 @@ fctx_cleanupaltfinds(fetchctx_t *fctx) { - - for (find = ISC_LIST_HEAD(fctx->altfinds); - find != NULL; -- find = next_find) { -+ find = next_find) -+ { - next_find = ISC_LIST_NEXT(find, publink); - ISC_LIST_UNLINK(fctx->altfinds, find, publink); - dns_adb_destroyfind(&find); -@@ -1024,7 +1025,8 @@ fctx_cleanupforwaddrs(fetchctx_t *fctx) { - - for (addr = ISC_LIST_HEAD(fctx->forwaddrs); - addr != NULL; -- addr = next_addr) { -+ addr = next_addr) -+ { - next_addr = ISC_LIST_NEXT(addr, publink); - ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink); - dns_adb_freeaddrinfo(fctx->adb, &addr); -@@ -1039,7 +1041,8 @@ fctx_cleanupaltaddrs(fetchctx_t *fctx) { - - for (addr = ISC_LIST_HEAD(fctx->altaddrs); - addr != NULL; -- addr = next_addr) { -+ addr = next_addr) -+ { - next_addr = ISC_LIST_NEXT(addr, publink); - ISC_LIST_UNLINK(fctx->altaddrs, addr, publink); - dns_adb_freeaddrinfo(fctx->adb, &addr); -@@ -1047,14 +1050,18 @@ fctx_cleanupaltaddrs(fetchctx_t *fctx) { - } - - static inline void --fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) { -- FCTXTRACE("stopeverything"); -+fctx_stopqueries(fetchctx_t *fctx, isc_boolean_t no_response) { -+ FCTXTRACE("stopqueries"); - fctx_cancelqueries(fctx, no_response); -+ fctx_stoptimer(fctx); -+} -+ -+static inline void -+fctx_cleanupall(fetchctx_t *fctx) { - fctx_cleanupfinds(fctx); - fctx_cleanupaltfinds(fctx); - fctx_cleanupforwaddrs(fctx); - fctx_cleanupaltaddrs(fctx); -- fctx_stoptimer(fctx); - } - - static inline void -@@ -1184,7 +1191,8 @@ fctx_done(fetchctx_t *fctx, isc_result_t result, int line) { - no_response = ISC_FALSE; - - fctx->reason = NULL; -- fctx_stopeverything(fctx, no_response); -+ -+ fctx_stopqueries(fctx, no_response); - - LOCK(&res->buckets[fctx->bucketnum].lock); - -@@ -3336,11 +3344,12 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) { - dns_resolver_cancelfetch(fctx->nsfetch); - - /* -- * Shut down anything that is still running on behalf of this -- * fetch. To avoid deadlock with the ADB, we must do this -- * before we lock the bucket lock. -+ * Shut down anything still running on behalf of this -+ * fetch, and clean up finds and addresses. To avoid deadlock -+ * with the ADB, we must do this before we lock the bucket lock. - */ -- fctx_stopeverything(fctx, ISC_FALSE); -+ fctx_stopqueries(fctx, ISC_FALSE); -+ fctx_cleanupall(fctx); - - LOCK(&res->buckets[bucketnum].lock); - --- -2.14.3 - diff --git a/SOURCES/bind99-CVE-2018-5740.patch b/SOURCES/bind99-CVE-2018-5740.patch deleted file mode 100644 index 90e858a..0000000 --- a/SOURCES/bind99-CVE-2018-5740.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 252a02f..bfffb8a 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -5957,6 +5957,7 @@ is_answertarget_allowed(fetchctx_t *fctx, dns_name_t *qname, dns_name_t *rname, - unsigned int nlabels; - dns_fixedname_t fixed; - dns_name_t prefix; -+ int order; - - REQUIRE(rdataset != NULL); - REQUIRE(rdataset->type == dns_rdatatype_cname || -@@ -5979,18 +5980,26 @@ is_answertarget_allowed(fetchctx_t *fctx, dns_name_t *qname, dns_name_t *rname, - tname = &cname.cname; - break; - case dns_rdatatype_dname: -+ if (dns_name_fullcompare(qname, rname, &order, &nlabels) != -+ dns_namereln_subdomain) -+ { -+ return (ISC_TRUE); -+ } - result = dns_rdata_tostruct(&rdata, &dname, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - dns_name_init(&prefix, NULL); - dns_fixedname_init(&fixed); - tname = dns_fixedname_name(&fixed); -- nlabels = dns_name_countlabels(qname) - -- dns_name_countlabels(rname); -+ nlabels = dns_name_countlabels(rname); - dns_name_split(qname, nlabels, &prefix, NULL); - result = dns_name_concatenate(&prefix, &dname.dname, tname, - NULL); -- if (result == DNS_R_NAMETOOLONG) -+ if (result == DNS_R_NAMETOOLONG) { -+ if (chainingp != NULL) { -+ *chainingp = ISC_TRUE; -+ } - return (ISC_TRUE); -+ } - RUNTIME_CHECK(result == ISC_R_SUCCESS); - break; - default: -@@ -6719,7 +6728,9 @@ answer_response(fetchctx_t *fctx) { - } - if ((ardataset->type == dns_rdatatype_cname || - ardataset->type == dns_rdatatype_dname) && -- !is_answertarget_allowed(fctx, qname, aname, ardataset, -+ type != ardataset->type && -+ type != dns_rdatatype_any && -+ !is_answertarget_allowed(fctx, qname, aname, ardataset, - NULL)) - { - return (DNS_R_SERVFAIL); diff --git a/SOURCES/bind99-CVE-2018-5743-option.patch b/SOURCES/bind99-CVE-2018-5743-option.patch deleted file mode 100644 index 264b157..0000000 --- a/SOURCES/bind99-CVE-2018-5743-option.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 7e7fc71357309c1646eee51d82ab515472c62346 Mon Sep 17 00:00:00 2001 -From: Evan Hunt -Date: Tue, 20 Jan 2015 16:10:30 -0800 -Subject: [PATCH] add keep-response-order option warning - -Support keep-response-order ACL on input, but do not take any action -setting it. Used as backward compatibility after support for pipelining -and TCP connection reusage were again removed. ---- - bin/named/config.c | 1 + - bin/named/server.c | 11 ++++++++++ - bin/tests/named.conf | 3 ++- - .../checkconf/bad-keep-response-order.conf | 21 +++++++++++++++++++ - bin/tests/system/checkconf/bad-many.conf | 3 ++- - bin/tests/system/checkconf/good.conf | 3 +++ - lib/bind9/check.c | 4 ++-- - lib/isccfg/namedconf.c | 1 + - 8 files changed, 43 insertions(+), 4 deletions(-) - create mode 100644 bin/tests/system/checkconf/bad-keep-response-order.conf - -diff --git a/bin/named/config.c b/bin/named/config.c -index 22d8a85..515cc4f 100644 ---- a/bin/named/config.c -+++ b/bin/named/config.c -@@ -72,6 +72,7 @@ options {\n\ - heartbeat-interval 60;\n\ - host-statistics no;\n\ - interface-interval 60;\n\ -+# keep-response-order {any;};\n\ - listen-on {any;};\n\ - listen-on-v6 {none;};\n\ - match-mapped-addresses no;\n\ -diff --git a/bin/named/server.c b/bin/named/server.c -index e8f19d3..0ee47af 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -4987,6 +4987,7 @@ load_configuration(const char *filename, ns_server_t *server, - const cfg_obj_t *options; - const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports; - const cfg_obj_t *views; -+ dns_acl_t *keepresporder=NULL; - dns_view_t *view = NULL; - dns_view_t *view_next; - dns_viewlist_t tmpviewlist; -@@ -5207,6 +5208,16 @@ load_configuration(const char *filename, ns_server_t *server, - dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, - server->blackholeacl); - -+ CHECK(configure_view_acl(NULL, config, "keep-response-order", NULL, -+ ns_g_aclconfctx, ns_g_mctx, -+ &keepresporder)); -+ if (keepresporder != NULL) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING, -+ "keep-response-order option is ignored and can be safely removed"); -+ dns_acl_detach(&keepresporder); -+ } -+ - obj = NULL; - result = ns_config_get(maps, "match-mapped-addresses", &obj); - INSIST(result == ISC_R_SUCCESS); -diff --git a/bin/tests/named.conf b/bin/tests/named.conf -index 722d262..5b40045 100644 ---- a/bin/tests/named.conf -+++ b/bin/tests/named.conf -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2004, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") -+ * Copyright (C) 2004, 2007, 2011, 2014 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any -@@ -116,6 +116,7 @@ options { - allow-transfer { any; }; - allow-recursion { !any; }; - blackhole { 45/24; }; -+ keep-response-order { 46/24; }; - - listen-on { - 10/24; -diff --git a/bin/tests/system/checkconf/bad-keep-response-order.conf b/bin/tests/system/checkconf/bad-keep-response-order.conf -new file mode 100644 -index 0000000..24c1f6c ---- /dev/null -+++ b/bin/tests/system/checkconf/bad-keep-response-order.conf -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+options { -+ keep-response-order { -+ does_not_exist; -+ }; -+}; -diff --git a/bin/tests/system/checkconf/bad-many.conf b/bin/tests/system/checkconf/bad-many.conf -index cfc4d02..09add87 100644 ---- a/bin/tests/system/checkconf/bad-many.conf -+++ b/bin/tests/system/checkconf/bad-many.conf -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2005, 2012 Internet Systems Consortium, Inc. ("ISC") -+ * Copyright (C) 2005, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above -@@ -33,6 +33,7 @@ options { - host-statistics-max 100; - hostname none; - interface-interval 30; -+ keep-response-order { 10.0.0.10/24; }; - listen-on port 90 { any; }; - listen-on port 100 { 127.0.0.1; }; - listen-on-v6 port 53 { none; }; -diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf -index cf7c745..43b0638 100644 ---- a/bin/tests/system/checkconf/good.conf -+++ b/bin/tests/system/checkconf/good.conf -@@ -44,6 +44,9 @@ options { - host-statistics-max 100; - hostname none; - interface-interval 30; -+ keep-response-order { -+ 10.0.0.10/24; -+ }; - listen-on port 90 { - "any"; - }; -diff --git a/lib/bind9/check.c b/lib/bind9/check.c -index 00c4b3e..d4803e2 100644 ---- a/lib/bind9/check.c -+++ b/lib/bind9/check.c -@@ -403,8 +403,8 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, - - static const char *acls[] = { "allow-query", "allow-query-on", - "allow-query-cache", "allow-query-cache-on", -- "blackhole", "match-clients", "match-destinations", -- "sortlist", "filter-aaaa", NULL }; -+ "blackhole", "keep-response-order", "match-clients", -+ "match-destinations", "sortlist", "filter-aaaa", NULL }; - - while (acls[i] != NULL) { - tresult = checkacl(acls[i++], actx, NULL, voptions, config, -diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c -index d9b1df1..f357c63 100644 ---- a/lib/isccfg/namedconf.c -+++ b/lib/isccfg/namedconf.c -@@ -959,6 +959,7 @@ options_clauses[] = { - { "host-statistics-max", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, - { "hostname", &cfg_type_qstringornone, 0 }, - { "interface-interval", &cfg_type_uint32, 0 }, -+ { "keep-response-order", &cfg_type_bracketed_aml, 0 }, - { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, - { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI }, - { "managed-keys-directory", &cfg_type_qstring, 0 }, --- -2.20.1 - diff --git a/SOURCES/bind99-CVE-2018-5743.patch b/SOURCES/bind99-CVE-2018-5743.patch deleted file mode 100644 index c1fa5f0..0000000 --- a/SOURCES/bind99-CVE-2018-5743.patch +++ /dev/null @@ -1,717 +0,0 @@ -From c8292710c84e40eeaea6a51df2842fc5f34458d5 Mon Sep 17 00:00:00 2001 -From: Petr Mensik -Date: Wed, 5 Jun 2019 15:57:14 +0200 -Subject: [PATCH] Fix CVE-2018-5743 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Squashed commit of the following: - -commit f8e5335ea483c72341093f02d964b1ea9290077d -Author: Petr Mensik -Date: Tue Jun 4 17:19:20 2019 +0200 - - Remove pipelined parameter and tcpconn structure with reference counter - - It is not ever used in this version. Is not required to work. - - TCP connection is never shared in this version. Do not use reference - counter, just attach and detach tcpquota to given client. - -commit e3521d5531054b51e897e5458b09392cc752797d -Author: Evan Hunt -Date: Fri Apr 5 16:26:19 2019 -0700 - - restore allowance for tcp-clients < interfaces - - in the "refactor tcpquota and pipeline refs" commit, the counting - of active interfaces was tightened in such a way that named could - fail to listen on an interface if there were more interfaces than - tcp-clients. when checking the quota to start accepting on an - interface, if the number of active clients was above zero, then - it was presumed that some other client was able to handle accepting - new connections. this, however, ignored the fact that the current client - could be included in that count, so if the quota was already exceeded - before all the interfaces were listening, some interfaces would never - listen. - - we now check whether the current client has been marked active; if so, - then the number of active clients on the interface must be greater - than 1, not 0. - - (cherry picked from commit 0b4e2cd4c3192ba88569dd344f542a8cc43742b5) - (cherry picked from commit d01023aaac35543daffbdf48464e320150235d41) - (cherry picked from commit 59434b987e8eb436b08c24e559ee094c4e939daa) - -commit 934effeb8a76f735ca1b07fbd00bc5c8e8d285a3 -Author: Evan Hunt -Date: Fri Apr 5 16:26:05 2019 -0700 - - refactor tcpquota and pipeline refs; allow special-case overrun in isc_quota - - - if the TCP quota has been exceeded but there are no clients listening - for new connections on the interface, we can now force attachment to the - quota using isc_quota_force(), instead of carrying on with the quota not - attached. - - the TCP client quota is now referenced via a reference-counted - 'ns_tcpconn' object, one of which is created whenever a client begins - listening for new connections, and attached to by members of that - client's pipeline group. when the last reference to the tcpconn - object is detached, it is freed and the TCP quota slot is released. - - reduce code duplication by adding mark_tcp_active() function. - - convert counters to atomic. - - (cherry picked from commit 7e8222378ca24f1302a0c1c638565050ab04681b) - (cherry picked from commit 4939451275722bfda490ea86ca13e84f6bc71e46) - (cherry picked from commit 13f7c918b8720d890408f678bd73c20e634539d9) - (cherry picked from commit c47ccf630f147378568b33e8fdb7b754f228c346) - - Remove usage of atomic operations, use classic locks - -commit adb720fd828327ef7452fbe9248ab6a2e0c99d8f -Author: Evan Hunt -Date: Fri Apr 5 16:12:18 2019 -0700 - - better tcpquota accounting and client mortality checks - - - ensure that tcpactive is cleaned up correctly when accept() fails. - - set 'client->tcpattached' when the client is attached to the tcpquota. - carry this value on to new clients sharing the same pipeline group. - don't call isc_quota_detach() on the tcpquota unless tcpattached is - set. this way clients that were allowed to accept TCP connections - despite being over quota (and therefore, were never attached to the - quota) will not inadvertently detach from it and mess up the - accounting. - - simplify the code for tcpquota disconnection by using a new function - tcpquota_disconnect(). - - before deciding whether to reject a new connection due to quota - exhaustion, check to see whether there are at least two active - clients. previously, this was "at least one", but that could be - insufficient if there was one other client in READING state (waiting - for messages on an open connection) but none in READY (listening - for new connections). - - before deciding whether a TCP client object can to go inactive, we - must ensure there are enough other clients to maintain service - afterward -- both accepting new connections and reading/processing new - queries. A TCP client can't shut down unless at least one - client is accepting new connections and (in the case of pipelined - clients) at least one additional client is waiting to read. - - (cherry picked from commit c7394738b2445c16f728a88394864dd61baad900) - (cherry picked from commit e965d5f11d3d0f6d59704e614fceca2093cb1856) - (cherry picked from commit 87d431161450777ea093821212abfb52d51b36e3) - (cherry picked from commit 2ab8a085b3c666f28f1f9229bd6ecb59915b26c3) - -commit a2c8804aec66f3e44d7dbb6a1b0f64d6cd7110dd -Author: Witold Kręcicki -Date: Fri Jan 4 12:50:51 2019 +0100 - - tcp-clients could still be exceeded (v2) - - the TCP client quota could still be ineffective under some - circumstances. this change: - - - improves quota accounting to ensure that TCP clients are - properly limited, while still guaranteeing that at least one client - is always available to serve TCP connections on each interface. - - uses more descriptive names and removes one (ntcptarget) that - was no longer needed - - adds comments - - (cherry picked from commit 924651f1d5e605cd186d03f4f7340bcc54d77cc2) - (cherry picked from commit 55a7a458e30e47874d34bdf1079eb863a0512396) - (cherry picked from commit 719f604e3fad5b7479bd14e2fa0ef4413f0a8fdc) - - Removed some unused parts - -Patch: bind98-CVE-2018-5743.patch -PatchNumber: 199 ---- - bin/named/client.c | 273 ++++++++++++++++++++----- - bin/named/include/named/client.h | 4 +- - bin/named/include/named/interfacemgr.h | 11 +- - bin/named/interfacemgr.c | 8 +- - doc/arm/Bv9ARM-book.xml | 3 +- - lib/isc/include/isc/quota.h | 7 + - lib/isc/quota.c | 33 ++- - 7 files changed, 275 insertions(+), 64 deletions(-) - -diff --git a/bin/named/client.c b/bin/named/client.c -index 9adf36b..c21b449 100644 ---- a/bin/named/client.c -+++ b/bin/named/client.c -@@ -279,6 +279,76 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) { - } - - /*% -+ * Allocate a reference-counted object that will maintain a single pointer to -+ * the (also reference-counted) TCP client quota, shared between all the -+ * clients processing queries on a single TCP connection. -+ */ -+static isc_result_t -+tcpconn_init(ns_client_t *client, isc_boolean_t force) { -+ isc_result_t result; -+ isc_quota_t *quota = NULL; -+ -+ REQUIRE(client->tcpquota == NULL); -+ -+ /* -+ * Try to attach to the quota first, so we won't pointlessly -+ * allocate memory for a tcpconn object if we can't get one. -+ */ -+ if (force) { -+ result = isc_quota_force(&ns_g_server->tcpquota, "a); -+ } else { -+ result = isc_quota_attach(&ns_g_server->tcpquota, "a); -+ } -+ if (result != ISC_R_SUCCESS) { -+ return (result); -+ } -+ -+ client->tcpquota = quota; -+ quota = NULL; -+ -+ return (ISC_R_SUCCESS); -+} -+ -+/*% -+ * Decrease the count of client structures sharing the TCP connection that -+ * 'client' is associated with. If this is the last client using this TCP -+ * connection, we detach from the TCP quota. -+ */ -+static void -+tcpconn_detach(ns_client_t *client) { -+ REQUIRE(client->tcpquota != NULL); -+ -+ isc_quota_detach(&client->tcpquota); -+} -+ -+/*% -+ * Mark a client as active and increment the interface's 'ntcpactive' -+ * counter, as a signal that there is at least one client servicing -+ * TCP queries for the interface. If we reach the TCP client quota at -+ * some point, this will be used to determine whether a quota overrun -+ * should be permitted. -+ * -+ * Marking the client active with the 'tcpactive' flag ensures proper -+ * accounting, by preventing us from incrementing or decrementing -+ * 'ntcpactive' more than once per client. -+ */ -+static void -+mark_tcp_active(ns_client_t *client, isc_boolean_t active) { -+ if (active && !client->tcpactive) { -+ LOCK(&client->interface->lock); -+ client->interface->ntcpactive++; -+ client->tcpactive = active; -+ UNLOCK(&client->interface->lock); -+ } else if (!active && client->tcpactive) { -+ LOCK(&client->interface->lock); -+ INSIST(client->interface->ntcpactive > 0); -+ client->interface->ntcpactive--; -+ client->tcpactive = active; -+ UNLOCK(&client->interface->lock); -+ } -+} -+ -+/* - * Check for a deactivation or shutdown request and take appropriate - * action. Returns ISC_TRUE if either is in progress; in this case - * the caller must no longer use the client object as it may have been -@@ -367,6 +437,7 @@ exit_check(ns_client_t *client) { - INSIST(client->recursionquota == NULL); - - if (NS_CLIENTSTATE_READING == client->newstate) { -+ INSIST(client->tcpquota != NULL); - client_read(client); - client->newstate = NS_CLIENTSTATE_MAX; - return (ISC_TRUE); /* We're done. */ -@@ -380,10 +451,12 @@ exit_check(ns_client_t *client) { - */ - INSIST(client->recursionquota == NULL); - INSIST(client->newstate <= NS_CLIENTSTATE_READY); -+ - if (client->nreads > 0) - dns_tcpmsg_cancelread(&client->tcpmsg); -- if (! client->nreads == 0) { -- /* Still waiting for read cancel completion. */ -+ -+ /* Still waiting for read cancel completion. */ -+ if (client->nreads > 0) { - return (ISC_TRUE); - } - -@@ -391,14 +464,50 @@ exit_check(ns_client_t *client) { - dns_tcpmsg_invalidate(&client->tcpmsg); - client->tcpmsg_valid = ISC_FALSE; - } -+ -+ /* -+ * Soon the client will be ready to accept a new TCP -+ * connection or UDP request, but we may have enough -+ * clients doing that already. Check whether this client -+ * needs to remain active and allow it go inactive if -+ * not. -+ * -+ * UDP clients always go inactive at this point, but a TCP -+ * client may need to stay active and return to READY -+ * state if no other clients are available to listen -+ * for TCP requests on this interface. -+ * -+ * Regardless, if we're going to FREED state, that means -+ * the system is shutting down and we don't need to -+ * retain clients. -+ */ -+ LOCK(&client->interface->lock); -+ if (client->mortal && TCP_CLIENT(client) && -+ client->newstate != NS_CLIENTSTATE_FREED && -+ !ns_g_clienttest && -+ client->interface->ntcpaccepting == 0) -+ { -+ /* Nobody else is accepting */ -+ client->mortal = ISC_FALSE; -+ client->newstate = NS_CLIENTSTATE_READY; -+ } -+ UNLOCK(&client->interface->lock); -+ -+ /* -+ * Detach from TCP connection and TCP client quota, -+ * if appropriate. If this is the last reference to -+ * the TCP connection in our pipeline group, the -+ * TCP quota slot will be released. -+ */ -+ if (client->tcpquota) { -+ tcpconn_detach(client); -+ } - if (client->tcpsocket != NULL) { - CTRACE("closetcp"); - isc_socket_detach(&client->tcpsocket); -+ mark_tcp_active(client, ISC_FALSE); - } - -- if (client->tcpquota != NULL) -- isc_quota_detach(&client->tcpquota); -- - if (client->timerset) { - (void)isc_timer_reset(client->timer, - isc_timertype_inactive, -@@ -411,24 +520,6 @@ exit_check(ns_client_t *client) { - client->state = NS_CLIENTSTATE_READY; - INSIST(client->recursionquota == NULL); - -- /* -- * Now the client is ready to accept a new TCP connection -- * or UDP request, but we may have enough clients doing -- * that already. Check whether this client needs to remain -- * active and force it to go inactive if not. -- * -- * UDP clients go inactive at this point, but TCP clients -- * may remain active if we have fewer active TCP client -- * objects than desired due to an earlier quota exhaustion. -- */ -- if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) { -- LOCK(&client->interface->lock); -- if (client->interface->ntcpcurrent < -- client->interface->ntcptarget) -- client->mortal = ISC_FALSE; -- UNLOCK(&client->interface->lock); -- } -- - /* - * We don't need the client; send it to the inactive - * queue for recycling. -@@ -475,18 +566,20 @@ exit_check(ns_client_t *client) { - if (client->nctls > 0) - return (ISC_TRUE); - -- /* Deactivate the client. */ -- if (client->interface) -- ns_interface_detach(&client->interface); -- - INSIST(client->naccepts == 0); - INSIST(client->recursionquota == NULL); -- if (client->tcplistener != NULL) -+ if (client->tcplistener != NULL) { - isc_socket_detach(&client->tcplistener); -+ mark_tcp_active(client, ISC_FALSE); -+ } - - if (client->udpsocket != NULL) - isc_socket_detach(&client->udpsocket); - -+ /* Deactivate the client. */ -+ if (client->interface) -+ ns_interface_detach(&client->interface); -+ - if (client->dispatch != NULL) - dns_dispatch_detach(&client->dispatch); - -@@ -605,13 +698,16 @@ client_start(isc_task_t *task, isc_event_t *event) { - return; - - if (TCP_CLIENT(client)) { -- client_accept(client); -+ if (client->tcpquota != NULL) { -+ client_read(client); -+ } else { -+ client_accept(client); -+ } - } else { - client_udprecv(client); - } - } - -- - /*% - * The client's task has received a shutdown event. - */ -@@ -1499,6 +1595,7 @@ client_request(isc_task_t *task, isc_event_t *event) { - client->nrecvs--; - } else { - INSIST(TCP_CLIENT(client)); -+ INSIST(client->tcpquota != NULL); - REQUIRE(event->ev_type == DNS_EVENT_TCPMSG); - REQUIRE(event->ev_sender == &client->tcpmsg); - buffer = &client->tcpmsg.buffer; -@@ -2146,6 +2243,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { - client->filter_aaaa = dns_v4_aaaa_ok; - #endif - client->needshutdown = ns_g_clienttest; -+ client->tcpactive = ISC_FALSE; - - ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL, - NS_EVENT_CLIENTCONTROL, client_start, client, client, -@@ -2240,22 +2338,29 @@ static void - client_newconn(isc_task_t *task, isc_event_t *event) { - ns_client_t *client = event->ev_arg; - isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event; -- isc_result_t result; - - REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN); - REQUIRE(NS_CLIENT_VALID(client)); - REQUIRE(client->task == task); -+ REQUIRE(client->interface != NULL); - - UNUSED(task); - - INSIST(client->state == NS_CLIENTSTATE_READY); - -+ /* -+ * The accept() was successful and we're now establishing a new -+ * connection. We need to make note of it in the client and -+ * interface objects so client objects can do the right thing -+ * when going inactive in exit_check() (see comments in -+ * client_accept() for details). -+ */ - INSIST(client->naccepts == 1); - client->naccepts--; - - LOCK(&client->interface->lock); -- INSIST(client->interface->ntcpcurrent > 0); -- client->interface->ntcpcurrent--; -+ INSIST(client->interface->ntcpaccepting > 0); -+ client->interface->ntcpaccepting--; - UNLOCK(&client->interface->lock); - - /* -@@ -2289,6 +2394,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), - "accept failed: %s", - isc_result_totext(nevent->result)); -+ tcpconn_detach(client); - } - - if (exit_check(client)) -@@ -2326,16 +2432,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { - * telnetting to port 53 (once per CPU) will - * deny service to legitimate TCP clients. - */ -- result = isc_quota_attach(&ns_g_server->tcpquota, -- &client->tcpquota); -- if (result == ISC_R_SUCCESS) -- result = ns_client_replace(client); -- if (result != ISC_R_SUCCESS) { -- ns_client_log(client, NS_LOGCATEGORY_CLIENT, -- NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, -- "no more TCP clients: %s", -- isc_result_totext(result)); -- } -+ (void)ns_client_replace(client); - - client_read(client); - } -@@ -2350,12 +2447,67 @@ client_accept(ns_client_t *client) { - - CTRACE("accept"); - -+ /* -+ * Set up a new TCP connection. This means try to attach to the -+ * TCP client quota (tcp-clients), but fail if we're over quota. -+ */ -+ result = tcpconn_init(client, ISC_FALSE); -+ if (result != ISC_R_SUCCESS) { -+ isc_boolean_t exit; -+ -+ ns_client_log(client, NS_LOGCATEGORY_CLIENT, -+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING, -+ "TCP client quota reached: %s", -+ isc_result_totext(result)); -+ -+ /* -+ * We have exceeded the system-wide TCP client quota. But, -+ * we can't just block this accept in all cases, because if -+ * we did, a heavy TCP load on other interfaces might cause -+ * this interface to be starved, with no clients able to -+ * accept new connections. -+ * -+ * So, we check here to see if any other clients are -+ * already servicing TCP queries on this interface (whether -+ * accepting, reading, or processing). If we find that at -+ * least one client other than this one is active, then -+ * it's okay *not* to call accept - we can let this -+ * client go inactive and another will take over when it's -+ * done. -+ * -+ * If there aren't enough active clients on the interface, -+ * then we can be a little bit flexible about the quota. -+ * We'll allow *one* extra client through to ensure we're -+ * listening on every interface; we do this by setting the -+ * 'force' option to tcpconn_init(). -+ * -+ * (Note: In practice this means that the real TCP client -+ * quota is tcp-clients plus the number of listening -+ * interfaces plus 1.) -+ */ -+ LOCK(&client->interface->lock); -+ exit = ISC_TF(client->interface->ntcpactive > (client->tcpactive ? 1 : 0)); -+ UNLOCK(&client->interface->lock); -+ if (exit) { -+ client->newstate = NS_CLIENTSTATE_INACTIVE; -+ (void)exit_check(client); -+ return; -+ } -+ -+ result = tcpconn_init(client, ISC_TRUE); -+ RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ } -+ -+ /* -+ * If this client was set up using get_client() or get_worker(), -+ * then TCP is already marked active. However, if it was restarted -+ * from exit_check(), it might not be, so we take care of it now. -+ */ -+ mark_tcp_active(client, ISC_TRUE); -+ - result = isc_socket_accept(client->tcplistener, client->task, - client_newconn, client); - if (result != ISC_R_SUCCESS) { -- UNEXPECTED_ERROR(__FILE__, __LINE__, -- "isc_socket_accept() failed: %s", -- isc_result_totext(result)); - /* - * XXXRTH What should we do? We're trying to accept but - * it didn't work. If we just give up, then TCP -@@ -2363,12 +2515,38 @@ client_accept(ns_client_t *client) { - * - * For now, we just go idle. - */ -+ UNEXPECTED_ERROR(__FILE__, __LINE__, -+ "isc_socket_accept() failed: %s", -+ isc_result_totext(result)); -+ -+ tcpconn_detach(client); -+ mark_tcp_active(client, ISC_FALSE); - return; - } -+ -+ /* -+ * The client's 'naccepts' counter indicates that this client has -+ * called accept() and is waiting for a new connection. It should -+ * never exceed 1. -+ */ - INSIST(client->naccepts == 0); - client->naccepts++; -+ -+ /* -+ * The interface's 'ntcpaccepting' counter is incremented when -+ * any client calls accept(), and decremented in client_newconn() -+ * once the connection is established. -+ * -+ * When the client object is shutting down after handling a TCP -+ * request (see exit_check()), if this value is at least one, that -+ * means another client has called accept() and is waiting to -+ * establish the next connection. That means the client may be -+ * be free to become inactive; otherwise it may need to start -+ * listening for connections itself to prevent the interface -+ * going dead. -+ */ - LOCK(&client->interface->lock); -- client->interface->ntcpcurrent++; -+ client->interface->ntcpaccepting++; - UNLOCK(&client->interface->lock); - } - -@@ -2626,6 +2804,7 @@ get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, - - if (tcp) { - client->attributes |= NS_CLIENTATTR_TCP; -+ mark_tcp_active(client, ISC_TRUE); - isc_socket_attach(ifp->tcpsocket, - &client->tcplistener); - } else { -diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h -index 98e79df..b210e61 100644 ---- a/bin/named/include/named/client.h -+++ b/bin/named/include/named/client.h -@@ -131,7 +131,7 @@ struct ns_client { - isc_stdtime_t requesttime; - isc_stdtime_t now; - dns_name_t signername; /*%< [T]SIG key name */ -- dns_name_t * signer; /*%< NULL if not valid sig */ -+ dns_name_t *signer; /*%< NULL if not valid sig */ - isc_boolean_t mortal; /*%< Die after handling request */ - isc_quota_t *tcpquota; - isc_quota_t *recursionquota; -@@ -159,6 +159,8 @@ struct ns_client { - ISC_LINK(ns_client_t) link; - ISC_LINK(ns_client_t) rlink; - ISC_QLINK(ns_client_t) ilink; -+ -+ isc_boolean_t tcpactive; - }; - - typedef ISC_QUEUE(ns_client_t) client_queue_t; -diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h -index 380dbed..56d953c 100644 ---- a/bin/named/include/named/interfacemgr.h -+++ b/bin/named/include/named/interfacemgr.h -@@ -80,9 +80,14 @@ struct ns_interface { - dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH]; - /*%< UDP dispatchers. */ - isc_socket_t * tcpsocket; /*%< TCP socket. */ -- int ntcptarget; /*%< Desired number of concurrent -- TCP accepts */ -- int ntcpcurrent; /*%< Current ditto, locked */ -+ int32_t ntcpaccepting; /*%< Number of clients -+ ready to accept new -+ TCP connections on this -+ interface */ -+ int32_t ntcpactive; /*%< Number of clients -+ servicing TCP queries -+ (whether accepting or -+ connected) */ - int nudpdispatch; /*%< Number of UDP dispatches */ - ns_clientmgr_t * clientmgr; /*%< Client manager. */ - ISC_LINK(ns_interface_t) link; -diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c -index 4aee47a..e3f8cee 100644 ---- a/bin/named/interfacemgr.c -+++ b/bin/named/interfacemgr.c -@@ -380,8 +380,8 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, - * connections will be handled in parallel even though there is - * only one client initially. - */ -- ifp->ntcptarget = 1; -- ifp->ntcpcurrent = 0; -+ ifp->ntcpaccepting = 0; -+ ifp->ntcpactive = 0; - ifp->nudpdispatch = 0; - - ISC_LINK_INIT(ifp, link); -@@ -510,9 +510,7 @@ ns_interface_accepttcp(ns_interface_t *ifp) { - */ - (void)isc_socket_filter(ifp->tcpsocket, "dataready"); - -- result = ns_clientmgr_createclients(ifp->clientmgr, -- ifp->ntcptarget, ifp, -- ISC_TRUE); -+ result = ns_clientmgr_createclients(ifp->clientmgr, 1, ifp, ISC_TRUE); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "TCP ns_clientmgr_createclients(): %s", -diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml -index af194d9..aa567aa 100644 ---- a/doc/arm/Bv9ARM-book.xml -+++ b/doc/arm/Bv9ARM-book.xml -@@ -8067,7 +8067,8 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; - - The number of file descriptors reserved for TCP, stdio, - etc. This needs to be big enough to cover the number of -- interfaces named listens on, tcp-clients as well as -+ interfaces named listens on plus -+ tcp-clients, as well as - to provide room for outgoing TCP queries and incoming zone - transfers. The default is 512. - The minimum value is 128 and the -diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h -index 7b0d0d9..bb1a927 100644 ---- a/lib/isc/include/isc/quota.h -+++ b/lib/isc/include/isc/quota.h -@@ -107,6 +107,13 @@ isc_quota_attach(isc_quota_t *quota, isc_quota_t **p); - * quota if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA). - */ - -+isc_result_t -+isc_quota_force(isc_quota_t *quota, isc_quota_t **p); -+/*%< -+ * Like isc_quota_attach, but will attach '*p' to the quota -+ * even if the hard quota has been exceeded. -+ */ -+ - void - isc_quota_detach(isc_quota_t **p); - /*%< -diff --git a/lib/isc/quota.c b/lib/isc/quota.c -index 5e5c50c..ca4c478 100644 ---- a/lib/isc/quota.c -+++ b/lib/isc/quota.c -@@ -81,20 +81,39 @@ isc_quota_release(isc_quota_t *quota) { - UNLOCK("a->lock); - } - --isc_result_t --isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) --{ -+static isc_result_t -+doattach(isc_quota_t *quota, isc_quota_t **p, isc_boolean_t force) { - isc_result_t result; -- INSIST(p != NULL && *p == NULL); -+ REQUIRE(p != NULL && *p == NULL); -+ - result = isc_quota_reserve(quota); -- if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) -+ if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) { -+ *p = quota; -+ } else if (result == ISC_R_QUOTA && force) { -+ /* attach anyway */ -+ LOCK("a->lock); -+ quota->used++; -+ UNLOCK("a->lock); -+ - *p = quota; -+ result = ISC_R_SUCCESS; -+ } -+ - return (result); - } - -+isc_result_t -+isc_quota_attach(isc_quota_t *quota, isc_quota_t **p) { -+ return (doattach(quota, p, ISC_FALSE)); -+} -+ -+isc_result_t -+isc_quota_force(isc_quota_t *quota, isc_quota_t **p) { -+ return (doattach(quota, p, ISC_TRUE)); -+} -+ - void --isc_quota_detach(isc_quota_t **p) --{ -+isc_quota_detach(isc_quota_t **p) { - INSIST(p != NULL && *p != NULL); - isc_quota_release(*p); - *p = NULL; --- -2.20.1 - diff --git a/SOURCES/bind99-ISC-Bugs-34738.patch b/SOURCES/bind99-ISC-Bugs-34738.patch deleted file mode 100644 index c866ac4..0000000 --- a/SOURCES/bind99-ISC-Bugs-34738.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 18df9e628ea10c7d607f43fcfd935e7924731f24 Mon Sep 17 00:00:00 2001 -From: Evan Hunt -Date: Mon, 9 Sep 2013 22:12:47 -0700 -Subject: [PATCH] [master] strdup journal filename - -3646. [bug] Journal filename string could be set incorrectly, - causing garbage in log messages. [RT #34738] ---- - lib/dns/journal.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/lib/dns/journal.c b/lib/dns/journal.c -index 08aabd5..46a52e1 100644 ---- a/lib/dns/journal.c -+++ b/lib/dns/journal.c -@@ -307,7 +307,7 @@ struct dns_journal { - unsigned int magic; /*%< JOUR */ - isc_mem_t *mctx; /*%< Memory context */ - journal_state_t state; -- const char *filename; /*%< Journal file name */ -+ char *filename; /*%< Journal file name */ - FILE * fp; /*%< File handle */ - isc_offset_t offset; /*%< Current file offset */ - journal_header_t header; /*%< In-core journal header */ -@@ -573,10 +573,13 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, - isc_mem_attach(mctx, &j->mctx); - j->state = JOURNAL_STATE_INVALID; - j->fp = NULL; -- j->filename = filename; -+ j->filename = isc_mem_strdup(mctx, filename); - j->index = NULL; - j->rawindex = NULL; - -+ if (j->filename == NULL) -+ FAIL(ISC_R_NOMEMORY); -+ - result = isc_stdio_open(j->filename, write ? "rb+" : "rb", &fp); - - if (result == ISC_R_FILENOTFOUND) { -@@ -679,6 +682,8 @@ journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write, - sizeof(journal_rawpos_t)); - j->index = NULL; - } -+ if (j->filename != NULL) -+ isc_mem_free(j->mctx, j->filename); - if (j->fp != NULL) - (void)isc_stdio_close(j->fp); - isc_mem_putanddetach(&j->mctx, j, sizeof(*j)); -@@ -1242,7 +1247,8 @@ dns_journal_destroy(dns_journal_t **journalp) { - isc_mem_put(j->mctx, j->it.target.base, j->it.target.length); - if (j->it.source.base != NULL) - isc_mem_put(j->mctx, j->it.source.base, j->it.source.length); -- -+ if (j->filename != NULL) -+ isc_mem_free(j->mctx, j->filename); - if (j->fp != NULL) - (void)isc_stdio_close(j->fp); - j->magic = 0; --- -1.8.3.1 - diff --git a/SOURCES/bind99-ISC-Bugs-34870-v3.patch b/SOURCES/bind99-ISC-Bugs-34870-v3.patch deleted file mode 100644 index 2869213..0000000 --- a/SOURCES/bind99-ISC-Bugs-34870-v3.patch +++ /dev/null @@ -1,213 +0,0 @@ -diff -up bind-9.9.4/bin/dig/dighost.c.send_buffers bind-9.9.4/bin/dig/dighost.c ---- bind-9.9.4/bin/dig/dighost.c.send_buffers 2013-10-31 14:22:20.296811613 +0100 -+++ bind-9.9.4/bin/dig/dighost.c 2013-10-31 14:57:00.336400190 +0100 -@@ -194,6 +194,7 @@ isc_boolean_t validated = ISC_TRUE; - isc_entropy_t *entp = NULL; - isc_mempool_t *commctx = NULL; - isc_boolean_t debugging = ISC_FALSE; -+isc_boolean_t debugtiming = ISC_FALSE; - isc_boolean_t memdebugging = ISC_FALSE; - char *progname = NULL; - isc_mutex_t lookup_lock; -@@ -553,6 +554,12 @@ debug(const char *format, ...) { - - if (debugging) { - fflush(stdout); -+ if (debugtiming) { -+ struct timeval tv; -+ (void)gettimeofday(&tv, NULL); -+ fprintf(stderr, "%ld.%06ld: ", (long)tv.tv_sec, -+ (long)tv.tv_usec); -+ } - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); -@@ -2416,8 +2423,10 @@ send_done(isc_task_t *_task, isc_event_t - - for (b = ISC_LIST_HEAD(sevent->bufferlist); - b != NULL; -- b = ISC_LIST_HEAD(sevent->bufferlist)) -+ b = ISC_LIST_HEAD(sevent->bufferlist)) { - ISC_LIST_DEQUEUE(sevent->bufferlist, b, link); -+ isc_mem_free(mctx, b); -+ } - - query = event->ev_arg; - query->waiting_senddone = ISC_FALSE; -@@ -2609,6 +2618,17 @@ send_tcp_connect(dig_query_t *query) { - } - } - -+static isc_buffer_t * -+clone_buffer(isc_buffer_t *source) { -+ isc_buffer_t *buffer; -+ buffer = isc_mem_allocate(mctx, sizeof(*buffer)); -+ if (buffer == NULL) -+ fatal("memory allocation failure in %s:%d", -+ __FILE__, __LINE__); -+ *buffer = *source; -+ return (buffer); -+} -+ - /*% - * Send a UDP packet to the remote nameserver, possible starting the - * recv action as well. Also make sure that the timer is running and -@@ -2618,6 +2638,7 @@ static void - send_udp(dig_query_t *query) { - dig_lookup_t *l = NULL; - isc_result_t result; -+ isc_buffer_t *sendbuf; - - debug("send_udp(%p)", query); - -@@ -2664,14 +2685,16 @@ send_udp(dig_query_t *query) { - debug("recvcount=%d", recvcount); - } - ISC_LIST_INIT(query->sendlist); -- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link); -+ sendbuf = clone_buffer(&query->sendbuf); -+ ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link); - debug("sending a request"); - TIME_NOW(&query->time_sent); - INSIST(query->sock != NULL); - query->waiting_senddone = ISC_TRUE; -- result = isc_socket_sendtov(query->sock, &query->sendlist, -- global_task, send_done, query, -- &query->sockaddr, NULL); -+ result = isc_socket_sendtov2(query->sock, &query->sendlist, -+ global_task, send_done, query, -+ &query->sockaddr, NULL, -+ ISC_SOCKFLAG_NORETRY); - check_result(result, "isc_socket_sendtov"); - sendcount++; - } -@@ -2838,6 +2861,7 @@ static void - launch_next_query(dig_query_t *query, isc_boolean_t include_question) { - isc_result_t result; - dig_lookup_t *l; -+ isc_buffer_t *buffer; - - INSIST(!free_now); - -@@ -2861,9 +2885,15 @@ launch_next_query(dig_query_t *query, is - isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used); - ISC_LIST_INIT(query->sendlist); - ISC_LINK_INIT(&query->slbuf, link); -- ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link); -- if (include_question) -- ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link); -+ if (!query->first_soa_rcvd) { -+ buffer = clone_buffer(&query->slbuf); -+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link); -+ if (include_question) { -+ buffer = clone_buffer(&query->sendbuf); -+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link); -+ } -+ } -+ - ISC_LINK_INIT(&query->lengthbuf, link); - ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link); - -diff -up bind-9.9.4/bin/dig/host.c.send_buffers bind-9.9.4/bin/dig/host.c ---- bind-9.9.4/bin/dig/host.c.send_buffers 2013-10-31 14:22:20.270811568 +0100 -+++ bind-9.9.4/bin/dig/host.c 2013-10-31 14:22:20.328811669 +0100 -@@ -638,6 +638,8 @@ pre_parse_args(int argc, char **argv) { - case 'w': break; - case 'C': break; - case 'D': -+ if (debugging) -+ debugtiming = ISC_TRUE; - debugging = ISC_TRUE; - break; - case 'N': break; -diff -up bind-9.9.4/bin/dig/include/dig/dig.h.send_buffers bind-9.9.4/bin/dig/include/dig/dig.h ---- bind-9.9.4/bin/dig/include/dig/dig.h.send_buffers 2013-10-31 14:22:20.270811568 +0100 -+++ bind-9.9.4/bin/dig/include/dig/dig.h 2013-10-31 14:22:20.328811669 +0100 -@@ -275,7 +275,7 @@ extern isc_boolean_t validated; - extern isc_taskmgr_t *taskmgr; - extern isc_task_t *global_task; - extern isc_boolean_t free_now; --extern isc_boolean_t debugging, memdebugging; -+extern isc_boolean_t debugging, debugtiming, memdebugging; - - extern char *progname; - extern int tries; -diff -up bind-9.9.4/lib/isc/include/isc/namespace.h.send_buffers bind-9.9.4/lib/isc/include/isc/namespace.h ---- bind-9.9.4/lib/isc/include/isc/namespace.h.send_buffers 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/lib/isc/include/isc/namespace.h 2013-10-31 14:22:20.328811669 +0100 -@@ -106,6 +106,7 @@ - #define isc_socket_sendv isc__socket_sendv - #define isc_socket_sendtov isc__socket_sendtov - #define isc_socket_sendto2 isc__socket_sendto2 -+#define isc_socket_sendtov2 isc__socket_sendtov2 - #define isc_socket_cleanunix isc__socket_cleanunix - #define isc_socket_permunix isc__socket_permunix - #define isc_socket_bind isc__socket_bind -diff -up bind-9.9.4/lib/isc/include/isc/socket.h.send_buffers bind-9.9.4/lib/isc/include/isc/socket.h ---- bind-9.9.4/lib/isc/include/isc/socket.h.send_buffers 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/lib/isc/include/isc/socket.h 2013-10-31 14:22:20.328811669 +0100 -@@ -866,6 +866,11 @@ isc_socket_sendtov(isc_socket_t *sock, i - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); - isc_result_t -+isc_socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist, -+ isc_task_t *task, isc_taskaction_t action, const void *arg, -+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, -+ unsigned int flags); -+isc_result_t - isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, -diff -up bind-9.9.4/lib/isc/unix/socket.c.send_buffers bind-9.9.4/lib/isc/unix/socket.c ---- bind-9.9.4/lib/isc/unix/socket.c.send_buffers 2013-10-31 14:22:20.293811608 +0100 -+++ bind-9.9.4/lib/isc/unix/socket.c 2013-10-31 14:22:20.330811673 +0100 -@@ -510,6 +510,11 @@ isc__socket_sendtov(isc_socket_t *sock, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); - ISC_SOCKETFUNC_SCOPE isc_result_t -+isc__socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist, -+ isc_task_t *task, isc_taskaction_t action, const void *arg, -+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, -+ unsigned int flags); -+ISC_SOCKETFUNC_SCOPE isc_result_t - isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, -@@ -4796,15 +4801,25 @@ ISC_SOCKETFUNC_SCOPE isc_result_t - isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg) - { -- return (isc__socket_sendtov(sock, buflist, task, action, arg, NULL, -- NULL)); -+ return (isc__socket_sendtov2(sock, buflist, task, action, arg, NULL, -+ NULL, 0)); - } - - ISC_SOCKETFUNC_SCOPE isc_result_t --isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist, -+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) - { -+ return (isc__socket_sendtov2(sock, buflist, task, action, arg, address, -+ pktinfo, 0)); -+} -+ -+ISC_SOCKETFUNC_SCOPE isc_result_t -+isc__socket_sendtov2(isc_socket_t *sock0, isc_bufferlist_t *buflist, -+ isc_task_t *task, isc_taskaction_t action, const void *arg, -+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, -+ unsigned int flags) -+{ - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_socketevent_t *dev; - isc__socketmgr_t *manager; -@@ -4837,7 +4852,7 @@ isc__socket_sendtov(isc_socket_t *sock0, - buffer = ISC_LIST_HEAD(*buflist); - } - -- return (socket_send(sock, dev, task, address, pktinfo, 0)); -+ return (socket_send(sock, dev, task, address, pktinfo, flags)); - } - - ISC_SOCKETFUNC_SCOPE isc_result_t diff --git a/SOURCES/bind99-ISC-Bugs-35073.patch b/SOURCES/bind99-ISC-Bugs-35073.patch deleted file mode 100644 index c8be3ed..0000000 --- a/SOURCES/bind99-ISC-Bugs-35073.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c -index 486c102..dc12a85 100644 ---- a/bin/nsupdate/nsupdate.c -+++ b/bin/nsupdate/nsupdate.c -@@ -1566,16 +1566,20 @@ evaluate_realm(char *cmdline) { - #ifdef GSSAPI - char *word; - char buf[1024]; -+ int n; - -- word = nsu_strsep(&cmdline, " \t\r\n"); -- if (word == NULL || *word == 0) { -- if (realm != NULL) -- isc_mem_free(mctx, realm); -+ if (realm != NULL) { -+ isc_mem_free(mctx, realm); - realm = NULL; -- return (STATUS_MORE); - } - -- snprintf(buf, sizeof(buf), "@%s", word); -+ word = nsu_strsep(&cmdline, " \t\r\n"); -+ if (word == NULL || *word == 0) -+ return (STATUS_MORE); -+ -+ n = snprintf(buf, sizeof(buf), "@%s", word); -+ if (n < 0 || (size_t)n >= sizeof(buf)) -+ fatal("realm is too long"); - realm = isc_mem_strdup(mctx, buf); - if (realm == NULL) - fatal("out of memory"); diff --git a/SOURCES/bind99-ISC-Bugs-35080.patch b/SOURCES/bind99-ISC-Bugs-35080.patch deleted file mode 100644 index 14c383f..0000000 --- a/SOURCES/bind99-ISC-Bugs-35080.patch +++ /dev/null @@ -1,42 +0,0 @@ -commit 3a2ea636103eaf40404fb82f228605d384c36434 -Author: Mark Andrews -Date: Tue Dec 17 09:08:59 2013 +1100 - - 3692. [bug] Two calls to dns_db_getoriginnode were fatal if there - was no data at the node. [RT #35080] - - (cherry picked from commit 161e803a5608956271d8120be37a1b383d14b647) - -diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c -index 2dd4aa0..941b77e 100644 ---- a/lib/dns/rbtdb.c -+++ b/lib/dns/rbtdb.c -@@ -1638,8 +1638,11 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, - - nodelock = &rbtdb->node_locks[bucket]; - -+#define KEEP_NODE(n, r) \ -+ ((n)->data != NULL || (n)->down != NULL || (n) == (r)->origin_node) -+ - /* Handle easy and typical case first. */ -- if (!node->dirty && (node->data != NULL || node->down != NULL)) { -+ if (!node->dirty && KEEP_NODE(node, rbtdb)) { - dns_rbtnode_refdecrement(node, &nrefs); - INSIST((int)nrefs >= 0); - if (nrefs == 0) { -@@ -1708,12 +1711,11 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, - isc_refcount_decrement(&nodelock->references, &refs); - INSIST((int)refs >= 0); - -- /* -- * XXXDCL should this only be done for cache zones? -- */ -- if (node->data != NULL || node->down != NULL) -+ if (KEEP_NODE(node, rbtdb)) - goto restore_locks; - -+#undef KEEP_NODE -+ - if (write_locked) { - /* - * We can now delete the node. diff --git a/SOURCES/bind99-automatic-interface-scanning-rh1294506.patch b/SOURCES/bind99-automatic-interface-scanning-rh1294506.patch deleted file mode 100644 index 0aec0c5..0000000 --- a/SOURCES/bind99-automatic-interface-scanning-rh1294506.patch +++ /dev/null @@ -1,685 +0,0 @@ -From 5013230b31da1d94ce5682e5c5c38011da744971 Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Wed, 11 May 2016 15:17:55 +0200 -Subject: [PATCH] Added support for automatic interface scan when new address - is assigned to any interface - -Signed-off-by: Tomas Hozza ---- - bin/named/config.c | 1 + - bin/named/control.c | 3 + - bin/named/include/named/control.h | 1 + - bin/named/include/named/server.h | 8 +++ - bin/named/interfacemgr.c | 144 ++++++++++++++++++++++++++++++++++++++ - bin/named/named.conf.docbook | 1 + - bin/named/server.c | 31 +++++++- - bin/named/statschannel.c | 5 ++ - bin/rndc/rndc.c | 1 + - bin/rndc/rndc.docbook | 12 ++++ - config.h.in | 12 ++++ - configure.in | 5 +- - doc/arm/Bv9ARM-book.xml | 22 +++++- - lib/isc/include/isc/socket.h | 10 ++- - lib/isc/unix/socket.c | 59 ++++++++++++++++ - lib/isccfg/namedconf.c | 1 + - 16 files changed, 310 insertions(+), 6 deletions(-) - -diff --git a/bin/named/config.c b/bin/named/config.c -index f6d0263..b43c0fc 100644 ---- a/bin/named/config.c -+++ b/bin/named/config.c -@@ -52,6 +52,7 @@ - /*% default configuration */ - static char defaultconf[] = "\ - options {\n\ -+ automatic-interface-scan yes;\n\ - # blackhole {none;};\n" - #ifndef WIN32 - " coresize default;\n\ -diff --git a/bin/named/control.c b/bin/named/control.c -index 06eadce..86fa691 100644 ---- a/bin/named/control.c -+++ b/bin/named/control.c -@@ -185,6 +185,9 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { - command_compare(command, NS_COMMAND_THAW)) { - result = ns_server_freeze(ns_g_server, ISC_FALSE, command, - text); -+ } else if (command_compare(command, NS_COMMAND_SCAN)) { -+ result = ISC_R_SUCCESS; -+ ns_server_scan_interfaces(ns_g_server); - } else if (command_compare(command, NS_COMMAND_SYNC)) { - result = ns_server_sync(ns_g_server, command, text); - } else if (command_compare(command, NS_COMMAND_RECURSING)) { -diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h -index d730a83..52ed583 100644 ---- a/bin/named/include/named/control.h -+++ b/bin/named/include/named/control.h -@@ -59,6 +59,7 @@ - #define NS_COMMAND_NULL "null" - #define NS_COMMAND_NOTIFY "notify" - #define NS_COMMAND_VALIDATION "validation" -+#define NS_COMMAND_SCAN "scan" - #define NS_COMMAND_SIGN "sign" - #define NS_COMMAND_LOADKEYS "loadkeys" - #define NS_COMMAND_ADDZONE "addzone" -diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h -index ff0bfd3..83622f4 100644 ---- a/bin/named/include/named/server.h -+++ b/bin/named/include/named/server.h -@@ -37,6 +37,7 @@ - #define NS_EVENTCLASS ISC_EVENTCLASS(0x4E43) - #define NS_EVENT_RELOAD (NS_EVENTCLASS + 0) - #define NS_EVENT_CLIENTCONTROL (NS_EVENTCLASS + 1) -+#define NS_EVENT_IFSCAN (NS_EVENTCLASS + 2) - - /*% - * Name server state. Better here than in lots of separate global variables. -@@ -114,6 +115,7 @@ struct ns_server { - dns_name_t *session_keyname; - unsigned int session_keyalg; - isc_uint16_t session_keybits; -+ isc_boolean_t interface_auto; - }; - - #define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R') -@@ -201,6 +203,12 @@ ns_server_reloadwanted(ns_server_t *server); - */ - - void -+ns_server_scan_interfaces(ns_server_t *server); -+/*%< -+ * Trigger a interface scan. -+ */ -+ -+void - ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush); - /*%< - * Inform the server that the zones should be flushed to disk on shutdown. -diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c -index 4f6b0f3..a9aa4a4 100644 ---- a/bin/named/interfacemgr.c -+++ b/bin/named/interfacemgr.c -@@ -33,6 +33,28 @@ - #include - #include - #include -+#include -+ -+#ifdef HAVE_NET_ROUTE_H -+#include -+#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR) -+#define USE_ROUTE_SOCKET 1 -+#define ROUTE_SOCKET_PROTOCOL PF_ROUTE -+#define MSGHDR rt_msghdr -+#define MSGTYPE rtm_type -+#endif -+#endif -+ -+#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) -+#include -+#include -+#if defined(RTM_NEWADDR) && defined(RTM_DELADDR) -+#define USE_ROUTE_SOCKET 1 -+#define ROUTE_SOCKET_PROTOCOL PF_NETLINK -+#define MSGHDR nlmsghdr -+#define MSGTYPE nlmsg_type -+#endif -+#endif - - #define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G') - #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC) -@@ -55,6 +77,11 @@ struct ns_interfacemgr { - dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */ - ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */ - ISC_LIST(isc_sockaddr_t) listenon; -+#ifdef USE_ROUTE_SOCKET -+ isc_task_t * task; -+ isc_socket_t * route; -+ unsigned char buf[2048]; -+#endif - }; - - static void -@@ -63,6 +90,71 @@ purge_old_interfaces(ns_interfacemgr_t *mgr); - static void - clearlistenon(ns_interfacemgr_t *mgr); - -+#ifdef USE_ROUTE_SOCKET -+static void -+route_event(isc_task_t *task, isc_event_t *event) { -+ isc_socketevent_t *sevent = NULL; -+ ns_interfacemgr_t *mgr = NULL; -+ isc_region_t r; -+ isc_result_t result; -+ struct MSGHDR *rtm; -+ -+ UNUSED(task); -+ -+ REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); -+ mgr = event->ev_arg; -+ sevent = (isc_socketevent_t *)event; -+ -+ if (sevent->result != ISC_R_SUCCESS) { -+ if (sevent->result != ISC_R_CANCELED) -+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, -+ "automatic interface scanning " -+ "terminated: %s", -+ isc_result_totext(sevent->result)); -+ ns_interfacemgr_detach(&mgr); -+ isc_event_free(&event); -+ return; -+ } -+ -+ rtm = (struct MSGHDR *)mgr->buf; -+#ifdef RTM_VERSION -+ if (rtm->rtm_version != RTM_VERSION) { -+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, -+ "automatic interface rescanning disabled: " -+ "rtm->rtm_version mismatch (%u != %u) " -+ "recompile required", rtm->rtm_version, -+ RTM_VERSION); -+ isc_task_detach(&mgr->task); -+ isc_socket_detach(&mgr->route); -+ ns_interfacemgr_detach(&mgr); -+ isc_event_free(&event); -+ return; -+ } -+#endif -+ -+ switch (rtm->MSGTYPE) { -+ case RTM_NEWADDR: -+ case RTM_DELADDR: -+ if (ns_g_server->interface_auto) -+ ns_server_scan_interfaces(ns_g_server); -+ break; -+ default: -+ break; -+ } -+ -+ /* -+ * Look for next route event. -+ */ -+ r.base = mgr->buf; -+ r.length = sizeof(mgr->buf); -+ result = isc_socket_recv(mgr->route, &r, 1, mgr->task, -+ route_event, mgr); -+ if (result != ISC_R_SUCCESS) -+ ns_interfacemgr_detach(&mgr); -+ isc_event_free(&event); -+} -+#endif -+ - isc_result_t - ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, - isc_socketmgr_t *socketmgr, -@@ -112,11 +204,52 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, - mgr->aclenv.geoip = ns_g_geoip; - #endif - -+#ifdef USE_ROUTE_SOCKET -+ mgr->route = NULL; -+ result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL, -+ isc_sockettype_raw, &mgr->route); -+ switch (result) { -+ case ISC_R_NOPERM: -+ case ISC_R_SUCCESS: -+ case ISC_R_NOTIMPLEMENTED: -+ case ISC_R_FAMILYNOSUPPORT: -+ break; -+ default: -+ goto cleanup_aclenv; -+ } -+ -+ mgr->task = NULL; -+ if (mgr->route != NULL) { -+ result = isc_task_create(taskmgr, 0, &mgr->task); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup_route; -+ } -+ mgr->references = (mgr->route != NULL) ? 2 : 1; -+#else - mgr->references = 1; -+#endif - mgr->magic = IFMGR_MAGIC; - *mgrp = mgr; -+ -+#ifdef USE_ROUTE_SOCKET -+ if (mgr->route != NULL) { -+ isc_region_t r = { mgr->buf, sizeof(mgr->buf) }; -+ -+ result = isc_socket_recv(mgr->route, &r, 1, mgr->task, -+ route_event, mgr); -+ if (result != ISC_R_SUCCESS) -+ ns_interfacemgr_detach(&mgr); -+ } -+#endif - return (ISC_R_SUCCESS); - -+#ifdef USE_ROUTE_SOCKET -+ cleanup_route: -+ if (mgr->route != NULL) -+ isc_socket_detach(&mgr->route); -+ cleanup_aclenv: -+ dns_aclenv_destroy(&mgr->aclenv); -+#endif - cleanup_listenon: - ns_listenlist_detach(&mgr->listenon4); - ns_listenlist_detach(&mgr->listenon6); -@@ -128,6 +261,13 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, - static void - ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { - REQUIRE(NS_INTERFACEMGR_VALID(mgr)); -+ -+#ifdef USE_ROUTE_SOCKET -+ if (mgr->route != NULL) -+ isc_socket_detach(&mgr->route); -+ if (mgr->task != NULL) -+ isc_task_detach(&mgr->task); -+#endif - dns_aclenv_destroy(&mgr->aclenv); - ns_listenlist_detach(&mgr->listenon4); - ns_listenlist_detach(&mgr->listenon6); -@@ -179,6 +319,10 @@ ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) { - * consider all interfaces "old". - */ - mgr->generation++; -+#ifdef USE_ROUTE_SOCKET -+ if (mgr->route != NULL) -+ isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV); -+#endif - purge_old_interfaces(mgr); - } - -diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook -index 8c23e52..a8cd31e 100644 ---- a/bin/named/named.conf.docbook -+++ b/bin/named/named.conf.docbook -@@ -373,6 +373,7 @@ options { - zero-no-soa-ttl boolean; - zero-no-soa-ttl-cache boolean; - dnssec-secure-to-insecure boolean; -+ automatic-interface-scan boolean; - deny-answer-addresses { - address_match_list - } except-from { namelist } ; -diff --git a/bin/named/server.c b/bin/named/server.c -index 24b31c3..942bab6 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -4485,8 +4485,9 @@ adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) { - } - - /* -- * This event callback is invoked to do periodic network -- * interface scanning. -+ * This event callback is invoked to do periodic network interface -+ * scanning. It is also called by ns_server_scan_interfaces(), -+ * invoked by "rndc scan" - */ - static void - interface_timer_tick(isc_task_t *task, isc_event_t *event) { -@@ -4494,7 +4495,14 @@ interface_timer_tick(isc_task_t *task, isc_event_t *event) { - ns_server_t *server = (ns_server_t *) event->ev_arg; - INSIST(task == server->task); - UNUSED(task); -+ -+ if (event->ev_type == NS_EVENT_IFSCAN) -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), -+ "automatic interface rescan"); -+ - isc_event_free(&event); -+ - /* - * XXX should scan interfaces unlocked and get exclusive access - * only to replace ACLs. -@@ -5419,6 +5427,14 @@ load_configuration(const char *filename, ns_server_t *server, - server->interface_interval = interface_interval; - - /* -+ * Enable automatic interface scans. -+ */ -+ obj = NULL; -+ result = ns_config_get(maps, "automatic-interface-scan", &obj); -+ INSIST(result == ISC_R_SUCCESS); -+ server->interface_auto = cfg_obj_asboolean(obj); -+ -+ /* - * Configure the dialup heartbeat timer. - */ - obj = NULL; -@@ -6637,6 +6653,17 @@ ns_server_reloadwanted(ns_server_t *server) { - UNLOCK(&server->reload_event_lock); - } - -+void -+ns_server_scan_interfaces(ns_server_t *server) { -+ isc_event_t *event; -+ -+ event = isc_event_allocate(ns_g_mctx, server, NS_EVENT_IFSCAN, -+ interface_timer_tick, server, -+ sizeof(isc_event_t)); -+ if (event != NULL) -+ isc_task_send(server->task, &event); -+} -+ - static char * - next_token(char **stringp, const char *delim) { - char *res; -diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c -index 37e98a8..b985f62 100644 ---- a/bin/named/statschannel.c -+++ b/bin/named/statschannel.c -@@ -341,6 +341,7 @@ init_desc(void) { - SET_SOCKSTATDESC(tcp4open, "TCP/IPv4 sockets opened", "TCP4Open"); - SET_SOCKSTATDESC(tcp6open, "TCP/IPv6 sockets opened", "TCP6Open"); - SET_SOCKSTATDESC(unixopen, "Unix domain sockets opened", "UnixOpen"); -+ SET_SOCKSTATDESC(rawopen, "Raw sockets opened", "RawOpen"); - SET_SOCKSTATDESC(udp4openfail, "UDP/IPv4 socket open failures", - "UDP4OpenFail"); - SET_SOCKSTATDESC(udp6openfail, "UDP/IPv6 socket open failures", -@@ -351,6 +352,8 @@ init_desc(void) { - "TCP6OpenFail"); - SET_SOCKSTATDESC(unixopenfail, "Unix domain socket open failures", - "UnixOpenFail"); -+ SET_SOCKSTATDESC(rawopenfail, "Raw socket open failures", -+ "RawOpenFail"); - SET_SOCKSTATDESC(udp4close, "UDP/IPv4 sockets closed", "UDP4Close"); - SET_SOCKSTATDESC(udp6close, "UDP/IPv6 sockets closed", "UDP6Close"); - SET_SOCKSTATDESC(tcp4close, "TCP/IPv4 sockets closed", "TCP4Close"); -@@ -358,6 +361,7 @@ init_desc(void) { - SET_SOCKSTATDESC(unixclose, "Unix domain sockets closed", "UnixClose"); - SET_SOCKSTATDESC(fdwatchclose, "FDwatch sockets closed", - "FDWatchClose"); -+ SET_SOCKSTATDESC(rawclose, "Raw sockets closed", "RawClose"); - SET_SOCKSTATDESC(udp4bindfail, "UDP/IPv4 socket bind failures", - "UDP4BindFail"); - SET_SOCKSTATDESC(udp6bindfail, "UDP/IPv6 socket bind failures", -@@ -424,6 +428,7 @@ init_desc(void) { - "UnixRecvErr"); - SET_SOCKSTATDESC(fdwatchrecvfail, "FDwatch recv errors", - "FDwatchRecvErr"); -+ SET_SOCKSTATDESC(rawrecvfail, "Raw recv errors", "RawRecvErr"); - INSIST(i == isc_sockstatscounter_max); - - /* Initialize DNSSEC statistics */ -diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c -index 9a007e2..be198b1 100644 ---- a/bin/rndc/rndc.c -+++ b/bin/rndc/rndc.c -@@ -160,6 +160,7 @@ command is one of the following:\n\ - Add zone to given view. Requires new-zone-file option.\n\ - delzone [\"file\"] zone [class [view]]\n\ - Removes zone from given view. Requires new-zone-file option.\n\ -+ scan Scan available network interfaces for changes.\n\ - signing -list zone [class [view]]\n\ - List the private records showing the state of DNSSEC\n\ - signing in the given zone.\n\ -diff --git a/bin/rndc/rndc.docbook b/bin/rndc/rndc.docbook -index 1789aaa..5b37b7f 100644 ---- a/bin/rndc/rndc.docbook -+++ b/bin/rndc/rndc.docbook -@@ -330,6 +330,18 @@ - - - -+ scan -+ -+ -+ Scan the list of available network interfaces -+ for changes, without performing a full -+ reconfig or waiting for the -+ interface-interval timer. -+ -+ -+ -+ -+ - sync -clean zone class view - - -diff --git a/config.h.in b/config.h.in -index 6ed8381..3515f69 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -280,6 +280,12 @@ int sigwait(const unsigned int *set, int *sig); - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_CAPABILITY_H - -+/* Define to 1 if you have the header file. */ -+#undef HAVE_LINUX_NETLINK_H -+ -+/* Define to 1 if you have the header file. */ -+#undef HAVE_LINUX_RTNETLINK_H -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_TYPES_H - -@@ -295,6 +301,9 @@ int sigwait(const unsigned int *set, int *sig); - /* Define to 1 if you have the header file. */ - #undef HAVE_NET_IF6_H - -+/* Define to 1 if you have the header file. */ -+#undef HAVE_NET_ROUTE_H -+ - /* Define if your OpenSSL version supports ECDSA. */ - #undef HAVE_OPENSSL_ECDSA - -@@ -358,6 +367,9 @@ int sigwait(const unsigned int *set, int *sig); - /* Define to 1 if you have the header file. */ - #undef HAVE_SYS_SELECT_H - -+/* Define to 1 if you have the header file. */ -+#undef HAVE_SYS_SOCKET_H -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_SYS_SOCKIO_H - -diff --git a/configure.in b/configure.in -index d72093f..38e626d 100644 ---- a/configure.in -+++ b/configure.in -@@ -375,11 +375,14 @@ fi - - AC_HEADER_STDC - --AC_CHECK_HEADERS(fcntl.h regex.h sys/time.h unistd.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h,,, -+AC_CHECK_HEADERS(fcntl.h regex.h sys/time.h unistd.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h sys/socket.h net/route.h linux/netlink.h linux/rtnetlink.h,,, - [$ac_includes_default - #ifdef HAVE_SYS_PARAM_H - # include - #endif -+#ifdef HAVE_SYS_SOCKET_H -+# include -+#endif - ]) - - AC_C_CONST -diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml -index 92c7b72..4c47d92 100644 ---- a/doc/arm/Bv9ARM-book.xml -+++ b/doc/arm/Bv9ARM-book.xml -@@ -4964,7 +4964,9 @@ badresp:1,adberr:0,findfail:0,valfail:0] - policy given | disabled | passthru | nxdomain | nodata | cname domain - recursive-only yes_or_no max-policy-ttl number ; - } recursive-only yes_or_no max-policy-ttl number -- break-dnssec yes_or_no min-ns-dots number ; -+ break-dnssec yes_or_no min-ns-dots number -+ automatic-interface-scan yes_or_no -+ ; - }; - - -@@ -5726,6 +5728,23 @@ options { - - - -+ automatic-interface-scan -+ -+ -+ If yes and supported by the OS, -+ automatically rescan network interfaces when the interface -+ addresses are added or removed. The default is -+ yes. -+ -+ -+ Currently the OS needs to support routing sockets for -+ automatic-interface-scan to be -+ supported. -+ -+ -+ -+ -+ - allow-new-zones - - -@@ -10494,6 +10513,7 @@ zone zone_name class allow-query-on { address_match_list }; - allow-transfer { address_match_list }; - allow-update-forwarding { address_match_list }; -+ automatic-interface-scan { yes_or_no }; - dnssec-update-mode ( maintain | no-resign ); - update-check-ksk yes_or_no; - dnssec-dnskey-kskonly yes_or_no; -diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h -index c5a753a..1cd90bb 100644 ---- a/lib/isc/include/isc/socket.h -+++ b/lib/isc/include/isc/socket.h -@@ -150,7 +150,12 @@ enum { - isc_sockstatscounter_unixrecvfail = 50, - isc_sockstatscounter_fdwatchrecvfail = 51, - -- isc_sockstatscounter_max = 52 -+ isc_sockstatscounter_rawopen = 52, -+ isc_sockstatscounter_rawopenfail = 53, -+ isc_sockstatscounter_rawclose = 54, -+ isc_sockstatscounter_rawrecvfail = 55, -+ -+ isc_sockstatscounter_max = 56 - }; - - /*** -@@ -221,7 +226,8 @@ typedef enum { - isc_sockettype_udp = 1, - isc_sockettype_tcp = 2, - isc_sockettype_unix = 3, -- isc_sockettype_fdwatch = 4 -+ isc_sockettype_fdwatch = 4, -+ isc_sockettype_raw = 5 - } isc_sockettype_t; - - /*@{*/ -diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c -index 82d0d16..cbc506b 100644 ---- a/lib/isc/unix/socket.c -+++ b/lib/isc/unix/socket.c -@@ -28,6 +28,11 @@ - #include - #include - -+#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) -+#include -+#include -+#endif -+ - #include - #include - #include -@@ -708,6 +713,18 @@ static const isc_statscounter_t fdwatchstatsindex[] = { - isc_sockstatscounter_fdwatchsendfail, - isc_sockstatscounter_fdwatchrecvfail - }; -+static const isc_statscounter_t rawstatsindex[] = { -+ isc_sockstatscounter_rawopen, -+ isc_sockstatscounter_rawopenfail, -+ isc_sockstatscounter_rawclose, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ isc_sockstatscounter_rawrecvfail, -+}; - - #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) || \ - defined(USE_WATCHER_THREAD) -@@ -1744,6 +1761,7 @@ doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) { - return (DOIO_EOF); - break; - case isc_sockettype_udp: -+ case isc_sockettype_raw: - break; - case isc_sockettype_fdwatch: - default: -@@ -2306,6 +2324,44 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock, - case isc_sockettype_unix: - sock->fd = socket(sock->pf, SOCK_STREAM, 0); - break; -+ case isc_sockettype_raw: -+ errno = EPFNOSUPPORT; -+ /* -+ * PF_ROUTE is a alias for PF_NETLINK on linux. -+ */ -+#if defined(PF_ROUTE) -+ if (sock->fd == -1 && sock->pf == PF_ROUTE) { -+#ifdef NETLINK_ROUTE -+ sock->fd = socket(sock->pf, SOCK_RAW, -+ NETLINK_ROUTE); -+#else -+ sock->fd = socket(sock->pf, SOCK_RAW, 0); -+#endif -+ if (sock->fd != -1) { -+#ifdef NETLINK_ROUTE -+ struct sockaddr_nl sa; -+ int n; -+ -+ /* -+ * Do an implicit bind. -+ */ -+ memset(&sa, 0, sizeof(sa)); -+ sa.nl_family = AF_NETLINK; -+ sa.nl_groups = RTMGRP_IPV4_IFADDR | -+ RTMGRP_IPV6_IFADDR; -+ n = bind(sock->fd, -+ (struct sockaddr *) &sa, -+ sizeof(sa)); -+ if (n < 0) { -+ close(sock->fd); -+ sock->fd = -1; -+ } -+#endif -+ sock->bound = 1; -+ } -+ } -+ #endif -+ break; - case isc_sockettype_fdwatch: - /* - * We should not be called for isc_sockettype_fdwatch -@@ -2602,6 +2658,9 @@ socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, - case isc_sockettype_unix: - sock->statsindex = unixstatsindex; - break; -+ case isc_sockettype_raw: -+ sock->statsindex = rawstatsindex; -+ break; - default: - INSIST(0); - } -diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c -index f5ff8e3..f49ff70 100644 ---- a/lib/isccfg/namedconf.c -+++ b/lib/isccfg/namedconf.c -@@ -931,6 +931,7 @@ bindkeys_clauses[] = { - */ - static cfg_clausedef_t - options_clauses[] = { -+ { "automatic-interface-scan", &cfg_type_boolean, 0 }, - { "avoid-v4-udp-ports", &cfg_type_bracketed_portlist, 0 }, - { "avoid-v6-udp-ports", &cfg_type_bracketed_portlist, 0 }, - { "bindkeys-file", &cfg_type_qstring, 0 }, --- -2.5.5 - diff --git a/SOURCES/bind99-coverity-fixes.patch b/SOURCES/bind99-coverity-fixes.patch deleted file mode 100644 index 0e60017..0000000 --- a/SOURCES/bind99-coverity-fixes.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 127701d9d32e568f09c775e722286e9c0b8c72ec Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Fri, 22 May 2015 16:56:25 +0200 -Subject: [PATCH] Fix coverity issues - -http://cov01.lab.eng.brq.redhat.com/covscanhub/waiving/9377/ -Signed-off-by: Tomas Hozza ---- - bin/named/server.c | 8 +++----- - lib/dns/dispatch.c | 5 +++-- - lib/dns/dst_api.c | 6 ++++++ - lib/dns/gen.c | 16 +++++++++++++++- - lib/dns/name.c | 8 ++------ - lib/dns/nsec3.c | 4 ++-- - lib/dns/rcode.c | 4 +++- - lib/isc/netaddr.c | 1 + - lib/isc/pk11.c | 21 ++++++++++++++------- - 9 files changed, 49 insertions(+), 24 deletions(-) - -diff --git a/bin/named/server.c b/bin/named/server.c -index 227c646..5e94660 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -8018,9 +8018,11 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text) { - dns_zone_t *zone = NULL; - char classstr[DNS_RDATACLASS_FORMATSIZE]; - char zonename[DNS_NAME_FORMATSIZE]; -- const char *vname, *sep, *msg = NULL, *arg; -+ const char *vname, *sep, *arg; - isc_boolean_t cleanup = ISC_FALSE; - -+ UNUSED(text); -+ - (void) next_token(&args, " \t"); - - arg = next_token(&args, " \t"); -@@ -8061,10 +8063,6 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text) { - result = synczone(zone, &cleanup); - isc_task_endexclusive(server->task); - -- if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) -- isc_buffer_putmem(text, (const unsigned char *)msg, -- strlen(msg) + 1); -- - view = dns_zone_getview(zone); - if (strcmp(view->name, "_default") == 0 || - strcmp(view->name, "_bind") == 0) -diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c -index 5063914..c93651d 100644 ---- a/lib/dns/dispatch.c -+++ b/lib/dns/dispatch.c -@@ -2278,9 +2278,10 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr, - - /* Create or adjust socket pool */ - if (mgr->spool != NULL) { -- if (maxrequests < DNS_DISPATCH_POOLSOCKS * 2) -+ if (maxrequests < DNS_DISPATCH_POOLSOCKS * 2) { - isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2); - isc_mempool_setfreemax(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2); -+ } - UNLOCK(&mgr->buffer_lock); - return (ISC_R_SUCCESS); - } -@@ -3765,7 +3766,7 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, - goto fail_alloc; - - dset->dispatches = isc_mem_get(mctx, sizeof(dns_dispatch_t *) * n); -- if (dset == NULL) { -+ if (dset->dispatches == NULL) { - result = ISC_R_NOMEMORY; - goto fail_lock; - } -diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c -index d96473f..e71f202 100644 ---- a/lib/dns/dst_api.c -+++ b/lib/dns/dst_api.c -@@ -1882,6 +1882,9 @@ dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { - #ifdef BIND9 - unsigned int flags = dst_entropy_flags; - -+ if (dst_entropy_pool == NULL) -+ return (ISC_R_FAILURE); -+ - if (len == 0) - return (ISC_R_SUCCESS); - -@@ -1914,6 +1917,9 @@ dst__entropy_status(void) { - unsigned char buf[32]; - static isc_boolean_t first = ISC_TRUE; - -+ if (dst_entropy_pool == NULL) -+ return (0); -+ - if (first) { - /* Someone believes RAND_status() initializes the PRNG */ - flags &= ~ISC_ENTROPY_GOODONLY; -diff --git a/lib/dns/gen.c b/lib/dns/gen.c -index 6b533dd..548f892 100644 ---- a/lib/dns/gen.c -+++ b/lib/dns/gen.c -@@ -335,10 +335,14 @@ insert_into_typenames(int type, const char *typename, const char *attr) { - typename); - exit(1); - } -+ - strncpy(ttn->typename, typename, sizeof(ttn->typename)); -- ttn->type = type; -+ ttn->typename[sizeof(ttn->typename) - 1] = '\0'; - - strncpy(ttn->macroname, ttn->typename, sizeof(ttn->macroname)); -+ ttn->macroname[sizeof(ttn->macroname) - 1] = '\0'; -+ -+ ttn->type = type; - c = strlen(ttn->macroname); - while (c > 0) { - if (ttn->macroname[c - 1] == '-') -@@ -364,7 +368,10 @@ insert_into_typenames(int type, const char *typename, const char *attr) { - attr, typename); - exit(1); - } -+ - strncpy(ttn->attr, attr, sizeof(ttn->attr)); -+ ttn->attr[sizeof(ttn->attr) - 1] = '\0'; -+ - ttn->sorted = 0; - if (maxtype < type) - maxtype = type; -@@ -393,11 +400,17 @@ add(int rdclass, const char *classname, int type, const char *typename, - newtt->next = NULL; - newtt->rdclass = rdclass; - newtt->type = type; -+ - strncpy(newtt->classname, classname, sizeof(newtt->classname)); -+ newtt->classname[sizeof(newtt->classname) - 1] = '\0'; -+ - strncpy(newtt->typename, typename, sizeof(newtt->typename)); -+ newtt->typename[sizeof(newtt->typename) - 1] = '\0'; -+ - if (strncmp(dirname, "./", 2) == 0) - dirname += 2; - strncpy(newtt->dirname, dirname, sizeof(newtt->dirname)); -+ newtt->dirname[sizeof(newtt->dirname) - 1] = '\0'; - - tt = types; - oldtt = NULL; -@@ -436,6 +449,7 @@ add(int rdclass, const char *classname, int type, const char *typename, - } - newcc->rdclass = rdclass; - strncpy(newcc->classname, classname, sizeof(newcc->classname)); -+ newcc->classname[sizeof(newcc->classname) - 1] = '\0'; - cc = classes; - oldcc = NULL; - -diff --git a/lib/dns/name.c b/lib/dns/name.c -index 4fcabb1..93173ee 100644 ---- a/lib/dns/name.c -+++ b/lib/dns/name.c -@@ -1859,7 +1859,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, - 0) - return (DNS_R_DISALLOWED); - new_current = c & 0x3F; -- n = 1; - state = fw_newcurrent; - } else - return (DNS_R_BADLABELTYPE); -@@ -1867,8 +1866,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, - case fw_ordinary: - if (downcase) - c = maptolower[c]; -- /* FALLTHROUGH */ -- case fw_copy: - *ndata++ = c; - n--; - if (n == 0) -@@ -1877,9 +1874,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, - case fw_newcurrent: - new_current *= 256; - new_current += c; -- n--; -- if (n != 0) -- break; - if (new_current >= biggest_pointer) - return (DNS_R_BADPOINTER); - biggest_pointer = new_current; -@@ -2398,6 +2392,8 @@ dns_name_tostring(dns_name_t *name, char **target, isc_mem_t *mctx) { - - isc_buffer_usedregion(&buf, ®); - p = isc_mem_allocate(mctx, reg.length + 1); -+ if (p == NULL) -+ return (ISC_R_NOMEMORY); - memcpy(p, (char *) reg.base, (int) reg.length); - p[reg.length] = '\0'; - -diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c -index 935f515..86fad33 100644 ---- a/lib/dns/nsec3.c -+++ b/lib/dns/nsec3.c -@@ -842,8 +842,8 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version, - dns_db_detachnode(db, &newnode); - } while (1); - -- if (result == ISC_R_NOMORE) -- result = ISC_R_SUCCESS; -+ /* result cannot be ISC_R_NOMORE here */ -+ INSIST(result != ISC_R_NOMORE); - - failure: - if (dbit != NULL) -diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c -index 0b7fe8c..091b3c7 100644 ---- a/lib/dns/rcode.c -+++ b/lib/dns/rcode.c -@@ -216,7 +216,9 @@ maybe_numeric(unsigned int *valuep, isc_textregion_t *source, - * isc_parse_uint32(). isc_parse_uint32() requires - * null termination, so we must make a copy. - */ -- strncpy(buffer, source->base, NUMBERSIZE); -+ strncpy(buffer, source->base, sizeof(buffer)); -+ buffer[sizeof(buffer) - 1] = '\0'; -+ - INSIST(buffer[source->length] == '\0'); - - result = isc_parse_uint32(&n, buffer, 10); -diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c -index 5cce1bc..6706542 100644 ---- a/lib/isc/netaddr.c -+++ b/lib/isc/netaddr.c -@@ -235,6 +235,7 @@ isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) { - nbytes = prefixlen / 8; - nbits = prefixlen % 8; - if (nbits != 0) { -+ INSIST(nbytes < ipbytes); - if ((p[nbytes] & (0xff>>nbits)) != 0U) - return (ISC_R_FAILURE); - nbytes++; -diff --git a/lib/isc/pk11.c b/lib/isc/pk11.c -index 015bff2..de4479b 100644 ---- a/lib/isc/pk11.c -+++ b/lib/isc/pk11.c -@@ -130,7 +130,10 @@ - #include - #include - --#define PINLEN 32 -+/* was 32 octets, Petr Spacek suggested 1024, SoftHSMv2 uses 256... */ -+#ifndef PINLEN -+#define PINLEN 256 -+#endif - - #ifndef PK11_NO_LOGERR - #define PK11_NO_LOGERR 1 -@@ -163,7 +166,7 @@ struct pk11_token { - char manuf[32]; - char model[16]; - char serial[16]; -- char pin[PINLEN]; -+ char pin[PINLEN + 1]; - }; - static ISC_LIST(pk11_token_t) tokens; - -@@ -498,7 +501,9 @@ pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype, - - /* Override the token's PIN */ - if (logon && pin != NULL && *pin != '\0') { -- memset(token->pin, 0, PINLEN); -+ if (strlen(pin) > PINLEN) -+ return ISC_R_RANGE; -+ memset(token->pin, 0, PINLEN + 1); - strncpy(token->pin, pin, PINLEN); - } - -@@ -1099,7 +1104,7 @@ pk11_parse_uri(pk11_object_t *obj, const char *label, - char *uri, *p, *a, *na, *v; - size_t len, l; - FILE *stream = NULL; -- char pin[PINLEN]; -+ char pin[PINLEN + 1]; - isc_boolean_t gotpin = ISC_FALSE; - isc_result_t ret; - -@@ -1207,10 +1212,12 @@ pk11_parse_uri(pk11_object_t *obj, const char *label, - ret = isc_stdio_open(v, "r", &stream); - if (ret != ISC_R_SUCCESS) - goto err; -- memset(pin, 0, PINLEN); -- ret = isc_stdio_read(pin, 1, PINLEN - 1, stream, NULL); -+ memset(pin, 0, PINLEN + 1); -+ ret = isc_stdio_read(pin, 1, PINLEN + 1, stream, &l); - if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF)) - goto err; -+ if (l > PINLEN) -+ DST_RET(ISC_R_RANGE); - ret = isc_stdio_close(stream); - stream = NULL; - if (ret != ISC_R_SUCCESS) -@@ -1238,7 +1245,7 @@ pk11_parse_uri(pk11_object_t *obj, const char *label, - DST_RET(ISC_R_NOTFOUND); - obj->slot = token->slotid; - if (gotpin) { -- memmove(token->pin, pin, PINLEN); -+ memmove(token->pin, pin, PINLEN + 1); - obj->reqlogon = ISC_TRUE; - } - --- -2.1.0 - diff --git a/SOURCES/bind99-coverity-fixes2.patch b/SOURCES/bind99-coverity-fixes2.patch deleted file mode 100644 index 14dab6c..0000000 --- a/SOURCES/bind99-coverity-fixes2.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 1f3ac11cb4ecfab52f517ebf78493b0f05318be2 Mon Sep 17 00:00:00 2001 -From: Evan Hunt -Date: Mon, 16 Jun 2014 15:31:04 -0700 -Subject: [PATCH] [v9_9] null terminate strings for coverity - ---- - bin/dig/dig.c | 1 + - bin/tests/system/dlzexternal/driver.c | 6 ++++++ - 2 files changed, 7 insertions(+) - -diff --git a/bin/dig/dig.c b/bin/dig/dig.c -index 8a5fead..6af0964 100644 ---- a/bin/dig/dig.c -+++ b/bin/dig/dig.c -@@ -1453,6 +1453,7 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, - ip6_int, ISC_FALSE) == ISC_R_SUCCESS) { - strncpy((*lookup)->textname, textname, - sizeof((*lookup)->textname)); -+ (*lookup)->textname[sizeof((*lookup)->textname)-1] = 0; - debug("looking up %s", (*lookup)->textname); - (*lookup)->trace_root = ISC_TF((*lookup)->trace || - (*lookup)->ns_search_only); -diff --git a/bin/tests/system/dlzexternal/driver.c b/bin/tests/system/dlzexternal/driver.c -index 053c25a..f99ac14 100644 ---- a/bin/tests/system/dlzexternal/driver.c -+++ b/bin/tests/system/dlzexternal/driver.c -@@ -133,8 +133,14 @@ add_name(struct dlz_example_data *state, struct record *list, - return (ISC_R_NOSPACE); - - strncpy(list[i].name, name, sizeof(list[i].name)); -+ list[i].name[sizeof(list[i].name) - 1] = '\0'; -+ - strncpy(list[i].type, type, sizeof(list[i].type)); -+ list[i].type[sizeof(list[i].type) - 1] = '\0'; -+ - strncpy(list[i].data, data, sizeof(list[i].data)); -+ list[i].data[sizeof(list[i].data) - 1] = '\0'; -+ - list[i].ttl = ttl; - - return (ISC_R_SUCCESS); --- -2.9.3 - diff --git a/SOURCES/bind99-dyndb.patch b/SOURCES/bind99-dyndb.patch deleted file mode 100644 index a021ef8..0000000 --- a/SOURCES/bind99-dyndb.patch +++ /dev/null @@ -1,5176 +0,0 @@ -From a86e8e75d0ac3266756df18575e16baff7743ccd Mon Sep 17 00:00:00 2001 -From: Evan Hunt -Date: Mon, 28 Sep 2015 23:12:35 -0700 -Subject: [PATCH] merge dyndb -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -4224. [func] Added support for "dyndb", a new interface for loading - zone data from an external database, developed by - Red Hat for the FreeIPA project. - - DynDB drivers fully implement the BIND database - API, and are capable of significantly better - performance and functionality than DLZ drivers, - while taking advantage of advanced database - features not available in BIND such as multi-master - replication. - - Thanks to Adam Tkac and Petr Spacek of Red Hat. - [RT #35271] - -(cherry picked from commit a00f9e2f50675bd43cc6a9fe2669709162a2ccb4) - -Make backport compilable - -add missing libraries - -(cherry picked from commit ac6bb3dd36149bc51e0367eba7c50e15dc076c9b) - -(cherry picked from commit ab8b419a797fae25f441273aca3ec18d8d0c1106) - -address linking issues - -(cherry picked from commit 1a0e5b0504576a17a99817d9eef10c4937ef0d63) - -silence compiler warnings - -(cherry picked from commit 0d990f57aefcb3a2e82a91367fc600ccf69eea63) - -remove deadcode; move NULL assignment arlier - -(cherry picked from commit 30f8d5e386a283c7e3a24683b78e489881c16c34) - -Updated WIN32 files (rt40877) -Use only differences in dyndb files, do not update win32 projects - -(cherry picked from commit 343aeac7176d28c4a1b9d246b1f7311b4cd5da7d) - -remove unnecessary return - -(cherry picked from commit 7f79448198139145cebc2540188b16b1861b98c5) - -add missing dependancy - -(cherry picked from commit 97e9fc9e53039c141e1a14adab0865a04225848a) - -4386.[bug]Remove shadowed overmem function/variable. [RT #42706] - -(cherry picked from commit 96beefd76f597b77d4fcd51f8d766e5e59a2d216) - -update dyndb_init inline documentationi [RT #43050] - -(cherry picked from commit 8c2c6b8b42766c8221c79bd43680dbfbaed17147) - -[master] fix dyndb issues; isc_errno_toresult() - -4445. [cleanup] isc_errno_toresult() can now be used to call the - formerly private function isc__errno2result(). - [RT #43050] - -4444. [bug] Fixed some issues related to dyndb: A bug caused - braces to be omitted when passing configuration text - from named.conf to a dyndb driver, and there was a - use-after-free in the sample dyndb driver. [RT #43050] - -Patch for dyndb driver submitted by Petr Spacek at Red Hat. - -(cherry picked from commit 3390d74e33385337631b19e68760025e0ca5d6ec) - -[master] pass source file and line to dyndb load function - -4455. [cleanup] Allow dyndb modules to correctly log the filename - and line number when processing configuration text - from named.conf. [RT #43050] - -(cherry picked from commit 02fb764681d145e4607c59280a48617013e886ac) - -install isc/errno.h - -(cherry picked from commit dec17fb66215d0b02ff9a5810658cdcd0215d240) - -4493. [bug] bin/tests/system/dyndb/driver/Makefile.in should use - SO_TARGETS. [RT# 43336] - -(cherry picked from commit c910fc24ce2aad5fa9e9a2d304f818fd8e996e6f) - -Include dyndb in tests building - -(picked by hand from master commit 93c211afc97e7a072c12ef346581065e4065ff15) - -Do not test type of a pointer - -Skip DEEPBIND - works only with shared library, but works. And fix dyndb test - -Backported to 9.9.4 - -Include commandline.c in export libraries - -Signed-off-by: Petr Menšík ---- - COPYRIGHT | 17 +- - bin/named/Makefile.in | 3 +- - bin/named/main.c | 1 + - bin/named/server.c | 68 ++- - bin/tests/Makefile.in | 2 - - bin/tests/system/Makefile.in | 2 +- - bin/tests/system/checkconf/good.conf | 9 + - bin/tests/system/conf.sh.in | 4 +- - bin/tests/system/dlzexternal/tests.sh | 2 - - bin/tests/system/dyndb/Makefile.in | 26 + - bin/tests/system/dyndb/clean.sh | 25 + - bin/tests/system/dyndb/driver/.gitignore | 1 + - bin/tests/system/dyndb/driver/AUTHORS | 8 + - bin/tests/system/dyndb/driver/COPYING | 15 + - bin/tests/system/dyndb/driver/Makefile.in | 60 +++ - bin/tests/system/dyndb/driver/README | 65 +++ - bin/tests/system/dyndb/driver/db.c | 848 ++++++++++++++++++++++++++++++ - bin/tests/system/dyndb/driver/db.h | 15 + - bin/tests/system/dyndb/driver/driver.c | 143 +++++ - bin/tests/system/dyndb/driver/instance.c | 161 ++++++ - bin/tests/system/dyndb/driver/instance.h | 47 ++ - bin/tests/system/dyndb/driver/lock.c | 56 ++ - bin/tests/system/dyndb/driver/lock.h | 17 + - bin/tests/system/dyndb/driver/log.c | 21 + - bin/tests/system/dyndb/driver/log.h | 27 + - bin/tests/system/dyndb/driver/syncptr.c | 265 ++++++++++ - bin/tests/system/dyndb/driver/syncptr.h | 15 + - bin/tests/system/dyndb/driver/util.h | 57 ++ - bin/tests/system/dyndb/driver/zone.c | 192 +++++++ - bin/tests/system/dyndb/driver/zone.h | 15 + - bin/tests/system/dyndb/ns1/named.conf | 42 ++ - bin/tests/system/dyndb/prereq.sh | 21 + - bin/tests/system/dyndb/tests.sh | 155 ++++++ - configure | 7 +- - configure.in | 3 + - doc/arm/Bv9ARM-book.xml | 2 + - doc/arm/dyndb.xml | 105 ++++ - lib/dns/Makefile.in | 8 +- - lib/dns/dlz.c | 64 +-- - lib/dns/dyndb.c | 486 +++++++++++++++++ - lib/dns/include/dns/Makefile.in | 4 +- - lib/dns/include/dns/dyndb.h | 166 ++++++ - lib/dns/include/dns/log.h | 1 + - lib/dns/include/dns/types.h | 1 + - lib/dns/lib.c | 4 +- - lib/dns/log.c | 1 + - lib/dns/win32/libdns.def | 4 + - lib/export/isc/Makefile.in | 6 +- - lib/isc/Makefile.in | 8 +- - lib/isc/commandline.c | 60 +++ - lib/isc/hash.c | 28 +- - lib/isc/include/isc/Makefile.in | 4 +- - lib/isc/include/isc/commandline.h | 18 +- - lib/isc/include/isc/errno.h | 25 + - lib/isc/include/isc/hash.h | 4 +- - lib/isc/include/isc/lex.h | 21 +- - lib/isc/lex.c | 110 +++- - lib/isc/tests/Makefile.in | 11 +- - lib/isc/tests/errno_test.c | 102 ++++ - lib/isc/unix/Makefile.in | 8 +- - lib/isc/unix/errno.c | 21 + - lib/isc/unix/errno2result.c | 14 +- - lib/isc/unix/errno2result.h | 7 +- - lib/isc/win32/Makefile.in | 8 +- - lib/isc/win32/errno.c | 18 + - lib/isc/win32/errno2result.c | 14 +- - lib/isc/win32/errno2result.h | 5 +- - lib/isc/win32/libisc.def | 2 + - lib/isc/win32/libisc.dsp | 8 + - lib/isc/win32/libisc.mak | 23 + - lib/isc/win32/socket.c | 4 +- - lib/isccfg/include/isccfg/grammar.h | 1 + - lib/isccfg/namedconf.c | 18 + - lib/isccfg/parser.c | 46 ++ - 74 files changed, 3703 insertions(+), 152 deletions(-) - create mode 100644 bin/tests/system/dyndb/Makefile.in - create mode 100644 bin/tests/system/dyndb/clean.sh - create mode 100644 bin/tests/system/dyndb/driver/.gitignore - create mode 100644 bin/tests/system/dyndb/driver/AUTHORS - create mode 100644 bin/tests/system/dyndb/driver/COPYING - create mode 100644 bin/tests/system/dyndb/driver/Makefile.in - create mode 100644 bin/tests/system/dyndb/driver/README - create mode 100644 bin/tests/system/dyndb/driver/db.c - create mode 100644 bin/tests/system/dyndb/driver/db.h - create mode 100644 bin/tests/system/dyndb/driver/driver.c - create mode 100644 bin/tests/system/dyndb/driver/instance.c - create mode 100644 bin/tests/system/dyndb/driver/instance.h - create mode 100644 bin/tests/system/dyndb/driver/lock.c - create mode 100644 bin/tests/system/dyndb/driver/lock.h - create mode 100644 bin/tests/system/dyndb/driver/log.c - create mode 100644 bin/tests/system/dyndb/driver/log.h - create mode 100644 bin/tests/system/dyndb/driver/syncptr.c - create mode 100644 bin/tests/system/dyndb/driver/syncptr.h - create mode 100644 bin/tests/system/dyndb/driver/util.h - create mode 100644 bin/tests/system/dyndb/driver/zone.c - create mode 100644 bin/tests/system/dyndb/driver/zone.h - create mode 100644 bin/tests/system/dyndb/ns1/named.conf - create mode 100644 bin/tests/system/dyndb/prereq.sh - create mode 100644 bin/tests/system/dyndb/tests.sh - create mode 100644 doc/arm/dyndb.xml - create mode 100644 lib/dns/dyndb.c - create mode 100644 lib/dns/include/dns/dyndb.h - create mode 100644 lib/isc/include/isc/errno.h - create mode 100644 lib/isc/tests/errno_test.c - create mode 100644 lib/isc/unix/errno.c - create mode 100644 lib/isc/win32/errno.c - -diff --git a/COPYRIGHT b/COPYRIGHT -index 525c222..137db13 100644 ---- a/COPYRIGHT -+++ b/COPYRIGHT -@@ -161,7 +161,7 @@ POSSIBILITY OF SUCH DAMAGE. - - ----------------------------------------------------------------------------- - --Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan -+Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan - (Royal Institute of Technology, Stockholm, Sweden). - All rights reserved. - -@@ -516,3 +516,18 @@ 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. - -+----------------------------------------------------------------------------- -+ -+Copyright (C) 2008-2011 Red Hat, Inc. -+ -+Permission to use, copy, modify, and/or distribute this software for any -+purpose with or without fee is hereby granted, provided that the above -+copyright notice and this permission notice appear in all copies. -+ -+THE SOFTWARE IS PROVIDED "AS IS" AND Red Hat DISCLAIMS ALL WARRANTIES WITH -+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+AND FITNESS. IN NO EVENT SHALL Red Hat BE LIABLE FOR ANY SPECIAL, DIRECT, -+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+PERFORMANCE OF THIS SOFTWARE. -diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in -index cd65777..8ec9ad7 100644 ---- a/bin/named/Makefile.in -+++ b/bin/named/Makefile.in -@@ -13,8 +13,6 @@ - # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - # PERFORMANCE OF THIS SOFTWARE. - --# $Id: Makefile.in,v 1.116 2011/03/10 23:47:49 tbox Exp $ -- - srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ -@@ -138,6 +136,7 @@ config.@O@: config.c bind.keys.h - ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ - -DVERSION=\"${VERSION}\" \ - -DSRCID=\"${SRCID}\" \ -+ -DDYNDB_LIBDIR=\"@libdir@/bind\" \ - -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ - -DNS_SYSCONFDIR=\"${sysconfdir}\" \ - -c ${srcdir}/config.c -diff --git a/bin/named/main.c b/bin/named/main.c -index 6e12847..d26783f 100644 ---- a/bin/named/main.c -+++ b/bin/named/main.c -@@ -45,6 +45,7 @@ - #include - - #include -+#include - #include - #include - #include -diff --git a/bin/named/server.c b/bin/named/server.c -index daa5b0e..6260f8f 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -30,6 +30,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -64,6 +65,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1243,6 +1245,33 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { - } - - static isc_result_t -+configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, -+ const dns_dyndbctx_t *dctx) -+{ -+ isc_result_t result = ISC_R_SUCCESS; -+ const cfg_obj_t *obj; -+ const char *name, *library; -+ -+ /* Get the name of the dyndb instance and the library path . */ -+ name = cfg_obj_asstring(cfg_tuple_get(dyndb, "name")); -+ library = cfg_obj_asstring(cfg_tuple_get(dyndb, "library")); -+ -+ obj = cfg_tuple_get(dyndb, "parameters"); -+ if (obj != NULL) -+ result = dns_dyndb_load(library, name, cfg_obj_asstring(obj), -+ cfg_obj_file(obj), cfg_obj_line(obj), -+ mctx, dctx); -+ -+ if (result != ISC_R_SUCCESS) -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR, -+ "dynamic database '%s' configuration failed: %s", -+ name, isc_result_totext(result)); -+ return (result); -+} -+ -+ -+static isc_result_t - disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { - isc_result_t result; - const cfg_obj_t *algorithms; -@@ -2058,6 +2087,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - const cfg_obj_t *dlz; - unsigned int dlzargc; - char **dlzargv; -+ const cfg_obj_t *dyndb_list; - const cfg_obj_t *disabled; - const cfg_obj_t *obj; - const cfg_listelt_t *element; -@@ -2097,6 +2127,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - unsigned int query_timeout, ndisp; - struct cfg_context *nzctx; - dns_rpz_zone_t *rpz; -+ dns_dyndbctx_t *dctx = NULL; - - REQUIRE(DNS_VIEW_VALID(view)); - -@@ -2317,7 +2348,8 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - goto cleanup; - } - -- result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv); -+ result = isc_commandline_strtoargv(mctx, s, &dlzargc, -+ &dlzargv, 0); - if (result != ISC_R_SUCCESS) { - isc_mem_free(mctx, s); - goto cleanup; -@@ -3261,6 +3293,31 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - dns_view_setrootdelonly(view, ISC_FALSE); - - /* -+ * Load DynDB modules. -+ */ -+ dyndb_list = NULL; -+ if (voptions != NULL) -+ (void)cfg_map_get(voptions, "dyndb", &dyndb_list); -+ else -+ (void)cfg_map_get(config, "dyndb", &dyndb_list); -+ -+ for (element = cfg_list_first(dyndb_list); -+ element != NULL; -+ element = cfg_list_next(element)) -+ { -+ const cfg_obj_t *dyndb = cfg_listelt_value(element); -+ -+ if (dctx == NULL) -+ CHECK(dns_dyndb_createctx(mctx, isc_hashctx, -+ ns_g_lctx, view, -+ ns_g_server->zonemgr, -+ ns_g_server->task, -+ ns_g_timermgr, &dctx)); -+ -+ CHECK(configure_dyndb(dyndb, mctx, dctx)); -+ } -+ -+ /* - * Setup automatic empty zones. If recursion is off then - * they are disabled by default. - */ -@@ -3445,6 +3502,8 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - - if (cache != NULL) - dns_cache_detach(&cache); -+ if (dctx != NULL) -+ dns_dyndb_destroyctx(&dctx); - - return (result); - } -@@ -4915,6 +4974,11 @@ load_configuration(const char *filename, ns_server_t *server, - CHECK(cfg_aclconfctx_create(ns_g_mctx, &ns_g_aclconfctx)); - - /* -+ * Shut down all dyndb instances. -+ */ -+ dns_dyndb_cleanup(ISC_FALSE); -+ -+ /* - * Parse the global default pseudo-config file. - */ - if (first_time) { -@@ -6043,6 +6107,8 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { - dns_view_detach(&view); - } - -+ dns_dyndb_cleanup(ISC_TRUE); -+ - while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) { - ISC_LIST_UNLINK(server->cachelist, nsc, link); - dns_cache_detach(&nsc->cache); -diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in -index 2020bf4..8477ae5 100644 ---- a/bin/tests/Makefile.in -+++ b/bin/tests/Makefile.in -@@ -13,8 +13,6 @@ - # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - # PERFORMANCE OF THIS SOFTWARE. - --# $Id: Makefile.in,v 1.145 2011/02/03 05:41:53 marka Exp $ -- - srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ -diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in -index f7bcc26..af8b82c 100644 ---- a/bin/tests/system/Makefile.in -+++ b/bin/tests/system/Makefile.in -@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@ - - @BIND9_MAKE_INCLUDES@ - --SUBDIRS = dlzexternal filter-aaaa lwresd rpz rrl \ -+SUBDIRS = dlzexternal dyndb filter-aaaa lwresd rpz rrl \ - rsabigexponent tkey tsiggss - TARGETS = - -diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf -index 5444fdd..a6310cd 100644 ---- a/bin/tests/system/checkconf/good.conf -+++ b/bin/tests/system/checkconf/good.conf -@@ -104,3 +104,12 @@ view "second" { - dnssec-validation auto; - zone-statistics full; - }; -+dyndb "name" "library.so" { -+ this; -+ \}; -+ is a { -+ "test" { \{ of; the; }; -+ } bracketed; -+ "text \""; -+ system; -+}; -diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in -index c40e8f1..eb02236 100644 ---- a/bin/tests/system/conf.sh.in -+++ b/bin/tests/system/conf.sh.in -@@ -60,8 +60,8 @@ SAMPLE=$TOP/lib/export/samples/sample - # v6synth - SUBDIRS="acl additional allow_query addzone autosign builtin - cacheclean checkconf @CHECKDS@ checknames checkzone @COVERAGE@ -- database dlv dlvauto dlz dlzexternal dname dns64 dnssec ecdsa -- formerr forward glue gost ixfr inline limits logfileconfig -+ database dlv dlvauto dlz dlzexternal dname dns64 dnssec dyndb -+ ecdsa formerr forward glue gost ixfr inline limits logfileconfig - lwresd masterfile masterformat metadata notify nsupdate pending - @PKCS11_TEST@ redirect resolver rndc rpz rrl rrsetorder rsabigexponent - smartsign sortlist spf staticstub stub tkey tsig tsiggss unknown -diff --git a/bin/tests/system/dlzexternal/tests.sh b/bin/tests/system/dlzexternal/tests.sh -index bd2eeac..103d4c9 100644 ---- a/bin/tests/system/dlzexternal/tests.sh -+++ b/bin/tests/system/dlzexternal/tests.sh -@@ -1,6 +1,4 @@ - #!/bin/sh --# tests for TSIG-GSS updates -- - SYSTEMTESTTOP=.. - . $SYSTEMTESTTOP/conf.sh - -diff --git a/bin/tests/system/dyndb/Makefile.in b/bin/tests/system/dyndb/Makefile.in -new file mode 100644 -index 0000000..c7792f2 ---- /dev/null -+++ b/bin/tests/system/dyndb/Makefile.in -@@ -0,0 +1,26 @@ -+# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_VERSION@ -+ -+@BIND9_MAKE_INCLUDES@ -+ -+SUBDIRS = driver -+TARGETS = -+ -+@BIND9_MAKE_RULES@ -diff --git a/bin/tests/system/dyndb/clean.sh b/bin/tests/system/dyndb/clean.sh -new file mode 100644 -index 0000000..2273396 ---- /dev/null -+++ b/bin/tests/system/dyndb/clean.sh -@@ -0,0 +1,25 @@ -+#!/bin/sh -+# -+# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# -+# Clean up after dyndb tests. -+# -+rm -f ns1/named.memstats -+rm -f ns1/update.txt -+rm -f added.a.out.* -+rm -f added.ptr.out.* -+rm -f deleted.a.out.* -+rm -f deleted.ptr.out.* -diff --git a/bin/tests/system/dyndb/driver/.gitignore b/bin/tests/system/dyndb/driver/.gitignore -new file mode 100644 -index 0000000..c3af857 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/.gitignore -@@ -0,0 +1 @@ -+lib/ -diff --git a/bin/tests/system/dyndb/driver/AUTHORS b/bin/tests/system/dyndb/driver/AUTHORS -new file mode 100644 -index 0000000..acc109c ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/AUTHORS -@@ -0,0 +1,8 @@ -+This sample driver is based on bind-dyndb-ldap project and small portions -+of code from ISC BIND 9.10. -+ -+Authors listed in alphabetical order: -+Adam Tkac -+Jiri Kuncar -+Martin Nagy -+Petr Spacek -diff --git a/bin/tests/system/dyndb/driver/COPYING b/bin/tests/system/dyndb/driver/COPYING -new file mode 100644 -index 0000000..08d4d77 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/COPYING -@@ -0,0 +1,15 @@ -+Copyright (C) 2009-2015 Red Hat -+Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") -+Copyright (C) 1999-2003 Internet Software Consortium. -+ -+Permission to use, copy, modify, and/or distribute this software for any -+purpose with or without fee is hereby granted, provided that the above -+copyright notice and this permission notice appear in all copies. -+ -+THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIMS ALL WARRANTIES WITH -+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+PERFORMANCE OF THIS SOFTWARE. -diff --git a/bin/tests/system/dyndb/driver/Makefile.in b/bin/tests/system/dyndb/driver/Makefile.in -new file mode 100644 -index 0000000..e23c563 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/Makefile.in -@@ -0,0 +1,60 @@ -+# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_MAKE_INCLUDES@ -+ -+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} -+ -+CDEFINES = -+CWARNINGS = -+ -+DNSLIBS = ../../../../../lib/dns/libdns.@A@ -+ISCLIBS = ../../../../../lib/isc/libisc.@A@ -+ -+DNSDEPLIBS = ../../../../../lib/dns/libdns.@A@ -+ISCDEPLIBS = ../../../../../lib/isc/libisc.@A@ -+ -+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} -+ -+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@ -+ -+ -+SRCS = db.c driver.c instance.c \ -+ lock.c log.c syncptr.c zone.c -+ -+OBJS = db.@O@ driver.@O@ instance.@O@ \ -+ lock.@O@ log.@O@ syncptr.@O@ zone.@O@ -+ -+SO_TARGETS = lib/sample.@SO@ -+TARGETS = @SO_TARGETS@ -+ -+@BIND9_MAKE_RULES@ -+ -+CFLAGS = @CFLAGS@ @SO_CFLAGS@ -+SO_LDFLAGS = @LDFLAGS@ -+ -+lib/sample.@SO@: sample.@SO@ -+ $(SHELL) ${top_srcdir}/mkinstalldirs `pwd`/lib -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL} sample.@SO@ `pwd`/lib -+ -+sample.@SO@: ${OBJS} ${DNSDEPLIBS} ${ISCDEPLIBS} -+ ${LIBTOOL_MODE_LINK} @SO_LD@ ${SO_LDFLAGS} -o $@ ${OBJS} \ -+ ${DNSLIBS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS} -+ -+clean distclean:: -+ rm -f ${OBJS} sample.so lib/sample.so -diff --git a/bin/tests/system/dyndb/driver/README b/bin/tests/system/dyndb/driver/README -new file mode 100644 -index 0000000..9aac0a6 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/README -@@ -0,0 +1,65 @@ -+To use the Dynamic DB sample driver, run named and check the log. -+ -+ $ cd testing -+ $ named -gc named.conf -+ -+You should be able to see something like: -+ -+zone test/IN: loaded serial 0 -+zone arpa/IN: loaded serial 0 -+ -+This means that the sample driver created empty zones "test." and -+"arpa." as defined by "arg" parameters in named.conf. -+ -+$ dig @localhost test. -+ -+should work as usual and you should be able to see the dummy zone with -+NS record pointing to the zone apex and A record with 127.0.0.1: -+ -+;; ANSWER SECTION: -+test. 86400 IN A 127.0.0.1 -+test. 86400 IN NS test. -+test. 86400 IN SOA test. test. 0 28800 7200 604800 86400 -+ -+This driver creates two empty zones and allows query/transfer/update to -+all IP addresses for demonstration purposes. -+ -+The driver wraps the RBT database implementation used natively by BIND, -+and modifies the addrdataset() and substractrdataset() functions to do -+additional work during dynamic updates. -+ -+A dynamic update modifies the target zone as usual. After that, the -+driver detects whether the modified RR was of type A or AAAA, and if so, -+attempts to appropriately generate or delete a matching PTR record in -+one of the two zones managed by the driver. -+ -+E.g.: -+ -+$ nsupdate -+> update add a.test. 300 IN A 192.0.2.1 -+> send -+ -+will add the A record -+a.test. 300 IN A 192.0.2.1 -+ -+and also automatically generate the PTR record -+1.2.0.192.in-addr.arpa. 300 IN PTR a.test. -+ -+AXFR and RR deletion via dynamic updates should work as usual. Deletion -+of a type A or AAAA record should delete the corresponding PTR record -+too. -+ -+The zone is stored only in memory, and all changes will be lost on -+reload/reconfig. -+ -+Hints for code readers: -+- Driver initialization starts in driver.c: dyndb_init() function. -+- New database implementation is registered by calling dns_db_register() -+ and passing a function pointer to it. This sample uses the function -+ create_db() to initialize the database. -+- Zones are created later in instance.c: load_sample_instance_zones(). -+- Database entry points are in structure db.c: dns_dbmethods_t -+ sampledb_methods -+- sampledb_methods points to an implementation of the database interface. -+ See the db.c: addrdataset() implementation and look at how the RBT -+ database instance is wrapped into an additional layer of logic. -diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c -new file mode 100644 -index 0000000..d2ca023 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/db.c -@@ -0,0 +1,848 @@ -+/* -+ * Database API implementation. The interface is defined in lib/dns/db.h. -+ * -+ * dns_db_*() calls on database instances backed by this driver use -+ * struct sampledb_methods to find appropriate function implementation. -+ * -+ * This example re-uses RBT DB implementation from original BIND and blindly -+ * proxies most of dns_db_*() calls to this underlying RBT DB. -+ * See struct sampledb below. -+ * -+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license -+ */ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "db.h" -+#include "instance.h" -+#include "syncptr.h" -+#include "util.h" -+ -+#define SAMPLEDB_MAGIC ISC_MAGIC('S', 'M', 'D', 'B') -+#define VALID_SAMPLEDB(sampledb) \ -+ ((sampledb) != NULL && (sampledb)->common.impmagic == SAMPLEDB_MAGIC) -+ -+struct sampledb { -+ dns_db_t common; -+ isc_refcount_t refs; -+ sample_instance_t *inst; -+ -+ /* -+ * Internal RBT database implementation provided by BIND. -+ * Most dns_db_* calls (find(), createiterator(), etc.) -+ * are blindly forwarded to this RBT DB. -+ */ -+ dns_db_t *rbtdb; -+}; -+ -+typedef struct sampledb sampledb_t; -+ -+/* -+ * Get full DNS name from the node. -+ * -+ * @warning -+ * The code silently expects that "node" came from RBTDB and thus -+ * assumption dns_dbnode_t (from RBTDB) == dns_rbtnode_t is correct. -+ * -+ * This should work as long as we use only RBTDB and nothing else. -+ */ -+static isc_result_t -+sample_name_fromnode(dns_dbnode_t *node, dns_name_t *name) { -+ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *) node; -+ return (dns_rbt_fullnamefromnode(rbtnode, name)); -+} -+ -+static void -+attach(dns_db_t *source, dns_db_t **targetp) { -+ sampledb_t *sampledb = (sampledb_t *)source; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ isc_refcount_increment(&sampledb->refs, NULL); -+ *targetp = source; -+} -+ -+static void -+free_sampledb(sampledb_t *sampledb) { -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_detach(&sampledb->rbtdb); -+ dns_name_free(&sampledb->common.origin, sampledb->common.mctx); -+ isc_mem_putanddetach(&sampledb->common.mctx, sampledb, sizeof(*sampledb)); -+} -+ -+static void -+detach(dns_db_t **dbp) { -+ sampledb_t *sampledb = (sampledb_t *)(*dbp); -+ unsigned int refs; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ isc_refcount_decrement(&sampledb->refs, &refs); -+ if (refs == 0) -+ free_sampledb(sampledb); -+ *dbp = NULL; -+} -+ -+/* -+ * This method should never be called, because DB is "persistent". -+ * See ispersistent() function. It means that database do not need to be -+ * loaded in the usual sense. -+ */ -+static isc_result_t -+beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) { -+ UNUSED(db); -+ UNUSED(addp); -+ UNUSED(dbloadp); -+ -+ fatal_error("current implementation should never call beginload()"); -+ -+ /* Not reached */ -+ return (ISC_R_SUCCESS); -+} -+ -+/* -+ * This method should never be called, because DB is "persistent". -+ * See ispersistent() function. It means that database do not need to be -+ * loaded in the usual sense. -+ */ -+static isc_result_t -+endload(dns_db_t *db, dns_dbload_t **dbloadp) { -+ UNUSED(db); -+ UNUSED(dbloadp); -+ -+ fatal_error("current implementation should never call endload()"); -+ -+ /* Not reached */ -+ return (ISC_R_SUCCESS); -+} -+ -+#if 0 -+static isc_result_t -+serialize(dns_db_t *db, dns_dbversion_t *version, FILE *file) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_serialize(sampledb->rbtdb, version, file)); -+} -+#endif -+ -+static isc_result_t -+dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, -+ dns_masterformat_t masterformat) -+{ -+ -+ UNUSED(db); -+ UNUSED(version); -+ UNUSED(filename); -+ UNUSED(masterformat); -+ -+ fatal_error("current implementation should never call dump()"); -+ -+ /* Not reached */ -+ return (ISC_R_SUCCESS); -+} -+ -+static void -+currentversion(dns_db_t *db, dns_dbversion_t **versionp) { -+ sampledb_t *sampledb = (sampledb_t *)db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_currentversion(sampledb->rbtdb, versionp); -+} -+ -+static isc_result_t -+newversion(dns_db_t *db, dns_dbversion_t **versionp) { -+ sampledb_t *sampledb = (sampledb_t *)db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_newversion(sampledb->rbtdb, versionp)); -+} -+ -+static void -+attachversion(dns_db_t *db, dns_dbversion_t *source, -+ dns_dbversion_t **targetp) -+{ -+ sampledb_t *sampledb = (sampledb_t *)db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_attachversion(sampledb->rbtdb, source, targetp); -+} -+ -+static void -+closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { -+ sampledb_t *sampledb = (sampledb_t *)db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_closeversion(sampledb->rbtdb, versionp, commit); -+} -+ -+static isc_result_t -+findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, -+ dns_dbnode_t **nodep) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_findnode(sampledb->rbtdb, name, create, nodep)); -+} -+ -+static isc_result_t -+find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, -+ dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, -+ dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, -+ dns_rdataset_t *sigrdataset) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_find(sampledb->rbtdb, name, version, type, -+ options, now, nodep, foundname, -+ rdataset, sigrdataset)); -+} -+ -+static isc_result_t -+findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, -+ isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, -+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_findzonecut(sampledb->rbtdb, name, options, -+ now, nodep, foundname, rdataset, -+ sigrdataset)); -+} -+ -+static void -+attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_attachnode(sampledb->rbtdb, source, targetp); -+ -+} -+ -+static void -+detachnode(dns_db_t *db, dns_dbnode_t **targetp) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_detachnode(sampledb->rbtdb, targetp); -+} -+ -+static isc_result_t -+expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_expirenode(sampledb->rbtdb, node, now)); -+} -+ -+static void -+printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_printnode(sampledb->rbtdb, node, out); -+} -+ -+static isc_result_t -+createiterator(dns_db_t *db, unsigned int options, -+ dns_dbiterator_t **iteratorp) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_createiterator(sampledb->rbtdb, options, iteratorp)); -+} -+ -+static isc_result_t -+findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, -+ dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, -+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_findrdataset(sampledb->rbtdb, node, version, type, -+ covers, now, rdataset, sigrdataset)); -+} -+ -+static isc_result_t -+allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, -+ isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_allrdatasets(sampledb->rbtdb, node, version, -+ now, iteratorp)); -+} -+ -+static isc_result_t -+addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, -+ isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, -+ dns_rdataset_t *addedrdataset) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ isc_result_t result; -+ dns_fixedname_t name; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_fixedname_init(&name); -+ CHECK(dns_db_addrdataset(sampledb->rbtdb, node, version, now, -+ rdataset, options, addedrdataset)); -+ if (rdataset->type == dns_rdatatype_a || -+ rdataset->type == dns_rdatatype_aaaa) { -+ CHECK(sample_name_fromnode(node, dns_fixedname_name(&name))); -+ CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name), -+ rdataset, DNS_DIFFOP_ADD)); -+ } -+ -+cleanup: -+ return (result); -+} -+ -+static isc_result_t -+subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, -+ dns_rdataset_t *rdataset, unsigned int options, -+ dns_rdataset_t *newrdataset) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ isc_result_t result; -+ dns_fixedname_t name; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_fixedname_init(&name); -+ result = dns_db_subtractrdataset(sampledb->rbtdb, node, version, -+ rdataset, options, newrdataset); -+ if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) -+ goto cleanup; -+ -+ if (rdataset->type == dns_rdatatype_a || -+ rdataset->type == dns_rdatatype_aaaa) { -+ CHECK(sample_name_fromnode(node, dns_fixedname_name(&name))); -+ CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name), -+ rdataset, DNS_DIFFOP_DEL)); -+ } -+ -+cleanup: -+ return (result); -+} -+ -+/* -+ * deleterdataset() function is not used during DNS update processing so syncptr -+ * implementation is left as an exercise to the reader. -+ */ -+static isc_result_t -+deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, -+ dns_rdatatype_t type, dns_rdatatype_t covers) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_deleterdataset(sampledb->rbtdb, node, version, -+ type, covers)); -+} -+ -+static isc_boolean_t -+issecure(dns_db_t *db) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_issecure(sampledb->rbtdb)); -+} -+ -+static unsigned int -+nodecount(dns_db_t *db) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_nodecount(sampledb->rbtdb)); -+} -+ -+/* -+ * The database does not need to be loaded from disk or written to disk. -+ * Always return ISC_TRUE. -+ */ -+static isc_boolean_t -+ispersistent(dns_db_t *db) { -+ UNUSED(db); -+ -+ return (ISC_TRUE); -+} -+ -+static void -+overmem(dns_db_t *db, isc_boolean_t over) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_overmem(sampledb->rbtdb, over); -+} -+ -+static void -+settask(dns_db_t *db, isc_task_t *task) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_settask(sampledb->rbtdb, task); -+} -+ -+static isc_result_t -+getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_getoriginnode(sampledb->rbtdb, nodep)); -+} -+ -+static void -+transfernode(dns_db_t *db, dns_dbnode_t **sourcep, dns_dbnode_t **targetp) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_transfernode(sampledb->rbtdb, sourcep, targetp); -+ -+} -+ -+static isc_result_t -+getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, -+ dns_hash_t *hash, isc_uint8_t *flags, -+ isc_uint16_t *iterations, -+ unsigned char *salt, size_t *salt_length) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_getnsec3parameters(sampledb->rbtdb, version, -+ hash, flags, iterations, -+ salt, salt_length)); -+ -+} -+ -+static isc_result_t -+findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create, -+ dns_dbnode_t **nodep) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_findnsec3node(sampledb->rbtdb, name, create, nodep)); -+} -+ -+static isc_result_t -+setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_setsigningtime(sampledb->rbtdb, rdataset, resign)); -+} -+ -+static isc_result_t -+getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_getsigningtime(sampledb->rbtdb, rdataset, name)); -+} -+ -+static void -+resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_resigned(sampledb->rbtdb, rdataset, version); -+} -+ -+static isc_boolean_t -+isdnssec(dns_db_t *db) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_isdnssec(sampledb->rbtdb)); -+} -+ -+static dns_stats_t * -+getrrsetstats(dns_db_t *db) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_getrrsetstats(sampledb->rbtdb)); -+ -+} -+ -+static isc_result_t -+rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return dns_db_rpz_enabled(sampledb->rbtdb, st); -+} -+ -+static void -+rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, -+ dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, -+ dns_rdataset_t *ardataset, dns_rpz_st_t *st, -+ dns_name_t *query_qname) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_rpz_findips(rpz, rpz_type, zone, db, version, ardataset, st, query_qname); -+} -+ -+#if 0 -+static void -+rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ dns_db_rpz_attach(sampledb->rbtdb, rpzs, rpz_num); -+} -+ -+static isc_result_t -+rpz_ready(dns_db_t *db) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_rpz_ready(sampledb->rbtdb)); -+} -+#endif -+ -+static isc_result_t -+findnodeext(dns_db_t *db, dns_name_t *name, -+ isc_boolean_t create, dns_clientinfomethods_t *methods, -+ dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_findnodeext(sampledb->rbtdb, name, create, -+ methods, clientinfo, nodep)); -+} -+ -+static isc_result_t -+findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, -+ dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, -+ dns_dbnode_t **nodep, dns_name_t *foundname, -+ dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, -+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) -+{ -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_findext(sampledb->rbtdb, name, version, type, -+ options, now, nodep, foundname, methods, -+ clientinfo, rdataset, sigrdataset)); -+} -+ -+#if 0 -+static isc_result_t -+setcachestats(dns_db_t *db, isc_stats_t *stats) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_setcachestats(sampledb->rbtdb, stats)); -+} -+ -+static unsigned int -+hashsize(dns_db_t *db) { -+ sampledb_t *sampledb = (sampledb_t *) db; -+ -+ REQUIRE(VALID_SAMPLEDB(sampledb)); -+ -+ return (dns_db_hashsize(sampledb->rbtdb)); -+} -+#endif -+ -+/* -+ * DB interface definition. Database driver uses this structure to -+ * determine which implementation of dns_db_*() function to call. -+ */ -+static dns_dbmethods_t sampledb_methods = { -+ attach, -+ detach, -+ beginload, -+ endload, -+// serialize, -+ dump, -+ currentversion, -+ newversion, -+ attachversion, -+ closeversion, -+ findnode, -+ find, -+ findzonecut, -+ attachnode, -+ detachnode, -+ expirenode, -+ printnode, -+ createiterator, -+ findrdataset, -+ allrdatasets, -+ addrdataset, -+ subtractrdataset, -+ deleterdataset, -+ issecure, -+ nodecount, -+ ispersistent, -+ overmem, -+ settask, -+ getoriginnode, -+ transfernode, -+ getnsec3parameters, -+ findnsec3node, -+ setsigningtime, -+ getsigningtime, -+ resigned, -+ isdnssec, -+ getrrsetstats, -+ rpz_enabled, -+ rpz_findips, -+ findnodeext, -+ findext, -+#if 0 -+ setcachestats, -+ hashsize -+#endif -+}; -+ -+/* Auxiliary driver functions. */ -+ -+/* -+ * Auxiliary functions add_*() create minimal database which can be loaded. -+ * This is necessary because this driver create empty 'fake' zone which -+ * is not loaded from disk so there is no way for user to supply SOA, NS and A -+ * records. -+ * -+ * Following functions were copied from BIND 9.10.2rc1 named/server.c, -+ * credit goes to ISC. -+ */ -+static isc_result_t -+add_soa(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, -+ dns_name_t *origin, dns_name_t *contact) -+{ -+ dns_dbnode_t *node = NULL; -+ dns_rdata_t rdata = DNS_RDATA_INIT; -+ dns_rdatalist_t rdatalist; -+ dns_rdataset_t rdataset; -+ isc_result_t result; -+ unsigned char buf[DNS_SOA_BUFFERSIZE]; -+ -+ dns_rdataset_init(&rdataset); -+ dns_rdatalist_init(&rdatalist); -+ CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), -+ 0, 28800, 7200, 604800, 86400, buf, &rdata)); -+ rdatalist.type = rdata.type; -+ rdatalist.covers = 0; -+ rdatalist.rdclass = rdata.rdclass; -+ rdatalist.ttl = 86400; -+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); -+ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); -+ CHECK(dns_db_findnode(db, name, ISC_TRUE, &node)); -+ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); -+ cleanup: -+ if (node != NULL) -+ dns_db_detachnode(db, &node); -+ return (result); -+} -+ -+ -+static isc_result_t -+add_ns(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, -+ dns_name_t *nsname) -+{ -+ dns_dbnode_t *node = NULL; -+ dns_rdata_ns_t ns; -+ dns_rdata_t rdata = DNS_RDATA_INIT; -+ dns_rdatalist_t rdatalist; -+ dns_rdataset_t rdataset; -+ isc_result_t result; -+ isc_buffer_t b; -+ unsigned char buf[DNS_NAME_MAXWIRE]; -+ -+ isc_buffer_init(&b, buf, sizeof(buf)); -+ -+ dns_rdataset_init(&rdataset); -+ dns_rdatalist_init(&rdatalist); -+ ns.common.rdtype = dns_rdatatype_ns; -+ ns.common.rdclass = dns_db_class(db); -+ ns.mctx = NULL; -+ dns_name_init(&ns.name, NULL); -+ dns_name_clone(nsname, &ns.name); -+ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, -+ &ns, &b)); -+ rdatalist.type = rdata.type; -+ rdatalist.covers = 0; -+ rdatalist.rdclass = rdata.rdclass; -+ rdatalist.ttl = 86400; -+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); -+ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); -+ CHECK(dns_db_findnode(db, name, ISC_TRUE, &node)); -+ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); -+ cleanup: -+ if (node != NULL) -+ dns_db_detachnode(db, &node); -+ return (result); -+} -+ -+static isc_result_t -+add_a(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name, -+ struct in_addr addr) -+{ -+ dns_dbnode_t *node = NULL; -+ dns_rdata_in_a_t a; -+ dns_rdata_t rdata = DNS_RDATA_INIT; -+ dns_rdatalist_t rdatalist; -+ dns_rdataset_t rdataset; -+ isc_result_t result; -+ isc_buffer_t b; -+ unsigned char buf[DNS_NAME_MAXWIRE]; -+ -+ isc_buffer_init(&b, buf, sizeof(buf)); -+ -+ dns_rdataset_init(&rdataset); -+ dns_rdatalist_init(&rdatalist); -+ a.common.rdtype = dns_rdatatype_a; -+ a.common.rdclass = dns_db_class(db); -+ a.in_addr = addr; -+ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_a, -+ &a, &b)); -+ rdatalist.type = rdata.type; -+ rdatalist.covers = 0; -+ rdatalist.rdclass = rdata.rdclass; -+ rdatalist.ttl = 86400; -+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); -+ CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); -+ CHECK(dns_db_findnode(db, name, ISC_TRUE, &node)); -+ CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); -+ cleanup: -+ if (node != NULL) -+ dns_db_detachnode(db, &node); -+ return (result); -+} -+ -+/* -+ * Driver-specific implementation of dns_db_create(). -+ * -+ * @param[in] argv Database-specific parameters from dns_db_create(). -+ * @param[in] driverarg Driver-specific parameter from dns_db_register(). -+ */ -+isc_result_t -+create_db(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, -+ dns_rdataclass_t rdclass, unsigned int argc, char *argv[], -+ void *driverarg, dns_db_t **dbp) -+{ -+ sampledb_t *sampledb = NULL; -+ isc_result_t result; -+ dns_dbversion_t *version = NULL; -+ struct in_addr a_addr; -+ -+ REQUIRE(type == dns_dbtype_zone); -+ REQUIRE(rdclass == dns_rdataclass_in); -+ REQUIRE(argc == 0); -+ REQUIRE(argv != NULL); -+ REQUIRE(driverarg != NULL); /* pointer to driver instance */ -+ REQUIRE(dbp != NULL && *dbp == NULL); -+ -+ UNUSED(driverarg); /* no driver-specific configuration */ -+ -+ a_addr.s_addr = 0x0100007fU; -+ -+ CHECKED_MEM_GET_PTR(mctx, sampledb); -+ ZERO_PTR(sampledb); -+ -+ isc_mem_attach(mctx, &sampledb->common.mctx); -+ dns_name_init(&sampledb->common.origin, NULL); -+ isc_ondestroy_init(&sampledb->common.ondest); -+ -+ sampledb->common.magic = DNS_DB_MAGIC; -+ sampledb->common.impmagic = SAMPLEDB_MAGIC; -+ -+ sampledb->common.methods = &sampledb_methods; -+ sampledb->common.attributes = 0; -+ sampledb->common.rdclass = rdclass; -+ -+ CHECK(dns_name_dupwithoffsets(origin, mctx, &sampledb->common.origin)); -+ -+ CHECK(isc_refcount_init(&sampledb->refs, 1)); -+ -+ /* Translate instance name to instance pointer. */ -+ sampledb->inst = driverarg; -+ -+ /* Create internal instance of RBT DB implementation from BIND. */ -+ CHECK(dns_db_create(mctx, "rbt", origin, dns_dbtype_zone, -+ dns_rdataclass_in, 0, NULL, &sampledb->rbtdb)); -+ -+ /* Create fake SOA, NS, and A records to make database loadable. */ -+ CHECK(dns_db_newversion(sampledb->rbtdb, &version)); -+ CHECK(add_soa(sampledb->rbtdb, version, origin, origin, origin)); -+ CHECK(add_ns(sampledb->rbtdb, version, origin, origin)); -+ CHECK(add_a(sampledb->rbtdb, version, origin, a_addr)); -+ dns_db_closeversion(sampledb->rbtdb, &version, ISC_TRUE); -+ -+ *dbp = (dns_db_t *)sampledb; -+ -+ return (ISC_R_SUCCESS); -+ -+cleanup: -+ if (sampledb != NULL) { -+ if (dns_name_dynamic(&sampledb->common.origin)) -+ dns_name_free(&sampledb->common.origin, mctx); -+ -+ isc_mem_putanddetach(&sampledb->common.mctx, sampledb, -+ sizeof(*sampledb)); -+ } -+ -+ return (result); -+} -diff --git a/bin/tests/system/dyndb/driver/db.h b/bin/tests/system/dyndb/driver/db.h -new file mode 100644 -index 0000000..80693a7 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/db.h -@@ -0,0 +1,15 @@ -+/** -+ * Database API implementation. -+ * -+ * Copyright (C) 2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#ifndef DB_H_ -+#define DB_H_ -+ -+isc_result_t -+create_db(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type, -+ dns_rdataclass_t rdclass, unsigned int argc, char *argv[], -+ void *driverarg, dns_db_t **dbp); -+ -+#endif /* DB_H_ */ -diff --git a/bin/tests/system/dyndb/driver/driver.c b/bin/tests/system/dyndb/driver/driver.c -new file mode 100644 -index 0000000..11e6743 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/driver.c -@@ -0,0 +1,143 @@ -+/* -+ * Driver API implementation and main entry point for BIND. -+ * -+ * BIND calls dyndb_version() before loading, dyndb_init() during startup -+ * and dyndb_destroy() during shutdown. -+ * -+ * It is completely up to implementation what to do. -+ * -+ * dyndb {} sections in named.conf are independent so -+ * driver init() and destroy() functions are called independently for -+ * each section even if they reference the same driver/library. It is -+ * up to driver implementation to detect and catch this situation if -+ * it is undesirable. -+ * -+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "db.h" -+#include "log.h" -+#include "instance.h" -+#include "util.h" -+ -+dns_dyndb_destroy_t dyndb_destroy; -+dns_dyndb_register_t dyndb_init; -+dns_dyndb_version_t dyndb_version; -+ -+/* -+ * Driver init is called for each dyndb section in named.conf -+ * once during startup and then again on every reload. -+ * -+ * @code -+ * dyndb example-name "sample.so" { param1 param2 }; -+ * @endcode -+ * -+ * @param[in] name User-defined string from dyndb "name" {}; definition -+ * in named.conf. -+ * The example above will have name = "example-name". -+ * @param[in] parameters User-defined parameters from dyndb section as one -+ * string. The example above will have -+ * params = "param1 param2"; -+ * @param[in] file The name of the file from which the parameters -+ * were read. -+ * @param[in] line The line number from which the parameters were read. -+ * @param[out] instp Pointer to instance-specific data -+ * (for one dyndb section). -+ */ -+isc_result_t -+dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters, -+ const char *file, unsigned long line, -+ const dns_dyndbctx_t *dctx, void **instp) -+{ -+ isc_result_t result; -+ unsigned int argc; -+ char **argv = NULL; -+ char *s = NULL; -+ sample_instance_t *sample_inst = NULL; -+ -+ REQUIRE(name != NULL); -+ REQUIRE(dctx != NULL); -+ -+ /* -+ * Depending on how dlopen() was called, we may not have -+ * access to named's global namespace, in which case we need -+ * to initialize libisc/libdns -+ */ -+ if (dctx->refvar != &isc_lctx) { -+ isc_log_setcontext(dctx->lctx); -+ dns_log_setcontext(dctx->lctx); -+ } -+ -+ if (isc_hashctx != NULL && isc_hashctx != dctx->hctx) -+ isc_hash_ctxdetach(&isc_hashctx); -+ isc_hashctx = dctx->hctx; -+ -+ s = isc_mem_strdup(mctx, parameters); -+ if (s == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup; -+ } -+ -+ result = isc_commandline_strtoargv(mctx, s, &argc, &argv, 0); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup; -+ -+ log_write(ISC_LOG_DEBUG(9), -+ "loading params for dyndb '%s' from %s:%lu", -+ name, file, line); -+ -+ /* Finally, create the instance. */ -+ CHECK(new_sample_instance(mctx, name, argc, argv, dctx, &sample_inst)); -+ -+ /* -+ * This is an example so we create and load zones -+ * right now. This step can be arbitrarily postponed. -+ */ -+ CHECK(load_sample_instance_zones(sample_inst)); -+ -+ *instp = sample_inst; -+ -+ cleanup: -+ if (s != NULL) -+ isc_mem_free(mctx, s); -+ if (argv != NULL) -+ isc_mem_put(mctx, argv, argc * sizeof(*argv)); -+ -+ return (result); -+} -+ -+/* -+ * Driver destroy is called for every instance on every reload and then once -+ * during shutdown. -+ * -+ * @param[out] instp Pointer to instance-specific data (for one dyndb section). -+ */ -+void -+dyndb_destroy(void **instp) { -+ destroy_sample_instance((sample_instance_t **)instp); -+} -+ -+/* -+ * Driver version is called when loading the driver to ensure there -+ * is no API mismatch betwen the driver and the caller. -+ */ -+int -+dyndb_version(unsigned int *flags) { -+ UNUSED(flags); -+ -+ return (DNS_DYNDB_VERSION); -+} -diff --git a/bin/tests/system/dyndb/driver/instance.c b/bin/tests/system/dyndb/driver/instance.c -new file mode 100644 -index 0000000..f2207b9 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/instance.c -@@ -0,0 +1,161 @@ -+/* -+ * Driver instance object. -+ * -+ * One instance is equivalent to dynamic-db section in named.conf. -+ * This module parses arguments and provide high-level operations -+ * instance init/zone load/instance destroy. -+ * -+ * Copyright (C) 2008-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "db.h" -+#include "util.h" -+#include "instance.h" -+#include "log.h" -+#include "zone.h" -+ -+/* -+ * Parse parameters and convert them to zone names. Caller has to deallocate -+ * resulting DNS names. -+ * -+ * @param[in] argv NULL-terminated string array of length 2 (excluding NULL) -+ * Each string has to be a valid DNS name. -+ * @param[out] z1 Zone name from argv[0] -+ * @param[out] z2 Zone name from argv[1] -+ */ -+static isc_result_t -+parse_params(isc_mem_t *mctx, int argc, char **argv, -+ dns_name_t *z1, dns_name_t *z2) -+{ -+ isc_result_t result; -+ int i; -+ -+ REQUIRE(argv != NULL); -+ REQUIRE(z1 != NULL); -+ REQUIRE(z2 != NULL); -+ -+ for (i = 0; i < argc; i++) { -+ log_info("param: '%s'", argv[i]); -+ } -+ log_info("number of params: %d", i); -+ -+ if (argc != 2) { -+ log_error("exactly two parameters " -+ "(absolute zone names) are required"); -+ result = ISC_R_FAILURE; -+ goto cleanup; -+ } -+ CHECK(dns_name_fromstring2(z1, argv[0], dns_rootname, 0, mctx)); -+ CHECK(dns_name_fromstring2(z2, argv[1], dns_rootname, 0, mctx)); -+ -+ result = ISC_R_SUCCESS; -+ -+cleanup: -+ return (result); -+} -+ -+/* -+ * Initialize new driver instance. It will not create zones until -+ * load_sample_instance_zones() is called. -+ */ -+isc_result_t -+new_sample_instance(isc_mem_t *mctx, const char *db_name, -+ int argc, char **argv, const dns_dyndbctx_t *dctx, -+ sample_instance_t **sample_instp) -+{ -+ isc_result_t result; -+ sample_instance_t *inst = NULL; -+ -+ REQUIRE(sample_instp != NULL && *sample_instp == NULL); -+ -+ CHECKED_MEM_GET_PTR(mctx, inst); -+ ZERO_PTR(inst); -+ isc_mem_attach(mctx, &inst->mctx); -+ -+ inst->db_name = isc_mem_strdup(mctx, db_name); -+ if (inst->db_name == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup; -+ } -+ -+ dns_fixedname_init(&inst->zone1_fn); -+ inst->zone1_name = dns_fixedname_name(&inst->zone1_fn); -+ -+ dns_fixedname_init(&inst->zone2_fn); -+ inst->zone2_name = dns_fixedname_name(&inst->zone2_fn); -+ -+ CHECK(parse_params(mctx, argc, argv, -+ inst->zone1_name, inst->zone2_name)); -+ -+ dns_view_attach(dctx->view, &inst->view); -+ dns_zonemgr_attach(dctx->zmgr, &inst->zmgr); -+ isc_task_attach(dctx->task, &inst->task); -+ -+ /* Register new DNS DB implementation. */ -+ CHECK(dns_db_register(db_name, create_db, inst, mctx, &inst->db_imp)); -+ -+ *sample_instp = inst; -+ result = ISC_R_SUCCESS; -+ -+cleanup: -+ if (result != ISC_R_SUCCESS) -+ destroy_sample_instance(&inst); -+ return (result); -+} -+ -+/* -+ * Create empty zones, add fake SOA, NS, and A records, load fake zones -+ * and add them to inst->view. -+ */ -+isc_result_t -+load_sample_instance_zones(sample_instance_t *inst) { -+ isc_result_t result; -+ -+ CHECK(create_zone(inst, inst->zone1_name, &inst->zone1)); -+ CHECK(activate_zone(inst, inst->zone1)); -+ -+ CHECK(create_zone(inst, inst->zone2_name, &inst->zone2)); -+ CHECK(activate_zone(inst, inst->zone2)); -+ -+cleanup: -+ return (result); -+} -+ -+void -+destroy_sample_instance(sample_instance_t **instp) { -+ sample_instance_t *inst; -+ REQUIRE(instp != NULL); -+ -+ inst = *instp; -+ if (inst == NULL) -+ return; -+ -+ if (inst->db_name != NULL) -+ isc_mem_free(inst->mctx, inst->db_name); -+ if (inst->zone1 != NULL) -+ dns_zone_detach(&inst->zone1); -+ if (inst->zone2 != NULL) -+ dns_zone_detach(&inst->zone2); -+ if (inst->db_imp != NULL) -+ dns_db_unregister(&inst->db_imp); -+ -+ dns_view_detach(&inst->view); -+ dns_zonemgr_detach(&inst->zmgr); -+ isc_task_detach(&inst->task); -+ -+ MEM_PUT_AND_DETACH(inst); -+ -+ *instp = NULL; -+} -diff --git a/bin/tests/system/dyndb/driver/instance.h b/bin/tests/system/dyndb/driver/instance.h -new file mode 100644 -index 0000000..ff0f5c3 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/instance.h -@@ -0,0 +1,47 @@ -+/** -+ * Driver instance object. -+ * -+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#ifndef _LD_INSTANCE_H_ -+#define _LD_INSTANCE_H_ -+ -+#include -+#include -+#include -+ -+struct sample_instance { -+ isc_mem_t *mctx; -+ char *db_name; -+ dns_dbimplementation_t *db_imp; -+ -+ /* These are needed for zone creation. */ -+ dns_view_t *view; -+ dns_zonemgr_t *zmgr; -+ isc_task_t *task; -+ isc_boolean_t exiting; -+ -+ dns_zone_t *zone1; -+ dns_fixedname_t zone1_fn; -+ dns_name_t *zone1_name; -+ -+ dns_zone_t *zone2; -+ dns_fixedname_t zone2_fn; -+ dns_name_t *zone2_name; -+}; -+ -+typedef struct sample_instance sample_instance_t; -+ -+isc_result_t -+new_sample_instance(isc_mem_t *mctx, const char *db_name, -+ int argc, char **argv, const dns_dyndbctx_t *dctx, -+ sample_instance_t **sample_instp); -+ -+isc_result_t -+load_sample_instance_zones(sample_instance_t *inst); -+ -+void -+destroy_sample_instance(sample_instance_t **sample_instp); -+ -+#endif /* !_LD_INSTANCE_H_ */ -diff --git a/bin/tests/system/dyndb/driver/lock.c b/bin/tests/system/dyndb/driver/lock.c -new file mode 100644 -index 0000000..c97c490 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/lock.c -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#include -+ -+#include -+#include -+ -+#include "lock.h" -+ -+/* -+ * Lock BIND dispatcher and allow only single task to run. -+ * -+ * @warning -+ * All calls to isc_task_beginexclusive() have to operate on the same task -+ * otherwise it would not be possible to distinguish recursive locking -+ * from real conflict on the dispatcher lock. -+ * For this reason this wrapper function always works with inst->task. -+ * As a result, this function have to be be called only from inst->task. -+ * -+ * Recursive locking is allowed. Auxiliary variable pointed to by "statep" -+ * stores information if last run_exclusive_enter() operation really locked -+ * something or if the lock was called recursively and was no-op. -+ * -+ * The pair (inst, state) used for run_exclusive_enter() has to be -+ * used for run_exclusive_exit(). -+ * -+ * @param[in] inst The instance with the only task which is allowed to run. -+ * @param[in,out] statep Lock state: ISC_R_SUCCESS or ISC_R_LOCKBUSY -+ */ -+void -+run_exclusive_enter(sample_instance_t *inst, isc_result_t *statep) { -+ REQUIRE(statep != NULL); -+ REQUIRE(*statep == ISC_R_IGNORE); -+ -+ *statep = isc_task_beginexclusive(inst->task); -+ RUNTIME_CHECK(*statep == ISC_R_SUCCESS || *statep == ISC_R_LOCKBUSY); -+} -+ -+/* -+ * Exit task-exclusive mode. -+ * -+ * @param[in] inst The instance used for previous run_exclusive_enter() call. -+ * @param[in] state Lock state as returned by run_exclusive_enter(). -+ */ -+void -+run_exclusive_exit(sample_instance_t *inst, isc_result_t state) { -+ if (state == ISC_R_SUCCESS) -+ isc_task_endexclusive(inst->task); -+ else -+ /* Unlocking recursive lock or the lock was never locked. */ -+ INSIST(state == ISC_R_LOCKBUSY || state == ISC_R_IGNORE); -+ -+ return; -+} -diff --git a/bin/tests/system/dyndb/driver/lock.h b/bin/tests/system/dyndb/driver/lock.h -new file mode 100644 -index 0000000..35c9c84 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/lock.h -@@ -0,0 +1,17 @@ -+/* -+ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#ifndef LOCK_H_ -+#define LOCK_H_ -+ -+#include "instance.h" -+#include "util.h" -+ -+void -+run_exclusive_enter(sample_instance_t *inst, isc_result_t *statep); -+ -+void -+run_exclusive_exit(sample_instance_t *inst, isc_result_t state); -+ -+#endif /* LOCK_H_ */ -diff --git a/bin/tests/system/dyndb/driver/log.c b/bin/tests/system/dyndb/driver/log.c -new file mode 100644 -index 0000000..2238c7e ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/log.c -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#include -+ -+#include -+ -+#include -+ -+#include "log.h" -+ -+void -+log_write(int level, const char *format, ...) { -+ va_list args; -+ -+ va_start(args, format); -+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB, -+ level, format, args); -+ va_end(args); -+} -diff --git a/bin/tests/system/dyndb/driver/log.h b/bin/tests/system/dyndb/driver/log.h -new file mode 100644 -index 0000000..27b38c8 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/log.h -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2009--2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#ifndef _LD_LOG_H_ -+#define _LD_LOG_H_ -+ -+#include -+#include -+#include -+ -+#define fatal_error(...) \ -+ isc_error_fatal(__FILE__, __LINE__, __VA_ARGS__) -+ -+#define log_error_r(fmt, ...) \ -+ log_error(fmt ": %s", ##__VA_ARGS__, dns_result_totext(result)) -+ -+#define log_error(format, ...) \ -+ log_write(ISC_LOG_ERROR, format, ##__VA_ARGS__) -+ -+#define log_info(format, ...) \ -+ log_write(ISC_LOG_INFO, format, ##__VA_ARGS__) -+ -+void -+log_write(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); -+ -+#endif /* !_LD_LOG_H_ */ -diff --git a/bin/tests/system/dyndb/driver/syncptr.c b/bin/tests/system/dyndb/driver/syncptr.c -new file mode 100644 -index 0000000..2191bae ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/syncptr.c -@@ -0,0 +1,265 @@ -+/* -+ * Automatic A/AAAA/PTR record synchronization. -+ * -+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "instance.h" -+#include "syncptr.h" -+#include "util.h" -+ -+/* Almost random value. See eventclass.h */ -+#define SYNCPTR_WRITE_EVENT (ISC_EVENTCLASS(1025) + 1) -+ -+/* -+ * Event used for making changes to reverse zones. -+ */ -+typedef struct syncptrevent syncptrevent_t; -+struct syncptrevent { -+ ISC_EVENT_COMMON(syncptrevent_t); -+ isc_mem_t *mctx; -+ dns_zone_t *zone; -+ dns_diff_t diff; -+ dns_fixedname_t ptr_target_name; /* referenced by owner name in tuple */ -+ isc_buffer_t b; /* referenced by target name in tuple */ -+ unsigned char buf[DNS_NAME_MAXWIRE]; -+}; -+ -+/* -+ * Write diff generated in syncptr() to reverse zone. -+ * -+ * This function will be called asynchronously and syncptr() will not get -+ * any result from it. -+ * -+ */ -+static void -+syncptr_write(isc_task_t *task, isc_event_t *event) { -+ syncptrevent_t *pevent = (syncptrevent_t *)event; -+ dns_dbversion_t *version = NULL; -+ dns_db_t *db = NULL; -+ isc_result_t result; -+ -+ REQUIRE(event->ev_type == SYNCPTR_WRITE_EVENT); -+ -+ UNUSED(task); -+ -+ CHECK(dns_zone_getdb(pevent->zone, &db)); -+ CHECK(dns_db_newversion(db, &version)); -+ CHECK(dns_diff_apply(&pevent->diff, db, version)); -+ -+cleanup: -+ if (db != NULL) { -+ if (version != NULL) -+ dns_db_closeversion(db, &version, ISC_TRUE); -+ dns_db_detach(&db); -+ } -+ dns_zone_detach(&pevent->zone); -+ dns_diff_clear(&pevent->diff); -+ isc_event_free(&event); -+} -+ -+/* -+ * Find a reverse zone for given IP address. -+ * -+ * @param[in] rdata IP address as A/AAAA record -+ * @param[out] name Owner name for the PTR record -+ * @param[out] zone DNS zone for reverse record matching the IP address -+ * -+ * @retval ISC_R_SUCCESS DNS name derived from given IP address belongs to an -+ * reverse zone managed by this driver instance. -+ * PTR record synchronization can continue. -+ * @retval ISC_R_NOTFOUND Suitable reverse zone was not found because it -+ * does not exist or is not managed by this driver. -+ */ -+static isc_result_t -+syncptr_find_zone(sample_instance_t *inst, dns_rdata_t *rdata, -+ dns_name_t *name, dns_zone_t **zone) -+{ -+ isc_result_t result; -+ isc_netaddr_t isc_ip; /* internal net address representation */ -+ dns_rdata_in_a_t ipv4; -+ dns_rdata_in_aaaa_t ipv6; -+ -+ REQUIRE(inst != NULL); -+ REQUIRE(zone != NULL && *zone == NULL); -+ -+ switch (rdata->type) { -+ case dns_rdatatype_a: -+ CHECK(dns_rdata_tostruct(rdata, &ipv4, inst->mctx)); -+ isc_netaddr_fromin(&isc_ip, &ipv4.in_addr); -+ break; -+ -+ case dns_rdatatype_aaaa: -+ CHECK(dns_rdata_tostruct(rdata, &ipv6, inst->mctx)); -+ isc_netaddr_fromin6(&isc_ip, &ipv6.in6_addr); -+ break; -+ -+ default: -+ fatal_error("unsupported address type 0x%x", rdata->type); -+ break; -+ } -+ -+ /* -+ * Convert IP address to PTR owner name. -+ * -+ * @example -+ * 192.168.0.1 -> 1.0.168.192.in-addr.arpa -+ */ -+ CHECK(dns_byaddr_createptrname2(&isc_ip, 0, name)); -+ -+ /* Find a zone containing owner name of the PTR record. */ -+ result = dns_zt_find(inst->view->zonetable, name, 0, NULL, zone); -+ if (result == DNS_R_PARTIALMATCH) -+ result = ISC_R_SUCCESS; -+ else if (result != ISC_R_SUCCESS) -+ goto cleanup; -+ -+ /* Make sure that the zone is managed by this driver. */ -+ if (*zone != inst->zone1 && *zone != inst->zone2) { -+ dns_zone_detach(zone); -+ result = ISC_R_NOTFOUND; -+ } -+ -+cleanup: -+ if (rdata->type == dns_rdatatype_a) -+ dns_rdata_freestruct(&ipv4); -+ else -+ dns_rdata_freestruct(&ipv6); -+ -+ return (result); -+} -+ -+/* -+ * Generate update event for PTR record to reflect change in A/AAAA record. -+ * -+ * @pre Reverse zone is managed by this driver. -+ * -+ * @param[in] a_name DNS domain of modified A/AAAA record -+ * @param[in] af Address family -+ * @param[in] ip_str IP address as a string (IPv4 or IPv6) -+ * @param[in] mod_op LDAP_MOD_DELETE if A/AAAA record is being deleted -+ * or LDAP_MOD_ADD if A/AAAA record is being added. -+ * -+ * @retval ISC_R_SUCCESS Event for PTR record update was generated and send. -+ * Change to reverse zone will be done asynchronously. -+ * @retval other Synchronization failed - reverse doesn't exist, -+ * is not managed by this driver instance, -+ * memory allocation error, etc. -+ */ -+static isc_result_t -+syncptr(sample_instance_t *inst, dns_name_t *name, -+ dns_rdata_t *addr_rdata, dns_ttl_t ttl, dns_diffop_t op) -+{ -+ isc_result_t result; -+ isc_mem_t *mctx = inst->mctx; -+ dns_fixedname_t ptr_name; -+ dns_zone_t *ptr_zone = NULL; -+ dns_rdata_ptr_t ptr_struct; -+ dns_rdata_t ptr_rdata = DNS_RDATA_INIT; -+ dns_difftuple_t *tp = NULL; -+ isc_task_t *task = NULL; -+ syncptrevent_t *pevent = NULL; -+ -+ dns_fixedname_init(&ptr_name); -+ DNS_RDATACOMMON_INIT(&ptr_struct, dns_rdatatype_ptr, dns_rdataclass_in); -+ dns_name_init(&ptr_struct.ptr, NULL); -+ -+ pevent = (syncptrevent_t *)isc_event_allocate(inst->mctx, inst, -+ SYNCPTR_WRITE_EVENT, -+ syncptr_write, NULL, -+ sizeof(syncptrevent_t)); -+ if (pevent == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup; -+ } -+ isc_buffer_init(&pevent->b, pevent->buf, sizeof(pevent->buf)); -+ dns_fixedname_init(&pevent->ptr_target_name); -+ -+ /* Check if reverse zone is managed by this driver */ -+ result = syncptr_find_zone(inst, addr_rdata, -+ dns_fixedname_name(&ptr_name), &ptr_zone); -+ if (result != ISC_R_SUCCESS) { -+ log_error_r("PTR record synchonization skipped: reverse zone " -+ "is not managed by driver instance '%s'", -+ inst->db_name); -+ goto cleanup; -+ } -+ -+ /* Reverse zone is managed by this driver, prepare PTR record */ -+ pevent->zone = NULL; -+ dns_zone_attach(ptr_zone, &pevent->zone); -+ CHECK(dns_name_copy(name, dns_fixedname_name(&pevent->ptr_target_name), -+ NULL)); -+ dns_name_clone(dns_fixedname_name(&pevent->ptr_target_name), -+ &ptr_struct.ptr); -+ dns_diff_init(inst->mctx, &pevent->diff); -+ CHECK(dns_rdata_fromstruct(&ptr_rdata, dns_rdataclass_in, -+ dns_rdatatype_ptr, &ptr_struct, &pevent->b)); -+ -+ /* Create diff */ -+ CHECK(dns_difftuple_create(mctx, op, dns_fixedname_name(&ptr_name), -+ ttl, &ptr_rdata, &tp)); -+ dns_diff_append(&pevent->diff, &tp); -+ -+ /* -+ * Send update event to the reverse zone. -+ * It will be processed asynchronously. -+ */ -+ dns_zone_gettask(ptr_zone, &task); -+ isc_task_send(task, (isc_event_t **)&pevent); -+ -+cleanup: -+ if (ptr_zone != NULL) -+ dns_zone_detach(&ptr_zone); -+ if (tp != NULL) -+ dns_difftuple_free(&tp); -+ if (task != NULL) -+ isc_task_detach(&task); -+ if (pevent != NULL) -+ isc_event_free((isc_event_t **)&pevent); -+ -+ return (result); -+} -+ -+/* -+ * Generate update event for every rdata in rdataset. -+ * -+ * @param[in] name Owner name for A/AAAA records in rdataset. -+ * @param[in] rdataset A/AAAA records. -+ * @param[in] op DNS_DIFFOP_ADD / DNS_DIFFOP_DEL for adding / deleting -+ * the rdata -+ */ -+isc_result_t -+syncptrs(sample_instance_t *inst, dns_name_t *name, -+ dns_rdataset_t *rdataset, dns_diffop_t op) -+{ -+ isc_result_t result; -+ dns_rdata_t rdata = DNS_RDATA_INIT; -+ -+ for (result = dns_rdataset_first(rdataset); -+ result == ISC_R_SUCCESS; -+ result = dns_rdataset_next(rdataset)) { -+ dns_rdataset_current(rdataset, &rdata); -+ result = syncptr(inst, name, &rdata, rdataset->ttl, op); -+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) -+ goto cleanup; -+ } -+ if (result == ISC_R_NOMORE) -+ result = ISC_R_SUCCESS; -+ -+cleanup: -+ return (result); -+} -diff --git a/bin/tests/system/dyndb/driver/syncptr.h b/bin/tests/system/dyndb/driver/syncptr.h -new file mode 100644 -index 0000000..2f9b3a6 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/syncptr.h -@@ -0,0 +1,15 @@ -+/* -+ * Sync PTR records -+ * -+ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#ifndef SYNCPTR_H_ -+#define SYNCPTR_H_ -+ -+#include -+isc_result_t -+syncptrs(sample_instance_t *inst, dns_name_t *name, dns_rdataset_t *rdataset, -+ dns_diffop_t op); -+ -+#endif /* SYNCPTR_H_ */ -diff --git a/bin/tests/system/dyndb/driver/util.h b/bin/tests/system/dyndb/driver/util.h -new file mode 100644 -index 0000000..2a00fe3 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/util.h -@@ -0,0 +1,57 @@ -+/* -+ * Memory allocation and error handling utilities. -+ * -+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#ifndef _LD_UTIL_H_ -+#define _LD_UTIL_H_ -+ -+#include -+#include -+ -+#include "log.h" -+ -+#define CLEANUP_WITH(result_code) \ -+ do { \ -+ result = (result_code); \ -+ goto cleanup; \ -+ } while(0) -+ -+#define CHECK(op) \ -+ do { \ -+ result = (op); \ -+ if (result != ISC_R_SUCCESS) \ -+ goto cleanup; \ -+ } while (0) -+ -+#define CHECKED_MEM_GET(m, target_ptr, s) \ -+ do { \ -+ (target_ptr) = isc_mem_get((m), (s)); \ -+ if ((target_ptr) == NULL) { \ -+ result = ISC_R_NOMEMORY; \ -+ log_error("Memory allocation failed"); \ -+ goto cleanup; \ -+ } \ -+ } while (0) -+ -+#define CHECKED_MEM_GET_PTR(m, target_ptr) \ -+ CHECKED_MEM_GET(m, target_ptr, sizeof(*(target_ptr))) -+ -+#define CHECKED_MEM_STRDUP(m, source, target) \ -+ do { \ -+ (target) = isc_mem_strdup((m), (source)); \ -+ if ((target) == NULL) { \ -+ result = ISC_R_NOMEMORY; \ -+ log_error("Memory allocation failed"); \ -+ goto cleanup; \ -+ } \ -+ } while (0) -+ -+#define ZERO_PTR(ptr) memset((ptr), 0, sizeof(*(ptr))) -+ -+#define MEM_PUT_AND_DETACH(target_ptr) \ -+ isc_mem_putanddetach(&(target_ptr)->mctx, target_ptr, \ -+ sizeof(*(target_ptr))) -+ -+#endif /* !_LD_UTIL_H_ */ -diff --git a/bin/tests/system/dyndb/driver/zone.c b/bin/tests/system/dyndb/driver/zone.c -new file mode 100644 -index 0000000..88bd967 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/zone.c -@@ -0,0 +1,192 @@ -+/* -+ * Zone management. -+ * -+ * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "util.h" -+#include "instance.h" -+#include "lock.h" -+#include "log.h" -+#include "zone.h" -+ -+extern const char *impname; -+ -+/* -+ * Create a new zone with origin 'name'. The zone stay invisible to clients -+ * until it is explicitly added to a view. -+ */ -+isc_result_t -+create_zone(sample_instance_t * const inst, dns_name_t * const name, -+ dns_zone_t ** const rawp) -+{ -+ isc_result_t result; -+ dns_zone_t *raw = NULL; -+ const char *zone_argv[1]; -+ char zone_name[DNS_NAME_FORMATSIZE]; -+ dns_acl_t *acl_any = NULL; -+ -+ REQUIRE(inst != NULL); -+ REQUIRE(name != NULL); -+ REQUIRE(rawp != NULL && *rawp == NULL); -+ -+ zone_argv[0] = inst->db_name; -+ -+ log_info("debug isc_mem_debugging(%p)=%X", &isc_mem_debugging, isc_mem_debugging); -+ CHECK(dns_zone_create(&raw, inst->mctx)); -+ CHECK(dns_zone_setorigin(raw, name)); -+ dns_zone_setclass(raw, dns_rdataclass_in); -+ dns_zone_settype(raw, dns_zone_master); -+ CHECK(dns_zone_setdbtype(raw, 1, zone_argv)); -+ CHECK(dns_zonemgr_managezone(inst->zmgr, raw)); -+ -+ /* This is completely insecure - use some sensible values instead! */ -+ CHECK(dns_acl_any(inst->mctx, &acl_any)); -+ dns_zone_setupdateacl(raw, acl_any); -+ dns_zone_setqueryacl(raw, acl_any); -+ dns_zone_setxfracl(raw, acl_any); -+ dns_acl_detach(&acl_any); -+ -+ *rawp = raw; -+ return (ISC_R_SUCCESS); -+ -+cleanup: -+ dns_name_format(name, zone_name, DNS_NAME_FORMATSIZE); -+ log_error_r("failed to create new zone '%s'", zone_name); -+ -+ if (raw != NULL) { -+ if (dns_zone_getmgr(raw) != NULL) -+ dns_zonemgr_releasezone(inst->zmgr, raw); -+ dns_zone_detach(&raw); -+ } -+ if (acl_any != NULL) -+ dns_acl_detach(&acl_any); -+ -+ return (result); -+} -+ -+/* -+ * Add zone to the view defined in inst->view. This will make the zone visible -+ * to clients. -+ */ -+static isc_result_t -+publish_zone(sample_instance_t *inst, dns_zone_t *zone) { -+ isc_result_t result; -+ isc_boolean_t freeze = ISC_FALSE; -+ dns_zone_t *zone_in_view = NULL; -+ dns_view_t *view_in_zone = NULL; -+ isc_result_t lock_state = ISC_R_IGNORE; -+ -+ REQUIRE(inst != NULL); -+ REQUIRE(zone != NULL); -+ -+ /* Return success if the zone is already in the view as expected. */ -+ result = dns_view_findzone(inst->view, dns_zone_getorigin(zone), -+ &zone_in_view); -+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) -+ goto cleanup; -+ -+ view_in_zone = dns_zone_getview(zone); -+ if (view_in_zone != NULL) { -+ /* Zone has a view set -> view should contain the same zone. */ -+ if (zone_in_view == zone) { -+ /* Zone is already published in the right view. */ -+ CLEANUP_WITH(ISC_R_SUCCESS); -+ } else if (view_in_zone != inst->view) { -+ /* -+ * Un-published inactive zone will have -+ * inst->view in zone but will not be present -+ * in the view itself. -+ */ -+ dns_zone_log(zone, ISC_LOG_ERROR, -+ "zone->view doesn't " -+ "match data in the view"); -+ CLEANUP_WITH(ISC_R_UNEXPECTED); -+ } -+ } -+ -+ if (zone_in_view != NULL) { -+ dns_zone_log(zone, ISC_LOG_ERROR, -+ "cannot publish zone: view already " -+ "contains another zone with this name"); -+ CLEANUP_WITH(ISC_R_UNEXPECTED); -+ } -+ -+ run_exclusive_enter(inst, &lock_state); -+ if (inst->view->frozen) { -+ freeze = ISC_TRUE; -+ dns_view_thaw(inst->view); -+ } -+ -+ dns_zone_setview(zone, inst->view); -+ CHECK(dns_view_addzone(inst->view, zone)); -+ -+cleanup: -+ if (zone_in_view != NULL) -+ dns_zone_detach(&zone_in_view); -+ if (freeze) -+ dns_view_freeze(inst->view); -+ run_exclusive_exit(inst, lock_state); -+ -+ return (result); -+} -+ -+/* -+ * @warning Never call this on raw part of in-line secure zone, call it only -+ * on the secure zone! -+ */ -+static isc_result_t -+load_zone(dns_zone_t *zone) { -+ isc_result_t result; -+ isc_boolean_t zone_dynamic; -+ isc_uint32_t serial; -+ -+ result = dns_zone_load(zone); -+ if (result != ISC_R_SUCCESS && result != DNS_R_UPTODATE -+ && result != DNS_R_DYNAMIC && result != DNS_R_CONTINUE) -+ goto cleanup; -+ zone_dynamic = (result == DNS_R_DYNAMIC); -+ -+ CHECK(dns_zone_getserial2(zone, &serial)); -+ dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", serial); -+ -+ if (zone_dynamic) -+ dns_zone_notify(zone); -+ -+cleanup: -+ return (result); -+} -+ -+/* -+ * Add zone to view and call dns_zone_load(). -+ */ -+isc_result_t -+activate_zone(sample_instance_t *inst, dns_zone_t *raw) { -+ isc_result_t result; -+ -+ /* -+ * Zone has to be published *before* zone load -+ * otherwise it will race with zone->view != NULL check -+ * in zone_maintenance() in zone.c. -+ */ -+ result = publish_zone(inst, raw); -+ if (result != ISC_R_SUCCESS) { -+ dns_zone_log(raw, ISC_LOG_ERROR, -+ "cannot add zone to view: %s", -+ dns_result_totext(result)); -+ goto cleanup; -+ } -+ -+ CHECK(load_zone(raw)); -+ -+cleanup: -+ return (result); -+} -diff --git a/bin/tests/system/dyndb/driver/zone.h b/bin/tests/system/dyndb/driver/zone.h -new file mode 100644 -index 0000000..a862691 ---- /dev/null -+++ b/bin/tests/system/dyndb/driver/zone.h -@@ -0,0 +1,15 @@ -+/* -+ * Copyright (C) 2014-2015 Red Hat ; see COPYRIGHT for license -+ */ -+ -+#ifndef ZONE_H_ -+#define ZONE_H_ -+ -+isc_result_t -+create_zone(sample_instance_t * const inst, dns_name_t * const name, -+ dns_zone_t ** const rawp); -+ -+isc_result_t -+activate_zone(sample_instance_t *inst, dns_zone_t *raw); -+ -+#endif /* ZONE_H_ */ -diff --git a/bin/tests/system/dyndb/ns1/named.conf b/bin/tests/system/dyndb/ns1/named.conf -new file mode 100644 -index 0000000..a4f334b ---- /dev/null -+++ b/bin/tests/system/dyndb/ns1/named.conf -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+controls { }; -+ -+options { -+ query-source address 10.53.0.1; -+ notify-source 10.53.0.1; -+ transfer-source 10.53.0.1; -+ port 5300; -+ pid-file "named.pid"; -+ session-keyfile "session.key"; -+ listen-on { 10.53.0.1; 127.0.0.1; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ notify yes; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+dyndb sample "../driver/lib/sample.so" { ipv4.example.nil. in-addr.arpa. }; -+dyndb sample2 "../driver/lib/sample.so" { ipv6.example.nil. 8.b.d.0.1.0.0.2.ip6.arpa. }; -diff --git a/bin/tests/system/dyndb/prereq.sh b/bin/tests/system/dyndb/prereq.sh -new file mode 100644 -index 0000000..fe7ef71 ---- /dev/null -+++ b/bin/tests/system/dyndb/prereq.sh -@@ -0,0 +1,21 @@ -+#!/bin/sh -+# -+# Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+../dlzexternal/dlopen || { -+ echo "I:dlopen() not supported - skipping dyndb test" -+ exit 255 -+} -+exit 0 -diff --git a/bin/tests/system/dyndb/tests.sh b/bin/tests/system/dyndb/tests.sh -new file mode 100644 -index 0000000..590b70b ---- /dev/null -+++ b/bin/tests/system/dyndb/tests.sh -@@ -0,0 +1,155 @@ -+#!/bin/sh -+# -+# Copyright (C) 2010-2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+ -+status=0 -+n=0 -+ -+DIGOPTS="@10.53.0.1 -p 5300" -+ -+newtest() { -+ n=`expr $n + 1` -+ echo "${1} (${n})" -+ ret=0 -+} -+ -+test_add() { -+ host="$1" -+ type="$2" -+ ip="$3" -+ -+ cat < ns1/update.txt -+server 10.53.0.1 5300 -+ttl 86400 -+update add $host $type $ip -+send -+EOF -+ -+ newtest "I:adding $host $type $ip" -+ $NSUPDATE ns1/update.txt > /dev/null 2>&1 || { -+ [ "$should_fail" ] || \ -+ echo "I:update failed for $host $type $ip" -+ return 1 -+ } -+ -+ out=`$DIG $DIGOPTS +noall +answer -t $type -q $host` -+ echo $out > added.a.out.$n -+ lines=`echo "$out" | grep "$ip" | wc -l` -+ [ $lines -eq 1 ] || { -+ [ "$should_fail" ] || \ -+ echo "I:dig output incorrect for $host $type $cmd: $out" -+ return 1 -+ } -+ -+ out=`$DIG $DIGOPTS +noall +answer -x $ip` -+ echo $out > added.ptr.out.$n -+ lines=`echo "$out" | grep "$host" | wc -l` -+ [ $lines -eq 1 ] || { -+ [ "$should_fail" ] || \ -+ echo "I:dig reverse output incorrect for $host $type $cmd: $out" -+ return 1 -+ } -+ -+ return 0 -+} -+ -+test_del() { -+ host="$1" -+ type="$2" -+ -+ ip=`$DIG $DIGOPTS +short $host $type` -+ -+ cat < ns1/update.txt -+server 10.53.0.1 5300 -+update del $host $type -+send -+EOF -+ -+ newtest "I:deleting $host $type (was $ip)" -+ $NSUPDATE ns1/update.txt > /dev/null 2>&1 || { -+ [ "$should_fail" ] || \ -+ echo "I:update failed deleting $host $type" -+ return 1 -+ } -+ -+ out=`$DIG $DIGOPTS +noall +answer -t $type -q $host` -+ echo $out > deleted.a.out.$n -+ lines=`echo "$out" | grep "$ip" | wc -l` -+ [ $lines -eq 0 ] || { -+ [ "$should_fail" ] || \ -+ echo "I:dig output incorrect for $host $type $cmd: $out" -+ return 1 -+ } -+ -+ out=`$DIG $DIGOPTS +noall +answer -x $ip` -+ echo $out > deleted.ptr.out.$n -+ lines=`echo "$out" | grep "$host" | wc -l` -+ [ $lines -eq 0 ] || { -+ [ "$should_fail" ] || \ -+ echo "I:dig reverse output incorrect for $host $type $cmd: $out" -+ return 1 -+ } -+ -+ return 0 -+} -+ -+test_add test1.ipv4.example.nil. A "10.53.0.10" || ret=1 -+status=`expr $status + $ret` -+ -+test_add test2.ipv4.example.nil. A "10.53.0.11" || ret=1 -+status=`expr $status + $ret` -+ -+test_add test3.ipv4.example.nil. A "10.53.0.12" || ret=1 -+status=`expr $status + $ret` -+ -+test_add test4.ipv6.example.nil. AAAA "2001:db8::1" || ret=1 -+status=`expr $status + $ret` -+ -+test_del test1.ipv4.example.nil. A || ret=1 -+status=`expr $status + $ret` -+ -+test_del test2.ipv4.example.nil. A || ret=1 -+status=`expr $status + $ret` -+ -+test_del test3.ipv4.example.nil. A || ret=1 -+status=`expr $status + $ret` -+ -+test_del test4.ipv6.example.nil. AAAA || ret=1 -+status=`expr $status + $ret` -+ -+newtest "I:checking parameter logging" -+grep "loading params for dyndb 'sample' from .*named.conf:41" ns1/named.run > /dev/null || ret=1 -+grep "loading params for dyndb 'sample2' from .*named.conf:42" ns1/named.run > /dev/null || ret=1 -+status=`expr $status + $ret` -+ -+echo "I:checking dyndb still works after reload" -+$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reload 2>&1 | sed 's/^/I:ns1 /' -+ -+test_add test5.ipv4.example.nil. A "10.53.0.10" || ret=1 -+status=`expr $status + $ret` -+ -+test_add test6.ipv6.example.nil. AAAA "2001:db8::1" || ret=1 -+status=`expr $status + $ret` -+ -+test_del test5.ipv4.example.nil. A || ret=1 -+status=`expr $status + $ret` -+ -+test_del test6.ipv6.example.nil. AAAA || ret=1 -+status=`expr $status + $ret` -+ -+exit $status -diff --git a/configure b/configure -index 2a53adf..c62da63 100755 ---- a/configure -+++ b/configure -@@ -162,7 +162,7 @@ - # - # ----------------------------------------------------------------------------- - # --# Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan -+# Copyright (c) 1997 - 2003 Kungliga Tekniska H�gskolan - # (Royal Institute of Technology, Stockholm, Sweden). - # All rights reserved. - # -@@ -19784,6 +19784,7 @@ $as_echo "#define ISC_DLZ_DLOPEN 1" >>confdefs.h - - fi - fi -+CFLAGS="$CFLAGS $SO_CFLAGS" - - - -@@ -20594,7 +20595,7 @@ ac_config_commands="$ac_config_commands chmod" - # elsewhere if there's a good reason for doing so. - # - --ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/ecdsa/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rrl/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh" -+ac_config_files="$ac_config_files make/Makefile make/mkdep Makefile bin/Makefile bin/check/Makefile bin/confgen/Makefile bin/confgen/unix/Makefile bin/dig/Makefile bin/dnssec/Makefile bin/named/Makefile bin/named/unix/Makefile bin/nsupdate/Makefile bin/pkcs11/Makefile bin/python/Makefile bin/python/dnssec-checkds.py bin/python/dnssec-coverage.py bin/rndc/Makefile bin/tests/Makefile bin/tests/atomic/Makefile bin/tests/db/Makefile bin/tests/dst/Makefile bin/tests/dst/Kdh.+002+18602.key bin/tests/dst/Kdh.+002+18602.private bin/tests/dst/Kdh.+002+48957.key bin/tests/dst/Kdh.+002+48957.private bin/tests/dst/Ktest.+001+00002.key bin/tests/dst/Ktest.+001+54622.key bin/tests/dst/Ktest.+001+54622.private bin/tests/dst/Ktest.+003+23616.key bin/tests/dst/Ktest.+003+23616.private bin/tests/dst/Ktest.+003+49667.key bin/tests/dst/dst_2_data bin/tests/dst/t2_data_1 bin/tests/dst/t2_data_2 bin/tests/dst/t2_dsasig bin/tests/dst/t2_rsasig bin/tests/hashes/Makefile bin/tests/headerdep_test.sh bin/tests/master/Makefile bin/tests/mem/Makefile bin/tests/names/Makefile bin/tests/net/Makefile bin/tests/rbt/Makefile bin/tests/resolver/Makefile bin/tests/sockaddr/Makefile bin/tests/system/Makefile bin/tests/system/conf.sh bin/tests/system/dlz/prereq.sh bin/tests/system/dlzexternal/Makefile bin/tests/system/dlzexternal/ns1/named.conf bin/tests/system/dyndb/Makefile bin/tests/system/dyndb/driver/Makefile bin/tests/system/ecdsa/prereq.sh bin/tests/system/filter-aaaa/Makefile bin/tests/system/gost/prereq.sh bin/tests/system/lwresd/Makefile bin/tests/system/rpz/Makefile bin/tests/system/rrl/Makefile bin/tests/system/rsabigexponent/Makefile bin/tests/system/tkey/Makefile bin/tests/system/tsiggss/Makefile bin/tests/tasks/Makefile bin/tests/timers/Makefile bin/tests/virtual-time/Makefile bin/tests/virtual-time/conf.sh bin/tools/Makefile contrib/check-secure-delegation.pl contrib/zone-edit.sh doc/Makefile doc/arm/Makefile doc/doxygen/Doxyfile doc/doxygen/Makefile doc/doxygen/doxygen-input-filter doc/misc/Makefile doc/xsl/Makefile doc/xsl/isc-docbook-chunk.xsl doc/xsl/isc-docbook-html.xsl doc/xsl/isc-docbook-latex.xsl doc/xsl/isc-manpage.xsl isc-config.sh lib/Makefile lib/bind9/Makefile lib/bind9/include/Makefile lib/bind9/include/bind9/Makefile lib/dns/Makefile lib/dns/include/Makefile lib/dns/include/dns/Makefile lib/dns/include/dst/Makefile lib/dns/tests/Makefile lib/export/Makefile lib/export/dns/Makefile lib/export/dns/include/Makefile lib/export/dns/include/dns/Makefile lib/export/dns/include/dst/Makefile lib/export/irs/Makefile lib/export/irs/include/Makefile lib/export/irs/include/irs/Makefile lib/export/isc/$thread_dir/Makefile lib/export/isc/$thread_dir/include/Makefile lib/export/isc/$thread_dir/include/isc/Makefile lib/export/isc/Makefile lib/export/isc/include/Makefile lib/export/isc/include/isc/Makefile lib/export/isc/nls/Makefile lib/export/isc/unix/Makefile lib/export/isc/unix/include/Makefile lib/export/isc/unix/include/isc/Makefile lib/export/isccfg/Makefile lib/export/isccfg/include/Makefile lib/export/isccfg/include/isccfg/Makefile lib/export/samples/Makefile lib/export/samples/Makefile-postinstall lib/irs/Makefile lib/irs/include/Makefile lib/irs/include/irs/Makefile lib/irs/include/irs/netdb.h lib/irs/include/irs/platform.h lib/isc/$arch/Makefile lib/isc/$arch/include/Makefile lib/isc/$arch/include/isc/Makefile lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h lib/isc/tests/Makefile lib/isc/nls/Makefile lib/isc/unix/Makefile lib/isc/unix/include/Makefile lib/isc/unix/include/isc/Makefile lib/isccc/Makefile lib/isccc/include/Makefile lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile lib/lwres/Makefile lib/lwres/include/Makefile lib/lwres/include/lwres/Makefile lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile lib/tests/Makefile lib/tests/include/Makefile lib/tests/include/tests/Makefile unit/Makefile unit/unittest.sh" - - - # -@@ -21637,6 +21638,8 @@ do - "bin/tests/system/dlz/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlz/prereq.sh" ;; - "bin/tests/system/dlzexternal/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlzexternal/Makefile" ;; - "bin/tests/system/dlzexternal/ns1/named.conf") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dlzexternal/ns1/named.conf" ;; -+ "bin/tests/system/dyndb/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dyndb/Makefile" ;; -+ "bin/tests/system/dyndb/driver/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/dyndb/driver/Makefile" ;; - "bin/tests/system/ecdsa/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/ecdsa/prereq.sh" ;; - "bin/tests/system/filter-aaaa/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/filter-aaaa/Makefile" ;; - "bin/tests/system/gost/prereq.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/gost/prereq.sh" ;; -diff --git a/configure.in b/configure.in -index 24eafb7..e8c68fc 100644 ---- a/configure.in -+++ b/configure.in -@@ -3755,6 +3755,7 @@ if test "$dlopen" = "yes"; then - [Define to allow building of objects for dlopen().]) - fi - fi -+CFLAGS="$CFLAGS $SO_CFLAGS" - - AC_SUBST(SO) - AC_SUBST(SO_CFLAGS) -@@ -3960,6 +3961,8 @@ AC_CONFIG_FILES([ - bin/tests/system/dlz/prereq.sh - bin/tests/system/dlzexternal/Makefile - bin/tests/system/dlzexternal/ns1/named.conf -+ bin/tests/system/dyndb/Makefile -+ bin/tests/system/dyndb/driver/Makefile - bin/tests/system/ecdsa/prereq.sh - bin/tests/system/filter-aaaa/Makefile - bin/tests/system/gost/prereq.sh -diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml -index bd42e11..16b50a3 100644 ---- a/doc/arm/Bv9ARM-book.xml -+++ b/doc/arm/Bv9ARM-book.xml -@@ -2384,6 +2384,8 @@ options { - - - -+ -+ - - IPv6 Support in <acronym>BIND</acronym> 9 - -diff --git a/doc/arm/dyndb.xml b/doc/arm/dyndb.xml -new file mode 100644 -index 0000000..4d92b22 ---- /dev/null -+++ b/doc/arm/dyndb.xml -@@ -0,0 +1,105 @@ -+ -+ -+ -+ -+ DynDB (Dynamic Database) -+ -+ DynDB is an extension to BIND 9 which, like DLZ -+ (see ), allows zone data to be -+ retrieved from an external database. Unlike DLZ, a DynDB module -+ provides a full-featured BIND zone database interface. Where -+ DLZ translates DNS queries into real-time database lookups, -+ resulting in relatively poor query performance, and is unable -+ to handle DNSSEC-signed data due to its limited API, a DynDB -+ module can pre-load an in-memory database from the external -+ data source, providing the same performance and functionality -+ as zones served natively by BIND. -+ -+ -+ A DynDB module supporting LDAP has been created by Red Hat -+ and is available from -+ https://fedorahosted.org/bind-dyndb-ldap/. -+ -+ -+ A sample DynDB module for testing and developer guidance -+ is included with the BIND source code, in the directory -+ bin/tests/system/dyndb/driver. -+ -+ -+ -+ Configuring DynDB -+ -+ A DynDB database is configured with a dyndb -+ statement in named.conf: -+ -+ -+ dyndb example "driver.so" { -+ parameters -+ }; -+ -+ -+ The file driver.so is a DynDB module which -+ implements the full DNS database API. Multiple -+ dyndb statements can be specified, to load -+ different drivers or multiple instances of the same driver. -+ Zones provided by a DynDB module are added to the view's zone -+ table, and are treated as normal authoritative zones when BIND -+ is responding to queries. Zone configuration is handled internally -+ by the DynDB module. -+ -+ -+ The parameters are passed as an opaque -+ string to the DynDB module's initialization routine. Configuration -+ syntax will differ depending on the driver. -+ -+ -+ -+ Sample DynDB Module -+ -+ For guidance in implementation of DynDB modules, the directory -+ bin/tests/system/dyndb/driver. -+ contains a basic DynDB module. -+ The example sets up two zones, whose names are passed -+ to the module as arguments in the dyndb -+ statement: -+ -+ -+ dyndb sample "sample.so" { example.nil. arpa. }; -+ -+ -+ In the above example, the module is configured to create a zone -+ "example.nil", which can answer queries and AXFR requests, and -+ accept DDNS updates. At runtime, prior to any updates, the zone -+ contains an SOA, NS, and a single A record at the apex: -+ -+ -+ example.nil. 86400 IN SOA example.nil. example.nil. ( -+ 0 28800 7200 604800 86400 -+ ) -+ example.nil. 86400 IN NS example.nil. -+ example.nil. 86400 IN A 127.0.0.1 -+ -+ -+ When the zone is updated dynamically, the DynDB module will determine -+ whether the updated RR is an address (i.e., type A or AAAA) and if -+ so, it will automatically update the corresponding PTR record in a -+ reverse zone. (Updates are not stored permanently; all updates are -+ lost when the server is restarted.) -+ -+ -+ -diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in -index 909250f..2efcc5a 100644 ---- a/lib/dns/Makefile.in -+++ b/lib/dns/Makefile.in -@@ -60,8 +60,8 @@ RRLOBJS = rrl.@O@ - DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ - cache.@O@ callbacks.@O@ clientinfo.@O@ compress.@O@ \ - db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \ -- dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ forward.@O@ iptable.@O@ \ -- journal.@O@ keydata.@O@ keytable.@O@ \ -+ dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ dyndb.@O@ forward.@O@ \ -+ iptable.@O@ journal.@O@ keydata.@O@ keytable.@O@ \ - lib.@O@ log.@O@ lookup.@O@ \ - master.@O@ masterdump.@O@ message.@O@ \ - name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \ -@@ -93,8 +93,8 @@ DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ @PKCS11LINKSRCS@ \ - DNSSRCS = acache.c acl.c adb.c byaddr.c \ - cache.c callbacks.c clientinfo.c compress.c \ - db.c dbiterator.c dbtable.c diff.c dispatch.c \ -- dlz.c dns64.c dnssec.c ds.c forward.c iptable.c journal.c \ -- keydata.c keytable.c lib.c log.c lookup.c \ -+ dlz.c dns64.c dnssec.c ds.c dyndb.c forward.c iptable.c \ -+ journal.c keydata.c keytable.c lib.c log.c lookup.c \ - master.c masterdump.c message.c \ - name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \ - rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \ -diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c -index 19c600c..ffcd23f 100644 ---- a/lib/dns/dlz.c -+++ b/lib/dns/dlz.c -@@ -69,6 +69,7 @@ - - - #include -+#include - #include - #include - #include -@@ -400,67 +401,6 @@ dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods, - } - - /*% -- * Helper function for dns_dlzstrtoargv(). -- * Pardon the gratuitous recursion. -- */ --static isc_result_t --dns_dlzstrtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, -- char ***argvp, unsigned int n) --{ -- isc_result_t result; -- -- restart: -- /* Discard leading whitespace. */ -- while (*s == ' ' || *s == '\t') -- s++; -- -- if (*s == '\0') { -- /* We have reached the end of the string. */ -- *argcp = n; -- *argvp = isc_mem_get(mctx, n * sizeof(char *)); -- if (*argvp == NULL) -- return (ISC_R_NOMEMORY); -- } else { -- char *p = s; -- while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') { -- if (*p == '\n') { -- *p = ' '; -- goto restart; -- } -- p++; -- } -- -- /* do "grouping", items between { and } are one arg */ -- if (*p == '{') { -- char *t = p; -- /* -- * shift all characters to left by 1 to get rid of '{' -- */ -- while (*t != '\0') { -- t++; -- *(t-1) = *t; -- } -- while (*p != '\0' && *p != '}') { -- p++; -- } -- /* get rid of '}' character */ -- if (*p == '}') { -- *p = '\0'; -- p++; -- } -- /* normal case, no "grouping" */ -- } else if (*p != '\0') -- *p++ = '\0'; -- -- result = dns_dlzstrtoargvsub(mctx, p, argcp, argvp, n + 1); -- if (result != ISC_R_SUCCESS) -- return (result); -- (*argvp)[n] = s; -- } -- return (ISC_R_SUCCESS); --} -- --/*% - * Tokenize the string "s" into whitespace-separated words, - * return the number of words in '*argcp' and an array - * of pointers to the words in '*argvp'. The caller -@@ -471,7 +411,7 @@ isc_result_t - dns_dlzstrtoargv(isc_mem_t *mctx, char *s, - unsigned int *argcp, char ***argvp) - { -- return(dns_dlzstrtoargvsub(mctx, s, argcp, argvp, 0)); -+ return(isc_commandline_strtoargv(mctx, s, argcp, argvp, 0)); - } - - /*% -diff --git a/lib/dns/dyndb.c b/lib/dns/dyndb.c -new file mode 100644 -index 0000000..76b77f0 ---- /dev/null -+++ b/lib/dns/dyndb.c -@@ -0,0 +1,486 @@ -+/* -+ * Copyright (C) 2008-2011 Red Hat, Inc. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND Red Hat DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL Red Hat BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+ -+#include -+ -+#if HAVE_DLFCN_H -+#include -+#elif _WIN32 -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define CHECK(op) \ -+ do { result = (op); \ -+ if (result != ISC_R_SUCCESS) goto cleanup; \ -+ } while (0) -+ -+ -+typedef struct dyndb_implementation dyndb_implementation_t; -+struct dyndb_implementation { -+ isc_mem_t *mctx; -+ void *handle; -+ dns_dyndb_register_t *register_func; -+ dns_dyndb_destroy_t *destroy_func; -+ char *name; -+ void *inst; -+ LINK(dyndb_implementation_t) link; -+}; -+ -+/* -+ * List of dyndb implementations. Locked by dyndb_lock. -+ * -+ * These are stored here so they can be cleaned up on shutdown. -+ * (The order in which they are stored is not important.) -+ */ -+static LIST(dyndb_implementation_t) dyndb_implementations; -+ -+/* Locks dyndb_implementations. */ -+static isc_mutex_t dyndb_lock; -+static isc_once_t once = ISC_ONCE_INIT; -+ -+static void -+dyndb_initialize(void) { -+ RUNTIME_CHECK(isc_mutex_init(&dyndb_lock) == ISC_R_SUCCESS); -+ INIT_LIST(dyndb_implementations); -+} -+ -+static dyndb_implementation_t * -+impfind(const char *name) { -+ dyndb_implementation_t *imp; -+ -+ for (imp = ISC_LIST_HEAD(dyndb_implementations); -+ imp != NULL; -+ imp = ISC_LIST_NEXT(imp, link)) -+ if (strcasecmp(name, imp->name) == 0) -+ return (imp); -+ return (NULL); -+} -+ -+#if HAVE_DLFCN_H -+static isc_result_t -+load_symbol(void *handle, const char *filename, -+ const char *symbol_name, void **symbolp) -+{ -+ const char *errmsg; -+ void *symbol; -+ -+ REQUIRE(handle != NULL); -+ REQUIRE(symbolp != NULL && *symbolp == NULL); -+ -+ symbol = dlsym(handle, symbol_name); -+ if (symbol == NULL) { -+ errmsg = dlerror(); -+ if (errmsg == NULL) -+ errmsg = "returned function pointer is NULL"; -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, -+ "failed to lookup symbol %s in " -+ "dyndb module '%s': %s", -+ symbol_name, filename, errmsg); -+ return (ISC_R_FAILURE); -+ } -+ dlerror(); -+ -+ *symbolp = symbol; -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+load_library(isc_mem_t *mctx, const char *filename, const char *instname, -+ dyndb_implementation_t **impp) -+{ -+ isc_result_t result; -+ void *handle = NULL; -+ dyndb_implementation_t *imp = NULL; -+ dns_dyndb_register_t *register_func = NULL; -+ dns_dyndb_destroy_t *destroy_func = NULL; -+ dns_dyndb_version_t *version_func = NULL; -+ int version, flags; -+ -+ REQUIRE(impp != NULL && *impp == NULL); -+ -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_INFO, -+ "loading DynDB instance '%s' driver '%s'", -+ instname, filename); -+ -+ flags = RTLD_NOW|RTLD_LOCAL; -+#if 0 -+ // Need to access the daemon variables from the plugin, not local copies -+#ifdef RTLD_DEEPBIND -+ flags |= RTLD_DEEPBIND; -+#endif -+#endif -+ -+ handle = dlopen(filename, flags); -+ if (handle == NULL) -+ CHECK(ISC_R_FAILURE); -+ -+ /* Clear dlerror */ -+ dlerror(); -+ -+ CHECK(load_symbol(handle, filename, "dyndb_version", -+ (void **)&version_func)); -+ -+ version = version_func(NULL); -+ if (version < (DNS_DYNDB_VERSION - DNS_DYNDB_AGE) || -+ version > DNS_DYNDB_VERSION) -+ { -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, -+ "driver API version mismatch: %d/%d", -+ version, DNS_DYNDB_VERSION); -+ CHECK(ISC_R_FAILURE); -+ } -+ -+ CHECK(load_symbol(handle, filename, "dyndb_init", -+ (void **)®ister_func)); -+ CHECK(load_symbol(handle, filename, "dyndb_destroy", -+ (void **)&destroy_func)); -+ -+ imp = isc_mem_get(mctx, sizeof(dyndb_implementation_t)); -+ if (imp == NULL) -+ CHECK(ISC_R_NOMEMORY); -+ -+ imp->mctx = NULL; -+ isc_mem_attach(mctx, &imp->mctx); -+ imp->handle = handle; -+ imp->register_func = register_func; -+ imp->destroy_func = destroy_func; -+ imp->name = isc_mem_strdup(mctx, instname); -+ if (imp->name == NULL) -+ CHECK(ISC_R_NOMEMORY); -+ -+ imp->inst = NULL; -+ INIT_LINK(imp, link); -+ -+ *impp = imp; -+ imp = NULL; -+ -+cleanup: -+ if (result != ISC_R_SUCCESS) -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, -+ "failed to dynamically load instance '%s' " -+ "driver '%s': %s (%s)", instname, filename, -+ dlerror(), isc_result_totext(result)); -+ if (imp != NULL) -+ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); -+ if (result != ISC_R_SUCCESS && handle != NULL) -+ dlclose(handle); -+ -+ return (result); -+} -+ -+static void -+unload_library(dyndb_implementation_t **impp) { -+ dyndb_implementation_t *imp; -+ -+ REQUIRE(impp != NULL && *impp != NULL); -+ -+ imp = *impp; -+ -+ isc_mem_free(imp->mctx, imp->name); -+ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); -+ -+ *impp = NULL; -+} -+#elif _WIN32 -+static isc_result_t -+load_symbol(HMODULE handle, const char *filename, -+ const char *symbol_name, void **symbolp) -+{ -+ void *symbol; -+ -+ REQUIRE(handle != NULL); -+ REQUIRE(symbolp != NULL && *symbolp == NULL); -+ -+ symbol = GetProcAddress(handle, symbol_name); -+ if (symbol == NULL) { -+ int errstatus = GetLastError(); -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, -+ "failed to lookup symbol %s in " -+ "dyndb module '%s': %d", -+ symbol_name, filename, errstatus); -+ return (ISC_R_FAILURE); -+ } -+ -+ *symbolp = symbol; -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+load_library(isc_mem_t *mctx, const char *filename, const char *instname, -+ dyndb_implementation_t **impp) -+{ -+ isc_result_t result; -+ HMODULE handle; -+ dyndb_implementation_t *imp = NULL; -+ dns_dyndb_register_t *register_func = NULL; -+ dns_dyndb_destroy_t *destroy_func = NULL; -+ dns_dyndb_version_t *version_func = NULL; -+ int version; -+ -+ REQUIRE(impp != NULL && *impp == NULL); -+ -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_INFO, -+ "loading DynDB instance '%s' driver '%s'", -+ instname, filename); -+ -+ handle = LoadLibraryA(filename); -+ if (handle == NULL) -+ CHECK(ISC_R_FAILURE); -+ -+ CHECK(load_symbol(handle, filename, "dyndb_version", -+ (void **)&version_func)); -+ -+ version = version_func(NULL); -+ if (version < (DNS_DYNDB_VERSION - DNS_DYNDB_AGE) || -+ version > DNS_DYNDB_VERSION) -+ { -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, -+ "driver API version mismatch: %d/%d", -+ version, DNS_DYNDB_VERSION); -+ CHECK(ISC_R_FAILURE); -+ } -+ -+ CHECK(load_symbol(handle, filename, "dyndb_init", -+ (void **)®ister_func)); -+ CHECK(load_symbol(handle, filename, "dyndb_destroy", -+ (void **)&destroy_func)); -+ -+ imp = isc_mem_get(mctx, sizeof(dyndb_implementation_t)); -+ if (imp == NULL) -+ CHECK(ISC_R_NOMEMORY); -+ -+ imp->mctx = NULL; -+ isc_mem_attach(mctx, &imp->mctx); -+ imp->handle = handle; -+ imp->register_func = register_func; -+ imp->destroy_func = destroy_func; -+ imp->name = isc_mem_strdup(mctx, instname); -+ if (imp->name == NULL) -+ CHECK(ISC_R_NOMEMORY); -+ -+ imp->inst = NULL; -+ INIT_LINK(imp, link); -+ -+ *impp = imp; -+ imp = NULL; -+ -+cleanup: -+ if (result != ISC_R_SUCCESS) -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_ERROR, -+ "failed to dynamically load instance '%s' " -+ "driver '%s': %d (%s)", instname, filename, -+ GetLastError(), isc_result_totext(result)); -+ if (imp != NULL) -+ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); -+ if (result != ISC_R_SUCCESS && handle != NULL) -+ FreeLibrary(handle); -+ -+ return (result); -+} -+ -+static void -+unload_library(dyndb_implementation_t **impp) { -+ dyndb_implementation_t *imp; -+ -+ REQUIRE(impp != NULL && *impp != NULL); -+ -+ imp = *impp; -+ -+ isc_mem_free(imp->mctx, imp->name); -+ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); -+ -+ *impp = NULL; -+} -+#else /* HAVE_DLFCN_H || _WIN32 */ -+static isc_result_t -+load_library(isc_mem_t *mctx, const char *filename, const char *instname, -+ dyndb_implementation_t **impp) -+{ -+ UNUSED(mctx); -+ UNUSED(filename); -+ UNUSED(instname); -+ UNUSED(impp); -+ -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DYNDB, -+ ISC_LOG_ERROR, -+ "dynamic database support is not implemented") -+ -+ return (ISC_R_NOTIMPLEMENTED); -+} -+ -+static void -+unload_library(dyndb_implementation_t **impp) -+{ -+ dyndb_implementation_t *imp; -+ -+ REQUIRE(impp != NULL && *impp != NULL); -+ -+ imp = *impp; -+ -+ if (imp->handle != NULL) -+ dlclose(imp->handle); -+ -+ isc_mem_putanddetach(&imp->mctx, imp, sizeof(dyndb_implementation_t)); -+ -+ *impp = NULL; -+} -+#endif /* HAVE_DLFCN_H */ -+ -+isc_result_t -+dns_dyndb_load(const char *libname, const char *name, const char *parameters, -+ const char *file, unsigned long line, isc_mem_t *mctx, -+ const dns_dyndbctx_t *dctx) -+{ -+ isc_result_t result; -+ dyndb_implementation_t *implementation = NULL; -+ -+ REQUIRE(DNS_DYNDBCTX_VALID(dctx)); -+ REQUIRE(name != NULL); -+ -+ RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS); -+ -+ LOCK(&dyndb_lock); -+ -+ /* duplicate instance names are not allowed */ -+ if (impfind(name) != NULL) -+ CHECK(ISC_R_EXISTS); -+ -+ CHECK(load_library(mctx, libname, name, &implementation)); -+ CHECK(implementation->register_func(mctx, name, parameters, file, line, -+ dctx, &implementation->inst)); -+ -+ APPEND(dyndb_implementations, implementation, link); -+ result = ISC_R_SUCCESS; -+ -+cleanup: -+ if (result != ISC_R_SUCCESS) -+ if (implementation != NULL) -+ unload_library(&implementation); -+ -+ UNLOCK(&dyndb_lock); -+ return (result); -+} -+ -+void -+dns_dyndb_cleanup(isc_boolean_t exiting) { -+ dyndb_implementation_t *elem; -+ dyndb_implementation_t *prev; -+ -+ RUNTIME_CHECK(isc_once_do(&once, dyndb_initialize) == ISC_R_SUCCESS); -+ -+ LOCK(&dyndb_lock); -+ elem = TAIL(dyndb_implementations); -+ while (elem != NULL) { -+ prev = PREV(elem, link); -+ UNLINK(dyndb_implementations, elem, link); -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, -+ DNS_LOGMODULE_DYNDB, ISC_LOG_INFO, -+ "unloading DynDB instance '%s'", elem->name); -+ elem->destroy_func(&elem->inst); -+ ENSURE(elem->inst == NULL); -+ unload_library(&elem); -+ elem = prev; -+ } -+ UNLOCK(&dyndb_lock); -+ -+ if (exiting == ISC_TRUE) -+ isc_mutex_destroy(&dyndb_lock); -+} -+ -+isc_result_t -+dns_dyndb_createctx(isc_mem_t *mctx, isc_hash_t *hctx, isc_log_t *lctx, -+ dns_view_t *view, dns_zonemgr_t *zmgr, -+ isc_task_t *task, isc_timermgr_t *tmgr, -+ dns_dyndbctx_t **dctxp) { -+ dns_dyndbctx_t *dctx; -+ -+ REQUIRE(dctxp != NULL && *dctxp == NULL); -+ -+ dctx = isc_mem_get(mctx, sizeof(*dctx)); -+ if (dctx == NULL) -+ return (ISC_R_NOMEMORY); -+ -+ memset(dctx, 0, sizeof(*dctx)); -+ if (view != NULL) -+ dns_view_attach(view, &dctx->view); -+ if (zmgr != NULL) -+ dns_zonemgr_attach(zmgr, &dctx->zmgr); -+ if (task != NULL) -+ isc_task_attach(task, &dctx->task); -+ dctx->timermgr = tmgr; -+ dctx->hctx = hctx; -+ dctx->lctx = lctx; -+ dctx->refvar = &isc_lctx; -+ -+ isc_mem_attach(mctx, &dctx->mctx); -+ dctx->magic = DNS_DYNDBCTX_MAGIC; -+ -+ *dctxp = dctx; -+ -+ return (ISC_R_SUCCESS); -+} -+ -+void -+dns_dyndb_destroyctx(dns_dyndbctx_t **dctxp) { -+ dns_dyndbctx_t *dctx; -+ -+ REQUIRE(dctxp != NULL && DNS_DYNDBCTX_VALID(*dctxp)); -+ -+ dctx = *dctxp; -+ *dctxp = NULL; -+ -+ dctx->magic = 0; -+ -+ if (dctx->view != NULL) -+ dns_view_detach(&dctx->view); -+ if (dctx->zmgr != NULL) -+ dns_zonemgr_detach(&dctx->zmgr); -+ if (dctx->task != NULL) -+ isc_task_detach(&dctx->task); -+ dctx->timermgr = NULL; -+ dctx->lctx = NULL; -+ -+ isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx)); -+} -diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in -index 832db46..a37b35e 100644 ---- a/lib/dns/include/dns/Makefile.in -+++ b/lib/dns/include/dns/Makefile.in -@@ -23,8 +23,8 @@ top_srcdir = @top_srcdir@ - - HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ - clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h \ -- dlz.h dnssec.h ds.h events.h fixedname.h iptable.h journal.h \ -- keyflags.h keytable.h keyvalues.h lib.h log.h \ -+ dlz.h dyndb.h dnssec.h ds.h events.h fixedname.h iptable.h \ -+ journal.h keyflags.h keytable.h keyvalues.h lib.h log.h \ - master.h masterdump.h message.h name.h ncache.h nsec.h \ - peer.h portlist.h private.h rbt.h rcode.h \ - rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \ -diff --git a/lib/dns/include/dns/dyndb.h b/lib/dns/include/dns/dyndb.h -new file mode 100644 -index 0000000..832ff27 ---- /dev/null -+++ b/lib/dns/include/dns/dyndb.h -@@ -0,0 +1,166 @@ -+/* -+ * Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+ * Copyright (C) 2008-2011 Red Hat, Inc. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND AUTHORS DISCLAIM ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef DNS_DYNDB_H -+#define DNS_DYNDB_H -+ -+#include -+ -+#include -+ -+ISC_LANG_BEGINDECLS -+ -+/*! -+ * \brief -+ * Context for intializing a dyndb module. -+ * -+ * This structure passes pointers to globals to which a dyndb -+ * module will need access -- the server memory context, hash -+ * context, log context, etc. The structure doesn't persist -+ * beyond configuring the dyndb module. The module's register function -+ * should attach to all reference-counted variables and its destroy -+ * function should detach from them. -+ */ -+struct dns_dyndbctx { -+ unsigned int magic; -+ isc_mem_t *mctx; -+ isc_hash_t *hctx; -+ isc_log_t *lctx; -+ dns_view_t *view; -+ dns_zonemgr_t *zmgr; -+ isc_task_t *task; -+ isc_timermgr_t *timermgr; -+ void *refvar; -+}; -+ -+#define DNS_DYNDBCTX_MAGIC ISC_MAGIC('D', 'd', 'b', 'c') -+#define DNS_DYNDBCTX_VALID(d) ISC_MAGIC_VALID(d, DNS_DYNDBCTX_MAGIC) -+ -+/* -+ * API version -+ * -+ * When the API changes, increment DNS_DYNDB_VERSION. If the -+ * change is backward-compatible (e.g., adding a new function call -+ * but not changing or removing an old one), increment DNS_DYNDB_AGE; -+ * if not, set DNS_DYNDB_AGE to 0. -+ */ -+#ifndef DNS_DYNDB_VERSION -+#define DNS_DYNDB_VERSION 1 -+#define DNS_DYNDB_AGE 0 -+#endif -+ -+typedef isc_result_t dns_dyndb_register_t(isc_mem_t *mctx, -+ const char *name, -+ const char *parameters, -+ const char *file, -+ unsigned long line, -+ const dns_dyndbctx_t *dctx, -+ void **instp); -+/*% -+ * Called when registering a new driver instance. 'name' must be unique. -+ * 'parameters' contains the driver configuration text. 'dctx' is the -+ * initialization context set up in dns_dyndb_createctx(). -+ * -+ * '*instp' must be set to the driver instance handle if the functino -+ * is successful. -+ * -+ * Returns: -+ *\li #ISC_R_SUCCESS -+ *\li #ISC_R_NOMEMORY -+ *\li Other errors are possible -+ */ -+ -+typedef void dns_dyndb_destroy_t(void **instp); -+/*% -+ * Destroy a driver instance. Dereference any reference-counted -+ * variables passed in 'dctx' and 'inst' in the register function. -+ * -+ * \c *instp must be set to \c NULL by the function before it returns. -+ */ -+ -+typedef int dns_dyndb_version_t(unsigned int *flags); -+/*% -+ * Return the API version number a dyndb module was compiled with. -+ * -+ * If the returned version number is no greater than than -+ * DNS_DYNDB_VERSION, and no less than DNS_DYNDB_VERSION - DNS_DYNDB_AGE, -+ * then the module is API-compatible with named. -+ * -+ * 'flags' is currently unused and may be NULL, but could be used in -+ * the future to pass back driver capabilities or other information. -+ */ -+ -+isc_result_t -+dns_dyndb_load(const char *libname, const char *name, const char *parameters, -+ const char *file, unsigned long line, isc_mem_t *mctx, -+ const dns_dyndbctx_t *dctx); -+/*% -+ * Load a dyndb module. -+ * -+ * This loads a dyndb module using dlopen() or equivalent, calls its register -+ * function (see dns_dyndb_register_t above), and if successful, adds -+ * the instance handle to a list of dyndb instances so it can be cleaned -+ * up later. -+ * -+ * 'file' and 'line' can be used to indicate the name of the file and -+ * the line number from which the parameters were taken, so that logged -+ * error messages, if any, will display the correct locations. -+ * -+ * Returns: -+ *\li #ISC_R_SUCCESS -+ *\li #ISC_R_NOMEMORY -+ *\li Other errors are possible -+ */ -+ -+void -+dns_dyndb_cleanup(isc_boolean_t exiting); -+/*% -+ * Shut down and destroy all running dyndb modules. -+ * -+ * 'exiting' indicates whether the server is shutting down, -+ * as opposed to merely being reconfigured. -+ */ -+ -+isc_result_t -+dns_dyndb_createctx(isc_mem_t *mctx, isc_hash_t *hctx, isc_log_t *lctx, -+ dns_view_t *view, dns_zonemgr_t *zmgr, -+ isc_task_t *task, isc_timermgr_t *tmgr, -+ dns_dyndbctx_t **dctxp); -+/*% -+ * Create a dyndb initialization context structure, with -+ * pointers to structures in the server that the dyndb module will -+ * need to access (view, zone manager, memory context, hash context, -+ * etc). This structure is expected to last only until all dyndb -+ * modules have been loaded and initialized; after that it will be -+ * destroyed with dns_dyndb_destroyctx(). -+ * -+ * Returns: -+ *\li #ISC_R_SUCCESS -+ *\li #ISC_R_NOMEMORY -+ *\li Other errors are possible -+ */ -+ -+void -+dns_dyndb_destroyctx(dns_dyndbctx_t **dctxp); -+/*% -+ * Destroys a dyndb initialization context structure; all -+ * reference-counted members are detached and the structure is freed. -+ */ -+ -+ISC_LANG_ENDDECLS -+ -+#endif /* DNS_DYNDB_H */ -diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h -index e8c8c10..a3b7e5a 100644 ---- a/lib/dns/include/dns/log.h -+++ b/lib/dns/include/dns/log.h -@@ -77,6 +77,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[]; - #define DNS_LOGMODULE_DLZ (&dns_modules[26]) - #define DNS_LOGMODULE_DNSSEC (&dns_modules[27]) - #define DNS_LOGMODULE_CRYPTO (&dns_modules[28]) -+#define DNS_LOGMODULE_DYNDB (&dns_modules[29]) - - ISC_LANG_BEGINDECLS - -diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h -index 76167c2..5dc03de 100644 ---- a/lib/dns/include/dns/types.h -+++ b/lib/dns/include/dns/types.h -@@ -60,6 +60,7 @@ typedef struct dns_dbtable dns_dbtable_t; - typedef void dns_dbversion_t; - typedef struct dns_dlzimplementation dns_dlzimplementation_t; - typedef struct dns_dlzdb dns_dlzdb_t; -+typedef struct dns_dyndbctx dns_dyndbctx_t; - typedef struct dns_sdlzimplementation dns_sdlzimplementation_t; - typedef struct dns_decompress dns_decompress_t; - typedef struct dns_dispatch dns_dispatch_t; -diff --git a/lib/dns/lib.c b/lib/dns/lib.c -index df16fa2..da86efd 100644 ---- a/lib/dns/lib.c -+++ b/lib/dns/lib.c -@@ -160,7 +160,9 @@ dns_lib_shutdown(void) { - return; - - dst_lib_destroy(); -- isc_hash_destroy(); -+ -+ if (isc_hashctx != NULL) -+ isc_hash_destroy(); - #ifndef BIND9 - dns_ecdb_unregister(&dbimp); - #endif -diff --git a/lib/dns/log.c b/lib/dns/log.c -index 75e0d79..ff9ca65 100644 ---- a/lib/dns/log.c -+++ b/lib/dns/log.c -@@ -83,6 +83,7 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = { - { "dns/dlz", 0 }, - { "dns/dnssec", 0 }, - { "dns/crypto", 0 }, -+ { "dns/dyndb", 0 }, - { NULL, 0 } - }; - -diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def -index 7661f80..5e20491 100644 ---- a/lib/dns/win32/libdns.def -+++ b/lib/dns/win32/libdns.def -@@ -230,6 +230,10 @@ dns_dnsseckey_destroy - dns_ds_buildrdata - dns_ds_digest_supported - dns_dumpctx_detach -+dns_dyndb_load -+dns_dyndb_cleanup -+dns_dyndb_createctx -+dns_dyndb_destroyctx - dns_fwdtable_add - dns_fwdtable_create - dns_fwdtable_destroy -diff --git a/lib/export/isc/Makefile.in b/lib/export/isc/Makefile.in -index a5f8bd0..4f4a9f7 100644 ---- a/lib/export/isc/Makefile.in -+++ b/lib/export/isc/Makefile.in -@@ -64,8 +64,8 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ - # Alphabetically - OBJS = @ISC_EXTRA_OBJS@ \ - assertions.@O@ backtrace.@O@ backtrace-emptytbl.@O@ base32.@O@ \ -- base64.@O@ buffer.@O@ bufferlist.@O@ counter.@O@ \ -- error.@O@ event.@O@ \ -+ base64.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \ -+ counter.@O@ error.@O@ event.@O@ \ - hash.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@ \ - inet_aton.@O@ iterated_hash.@O@ lex.@O@ lfsr.@O@ log.@O@ \ - md5.@O@ mutexblock.@O@ netaddr.@O@ netscope.@O@ \ -@@ -86,7 +86,7 @@ ISCDRIVERSRCS = mem.c task.c lib.c timer.c heap.c - - SRCS = @ISC_EXTRA_SRCS@ \ - assertions.c backtrace.c backtrace-emptytbl.c base32.c \ -- base64.c buffer.c bufferlist.c counter.c \ -+ base64.c buffer.c bufferlist.c counter.c commandline.c \ - error.c event.c \ - hash.c hex.c hmacmd5.c hmacsha.c \ - inet_aton.c iterated_hash.c lex.c log.c lfsr.c \ -diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in -index df62ec9..4d3a0af 100644 ---- a/lib/isc/Makefile.in -+++ b/lib/isc/Makefile.in -@@ -37,7 +37,7 @@ CWARNINGS = - - # Alphabetically - UNIXOBJS = @ISC_ISCIPV6_O@ @ISC_ISCPK11_API_O@ \ -- unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ \ -+ unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ unix/errno.@O@ \ - unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \ - unix/interfaceiter.@O@ unix/keyboard.@O@ unix/net.@O@ \ - unix/os.@O@ unix/resource.@O@ unix/socket.@O@ unix/stdio.@O@ \ -@@ -49,9 +49,9 @@ THREADOPTOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@ - - THREADOBJS = @THREADOPTOBJS@ @ISC_THREAD_DIR@/thread.@O@ - --WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ -- win32/fsaccess.@O@ win32/once.@O@ win32/stdtime.@O@ \ -- win32/thread.@O@ win32/time.@O@ -+WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/errno.@O@ \ -+ win32/file.@O@ win32/fsaccess.@O@ win32/once.@O@ \ -+ win32/stdtime.@O@ win32/thread.@O@ win32/time.@O@ - - # Alphabetically - OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \ -diff --git a/lib/isc/commandline.c b/lib/isc/commandline.c -index aca1203..26ad23c 100644 ---- a/lib/isc/commandline.c -+++ b/lib/isc/commandline.c -@@ -68,6 +68,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -223,3 +224,62 @@ isc_commandline_parse(int argc, char * const *argv, const char *options) { - - return (isc_commandline_option); - } -+ -+isc_result_t -+isc_commandline_strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, -+ char ***argvp, unsigned int n) -+{ -+ isc_result_t result; -+ -+ restart: -+ /* Discard leading whitespace. */ -+ while (*s == ' ' || *s == '\t') -+ s++; -+ -+ if (*s == '\0') { -+ /* We have reached the end of the string. */ -+ *argcp = n; -+ *argvp = isc_mem_get(mctx, n * sizeof(char *)); -+ if (*argvp == NULL) -+ return (ISC_R_NOMEMORY); -+ } else { -+ char *p = s; -+ while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') { -+ if (*p == '\n') { -+ *p = ' '; -+ goto restart; -+ } -+ p++; -+ } -+ -+ /* do "grouping", items between { and } are one arg */ -+ if (*p == '{') { -+ char *t = p; -+ /* -+ * shift all characters to left by 1 to get rid of '{' -+ */ -+ while (*t != '\0') { -+ t++; -+ *(t-1) = *t; -+ } -+ while (*p != '\0' && *p != '}') { -+ p++; -+ } -+ /* get rid of '}' character */ -+ if (*p == '}') { -+ *p = '\0'; -+ p++; -+ } -+ /* normal case, no "grouping" */ -+ } else if (*p != '\0') -+ *p++ = '\0'; -+ -+ result = isc_commandline_strtoargv(mctx, p, -+ argcp, argvp, n + 1); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ (*argvp)[n] = s; -+ } -+ -+ return (ISC_R_SUCCESS); -+} -diff --git a/lib/isc/hash.c b/lib/isc/hash.c -index f1d68c7..c3712e6 100644 ---- a/lib/isc/hash.c -+++ b/lib/isc/hash.c -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id: hash.c,v 1.16 2009/09/01 00:22:28 jinmei Exp $ */ -- - /*! \file - * Some portion of this code was derived from universal hash function - * libraries of Rice University. -@@ -101,7 +99,8 @@ struct isc_hash { - - static isc_mutex_t createlock; - static isc_once_t once = ISC_ONCE_INIT; --static isc_hash_t *hash = NULL; -+ -+LIBISC_EXTERNAL_DATA isc_hash_t *isc_hashctx = NULL; - - static unsigned char maptolower[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, -@@ -224,14 +223,15 @@ isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) { - isc_result_t result = ISC_R_SUCCESS; - - REQUIRE(mctx != NULL); -- INSIST(hash == NULL); -+ INSIST(isc_hashctx == NULL); - - RUNTIME_CHECK(isc_once_do(&once, initialize_lock) == ISC_R_SUCCESS); - - LOCK(&createlock); - -- if (hash == NULL) -- result = isc_hash_ctxcreate(mctx, entropy, limit, &hash); -+ if (isc_hashctx == NULL) -+ result = isc_hash_ctxcreate(mctx, entropy, limit, -+ &isc_hashctx); - - UNLOCK(&createlock); - -@@ -283,9 +283,9 @@ isc_hash_ctxinit(isc_hash_t *hctx) { - - void - isc_hash_init() { -- INSIST(hash != NULL && VALID_HASH(hash)); -+ INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx)); - -- isc_hash_ctxinit(hash); -+ isc_hash_ctxinit(isc_hashctx); - } - - void -@@ -350,12 +350,12 @@ void - isc_hash_destroy() { - unsigned int refs; - -- INSIST(hash != NULL && VALID_HASH(hash)); -+ INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx)); - -- isc_refcount_decrement(&hash->refcnt, &refs); -+ isc_refcount_decrement(&isc_hashctx->refcnt, &refs); - INSIST(refs == 0); - -- destroy(&hash); -+ destroy(&isc_hashctx); - } - - static inline unsigned int -@@ -397,8 +397,8 @@ unsigned int - isc_hash_calc(const unsigned char *key, unsigned int keylen, - isc_boolean_t case_sensitive) - { -- INSIST(hash != NULL && VALID_HASH(hash)); -- REQUIRE(keylen <= hash->limit); -+ INSIST(isc_hashctx != NULL && VALID_HASH(isc_hashctx)); -+ REQUIRE(keylen <= isc_hashctx->limit); - -- return (hash_calc(hash, key, keylen, case_sensitive)); -+ return (hash_calc(isc_hashctx, key, keylen, case_sensitive)); - } -diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in -index 38af3f9..7ca1170 100644 ---- a/lib/isc/include/isc/Makefile.in -+++ b/lib/isc/include/isc/Makefile.in -@@ -27,8 +27,8 @@ top_srcdir = @top_srcdir@ - # install target below. - # - HEADERS = app.h assertions.h base64.h bind9.h bitstring.h boolean.h \ -- buffer.h bufferlist.h commandline.h counter.h entropy.h error.h event.h \ -- eventclass.h file.h formatcheck.h fsaccess.h \ -+ buffer.h bufferlist.h commandline.h counter.h entropy.h errno.h \ -+ error.h event.h eventclass.h file.h formatcheck.h fsaccess.h \ - hash.h heap.h hex.h hmacmd5.h hmacsha.h \ - httpd.h \ - interfaceiter.h @ISC_IPV6_H@ iterated_hash.h lang.h lex.h \ -diff --git a/lib/isc/include/isc/commandline.h b/lib/isc/include/isc/commandline.h -index 384640a..d35ccbf 100644 ---- a/lib/isc/include/isc/commandline.h -+++ b/lib/isc/include/isc/commandline.h -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id: commandline.h,v 1.16 2007/06/19 23:47:18 tbox Exp $ */ -- - #ifndef ISC_COMMANDLINE_H - #define ISC_COMMANDLINE_H 1 - -@@ -25,6 +23,7 @@ - #include - #include - #include -+#include - - /*% Index into parent argv vector. */ - LIBISC_EXTERNAL_DATA extern int isc_commandline_index; -@@ -41,9 +40,22 @@ LIBISC_EXTERNAL_DATA extern isc_boolean_t isc_commandline_reset; - - ISC_LANG_BEGINDECLS - --/*% parse command line */ - int - isc_commandline_parse(int argc, char * const *argv, const char *options); -+/*%< -+ * Parse a command line (similar to getopt()) -+ */ -+ -+isc_result_t -+isc_commandline_strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, -+ char ***argvp, unsigned int n); -+/*%< -+ * Tokenize the string "s" into whitespace-separated words, -+ * returning the number of words in '*argcp' and an array -+ * of pointers to the words in '*argvp'. The caller -+ * must free the array using isc_mem_free(). The string -+ * is modified in-place. -+ */ - - ISC_LANG_ENDDECLS - -diff --git a/lib/isc/include/isc/errno.h b/lib/isc/include/isc/errno.h -new file mode 100644 -index 0000000..47ec90f ---- /dev/null -+++ b/lib/isc/include/isc/errno.h -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ */ -+ -+#ifndef ISC_ERRNO_H -+#define ISC_ERRNO_H 1 -+ -+/*! \file isc/file.h */ -+ -+#include -+ -+ISC_LANG_BEGINDECLS -+ -+isc_result_t -+isc_errno_toresult(int err); -+/*!< -+ * \brief Convert a POSIX errno value to an ISC result code. -+ */ -+ISC_LANG_ENDDECLS -+ -+#endif /* ISC_ERRNO_H */ -diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h -index ca04b4e..5ef1e4c 100644 ---- a/lib/isc/include/isc/hash.h -+++ b/lib/isc/include/isc/hash.h -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id: hash.h,v 1.12 2009/01/17 23:47:43 tbox Exp $ */ -- - #ifndef ISC_HASH_H - #define ISC_HASH_H 1 - -@@ -81,6 +79,8 @@ - ***/ - ISC_LANG_BEGINDECLS - -+LIBDNS_EXTERNAL_DATA extern isc_hash_t *isc_hashctx; -+ - isc_result_t - isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, unsigned int limit, - isc_hash_t **hctx); -diff --git a/lib/isc/include/isc/lex.h b/lib/isc/include/isc/lex.h -index 8612150..6ce1465 100644 ---- a/lib/isc/include/isc/lex.h -+++ b/lib/isc/include/isc/lex.h -@@ -90,6 +90,7 @@ ISC_LANG_BEGINDECLS - #define ISC_LEXOPT_ESCAPE 0x100 /*%< Recognize escapes. */ - #define ISC_LEXOPT_QSTRINGMULTILINE 0x200 /*%< Allow multiline "" strings */ - #define ISC_LEXOPT_OCTAL 0x400 /*%< Expect a octal number. */ -+#define ISC_LEXOPT_BTEXT 0x800 /*%< Bracketed text. */ - /*@}*/ - /*@{*/ - /*! -@@ -122,7 +123,8 @@ typedef enum { - isc_tokentype_eof = 5, - isc_tokentype_initialws = 6, - isc_tokentype_special = 7, -- isc_tokentype_nomore = 8 -+ isc_tokentype_nomore = 8, -+ isc_tokentype_btext = 8 - } isc_tokentype_t; - - typedef union { -@@ -412,6 +414,23 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name); - * \li #ISC_R_NOTFOUND - there are no sources. - */ - -+isc_result_t -+isc_lex_setsourceline(isc_lex_t *lex, unsigned long line); -+/*%< -+ * Assigns a new line number to the input source. This can be used -+ * when parsing a buffer that's been excerpted from the middle a file, -+ * allowing logged messages to display the correct line number, -+ * rather than the line number within the buffer. -+ * -+ * Requires: -+ * -+ * \li 'lex' is a valid lexer. -+ * -+ * Returns: -+ * \li #ISC_R_SUCCESS -+ * \li #ISC_R_NOTFOUND - there are no sources. -+ */ -+ - isc_boolean_t - isc_lex_isfile(isc_lex_t *lex); - /*%< -diff --git a/lib/isc/lex.c b/lib/isc/lex.c -index 1dc2332..46fec84 100644 ---- a/lib/isc/lex.c -+++ b/lib/isc/lex.c -@@ -62,6 +62,7 @@ struct isc_lex { - unsigned int comments; - isc_boolean_t comment_ok; - isc_boolean_t last_was_eol; -+ unsigned int brace_count; - unsigned int paren_count; - unsigned int saved_paren_count; - isc_lexspecials_t specials; -@@ -110,6 +111,7 @@ isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp) { - lex->comments = 0; - lex->comment_ok = ISC_TRUE; - lex->last_was_eol = ISC_TRUE; -+ lex->brace_count = 0; - lex->paren_count = 0; - lex->saved_paren_count = 0; - memset(lex->specials, 0, 256); -@@ -309,7 +311,8 @@ typedef enum { - lexstate_ccomment, - lexstate_ccommentend, - lexstate_eatline, -- lexstate_qstring -+ lexstate_qstring, -+ lexstate_btext - } lexstate; - - #define IWSEOL (ISC_LEXOPT_INITIALWS | ISC_LEXOPT_EOL) -@@ -392,10 +395,17 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { - source->at_eof) - { - if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && -- lex->paren_count != 0) { -+ lex->paren_count != 0) -+ { - lex->paren_count = 0; - return (ISC_R_UNBALANCED); - } -+ if ((options & ISC_LEXOPT_BTEXT) != 0 && -+ lex->brace_count != 0) -+ { -+ lex->brace_count = 0; -+ return (ISC_R_UNBALANCED); -+ } - if ((options & ISC_LEXOPT_EOF) != 0) { - tokenp->type = isc_tokentype_eof; - return (ISC_R_SUCCESS); -@@ -507,6 +517,12 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { - result = ISC_R_UNBALANCED; - goto done; - } -+ if ((options & ISC_LEXOPT_BTEXT) != 0 && -+ lex->brace_count != 0) { -+ lex->brace_count = 0; -+ result = ISC_R_UNBALANCED; -+ goto done; -+ } - if ((options & ISC_LEXOPT_EOF) == 0) { - result = ISC_R_EOF; - goto done; -@@ -539,21 +555,34 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { - } else if (lex->specials[c]) { - lex->last_was_eol = ISC_FALSE; - if ((c == '(' || c == ')') && -- (options & ISC_LEXOPT_DNSMULTILINE) != 0) { -+ (options & ISC_LEXOPT_DNSMULTILINE) != 0) -+ { - if (c == '(') { - if (lex->paren_count == 0) - options &= ~IWSEOL; - lex->paren_count++; - } else { - if (lex->paren_count == 0) { -- result = ISC_R_UNBALANCED; -- goto done; -+ result = -+ ISC_R_UNBALANCED; -+ goto done; - } - lex->paren_count--; - if (lex->paren_count == 0) -- options = -- saved_options; -+ options = saved_options; -+ } -+ continue; -+ } else if (c == '{' && -+ (options & ISC_LEXOPT_BTEXT) != 0) -+ { -+ if (lex->brace_count != 0) { -+ result = ISC_R_UNBALANCED; -+ goto done; - } -+ lex->brace_count++; -+ options &= ~IWSEOL; -+ state = lexstate_btext; -+ no_comments = ISC_TRUE; - continue; - } - tokenp->type = isc_tokentype_special; -@@ -769,6 +798,55 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { - remaining--; - } - break; -+ case lexstate_btext: -+ if (c == EOF) { -+ result = ISC_R_UNEXPECTEDEND; -+ goto done; -+ } -+ if (c == '{') { -+ if (escaped) { -+ escaped = ISC_FALSE; -+ } else { -+ lex->brace_count++; -+ } -+ } else if (c == '}') { -+ if (escaped) { -+ escaped = ISC_FALSE; -+ } else { -+ INSIST(lex->brace_count > 0); -+ lex->brace_count--; -+ } -+ -+ if (lex->brace_count == 0) { -+ tokenp->type = isc_tokentype_btext; -+ tokenp->value.as_textregion.base = -+ lex->data; -+ tokenp->value.as_textregion.length = -+ (unsigned int) (lex->max_token - -+ remaining); -+ no_comments = ISC_FALSE; -+ done = ISC_TRUE; -+ break; -+ } -+ } -+ -+ if (c == '\\' && !escaped) -+ escaped = ISC_TRUE; -+ else -+ escaped = ISC_FALSE; -+ -+ if (remaining == 0U) { -+ result = grow_data(lex, &remaining, -+ &curr, &prev); -+ if (result != ISC_R_SUCCESS) -+ goto done; -+ } -+ INSIST(remaining > 0U); -+ prev = curr; -+ *curr++ = c; -+ *curr = '\0'; -+ remaining--; -+ break; - default: - FATAL_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_LEX, -@@ -895,7 +973,6 @@ isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r) - source->ignored; - } - -- - char * - isc_lex_getsourcename(isc_lex_t *lex) { - inputsource *source; -@@ -922,7 +999,6 @@ isc_lex_getsourceline(isc_lex_t *lex) { - return (source->line); - } - -- - isc_result_t - isc_lex_setsourcename(isc_lex_t *lex, const char *name) { - inputsource *source; -@@ -932,7 +1008,7 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name) { - source = HEAD(lex->sources); - - if (source == NULL) -- return(ISC_R_NOTFOUND); -+ return (ISC_R_NOTFOUND); - newname = isc_mem_strdup(lex->mctx, name); - if (newname == NULL) - return (ISC_R_NOMEMORY); -@@ -941,6 +1017,20 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name) { - return (ISC_R_SUCCESS); - } - -+isc_result_t -+isc_lex_setsourceline(isc_lex_t *lex, unsigned long line) { -+ inputsource *source; -+ -+ REQUIRE(VALID_LEX(lex)); -+ source = HEAD(lex->sources); -+ -+ if (source == NULL) -+ return (ISC_R_NOTFOUND); -+ -+ source->line = line; -+ return (ISC_R_SUCCESS); -+} -+ - isc_boolean_t - isc_lex_isfile(isc_lex_t *lex) { - inputsource *source; -diff --git a/lib/isc/tests/Makefile.in b/lib/isc/tests/Makefile.in -index 564d3cd..f04396e 100644 ---- a/lib/isc/tests/Makefile.in -+++ b/lib/isc/tests/Makefile.in -@@ -12,8 +12,6 @@ - # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - # PERFORMANCE OF THIS SOFTWARE. - --# $Id$ -- - srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ -@@ -37,13 +35,14 @@ LIBS = @LIBS@ @ATFLIBS@ - OBJS = isctest.@O@ - SRCS = isctest.c taskpool_test.c socket_test.c hash_test.c \ - sockaddr_test.c symtab_test.c task_test.c queue_test.c \ -- parse_test.c pool_test.c regex_test.c safe_test.c -+ parse_test.c pool_test.c regex_test.c safe_test.c \ -+ errno_test.c - - SUBDIRS = - TARGETS = taskpool_test@EXEEXT@ socket_test@EXEEXT@ hash_test@EXEEXT@ \ - sockaddr_test@EXEEXT@ symtab_test@EXEEXT@ task_test@EXEEXT@ \ - queue_test@EXEEXT@ parse_test@EXEEXT@ pool_test@EXEEXT@ \ -- regex_test@EXEEXT@ safe_test@EXEEXT@ -+ regex_test@EXEEXT@ safe_test@EXEEXT@ errno_test@EXEEXT@ - - @BIND9_MAKE_RULES@ - -@@ -91,6 +90,10 @@ safe_test@EXEEXT@: safe_test.@O@ ${ISCDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - safe_test.@O@ ${ISCLIBS} ${LIBS} - -+ -+errno_test@EXEEXT@: errno_test.@O@ ${ISCDEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ -+ errno_test.@O@ ${ISCLIBS} ${LIBS} - unit:: - sh ${top_srcdir}/unit/unittest.sh - -diff --git a/lib/isc/tests/errno_test.c b/lib/isc/tests/errno_test.c -new file mode 100644 -index 0000000..253a857 ---- /dev/null -+++ b/lib/isc/tests/errno_test.c -@@ -0,0 +1,102 @@ -+/* -+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ */ -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+typedef struct { -+ int err; -+ isc_result_t result; -+} testpair_t; -+ -+testpair_t testpair[] = { -+ { EPERM, ISC_R_NOPERM }, -+ { ENOENT, ISC_R_FILENOTFOUND }, -+ { EIO, ISC_R_IOERROR }, -+ { EBADF, ISC_R_INVALIDFILE }, -+ { ENOMEM, ISC_R_NOMEMORY }, -+ { EACCES, ISC_R_NOPERM }, -+ { EEXIST, ISC_R_FILEEXISTS }, -+ { ENOTDIR, ISC_R_INVALIDFILE }, -+ { EINVAL, ISC_R_INVALIDFILE }, -+ { ENFILE, ISC_R_TOOMANYOPENFILES }, -+ { EMFILE, ISC_R_TOOMANYOPENFILES }, -+ { EPIPE, ISC_R_CONNECTIONRESET }, -+ { ENAMETOOLONG, ISC_R_INVALIDFILE }, -+ { ELOOP, ISC_R_INVALIDFILE }, -+#ifdef EOVERFLOW -+ { EOVERFLOW, ISC_R_RANGE }, -+#endif -+#ifdef EAFNOSUPPORT -+ { EAFNOSUPPORT, ISC_R_FAMILYNOSUPPORT }, -+#endif -+#ifdef EADDRINUSE -+ { EADDRINUSE, ISC_R_ADDRINUSE }, -+#endif -+ { EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL }, -+#ifdef ENETDOWN -+ { ENETDOWN, ISC_R_NETDOWN }, -+#endif -+#ifdef ENETUNREACH -+ { ENETUNREACH, ISC_R_NETUNREACH }, -+#endif -+#ifdef ECONNABORTED -+ { ECONNABORTED, ISC_R_CONNECTIONRESET }, -+#endif -+#ifdef ECONNRESET -+ { ECONNRESET, ISC_R_CONNECTIONRESET }, -+#endif -+#ifdef ENOBUFS -+ { ENOBUFS, ISC_R_NORESOURCES }, -+#endif -+#ifdef ENOTCONN -+ { ENOTCONN, ISC_R_NOTCONNECTED }, -+#endif -+#ifdef ETIMEDOUT -+ { ETIMEDOUT, ISC_R_TIMEDOUT }, -+#endif -+ { ECONNREFUSED, ISC_R_CONNREFUSED }, -+#ifdef EHOSTDOWN -+ { EHOSTDOWN, ISC_R_HOSTDOWN }, -+#endif -+#ifdef EHOSTUNREACH -+ { EHOSTUNREACH, ISC_R_HOSTUNREACH }, -+#endif -+ { 0, ISC_R_UNEXPECTED } -+}; -+ -+ATF_TC(isc_errno_toresult); -+ATF_TC_HEAD(isc_errno_toresult, tc) { -+ atf_tc_set_md_var(tc, "descr", "convert errno to ISC result"); -+} -+ATF_TC_BODY(isc_errno_toresult, tc) { -+ isc_result_t result, expect; -+ size_t i; -+ -+ for (i = 0; i < sizeof(testpair)/sizeof(testpair[0]); i++) { -+ result = isc_errno_toresult(testpair[i].err); -+ expect = testpair[i].result; -+ ATF_CHECK(result == expect); -+ } -+} -+ -+/* -+ * Main -+ */ -+ATF_TP_ADD_TCS(tp) { -+ ATF_TP_ADD_TC(tp, isc_errno_toresult); -+ return (atf_no_error()); -+} -+ -diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in -index 0595fa2..8f32119 100644 ---- a/lib/isc/unix/Makefile.in -+++ b/lib/isc/unix/Makefile.in -@@ -13,8 +13,6 @@ - # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - # PERFORMANCE OF THIS SOFTWARE. - --# $Id: Makefile.in,v 1.44 2009/12/05 23:31:41 each Exp $ -- - srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ -@@ -30,14 +28,14 @@ CWARNINGS = - - # Alphabetically - OBJS = @ISC_IPV6_O@ @ISC_PK11_API_O@ \ -- app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \ -- fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \ -+ app.@O@ dir.@O@ entropy.@O@ errno.@O@ errno2result.@O@ \ -+ file.@O@ fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \ - os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \ - strerror.@O@ syslog.@O@ time.@O@ - - # Alphabetically - SRCS = @ISC_IPV6_C@ @ISC_PK11_API_C@ \ -- app.c dir.c entropy.c errno2result.c file.c \ -+ app.c dir.c entropy.c errno.c errno2result.c file.c \ - fsaccess.c interfaceiter.c keyboard.c net.c \ - os.c resource.c socket.c stdio.c stdtime.c \ - strerror.c syslog.c time.c -diff --git a/lib/isc/unix/errno.c b/lib/isc/unix/errno.c -new file mode 100644 -index 0000000..c5f1c56 ---- /dev/null -+++ b/lib/isc/unix/errno.c -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+ -+#include "errno2result.h" -+ -+isc_result_t -+isc_errno_toresult(int err) { -+ return (isc___errno2result(err, ISC_FALSE, 0, 0)); -+} -diff --git a/lib/isc/unix/errno2result.c b/lib/isc/unix/errno2result.c -index 2951ef8..2309794 100644 ---- a/lib/isc/unix/errno2result.c -+++ b/lib/isc/unix/errno2result.c -@@ -34,7 +34,9 @@ - * not already there. - */ - isc_result_t --isc___errno2result(int posixerrno, const char *file, unsigned int line) { -+isc___errno2result(int posixerrno, isc_boolean_t dolog, -+ const char *file, unsigned int line) -+{ - char strbuf[ISC_STRERRORSIZE]; - - switch (posixerrno) { -@@ -108,10 +110,12 @@ isc___errno2result(int posixerrno, const char *file, unsigned int line) { - case ECONNREFUSED: - return (ISC_R_CONNREFUSED); - default: -- isc__strerror(posixerrno, strbuf, sizeof(strbuf)); -- UNEXPECTED_ERROR(file, line, "unable to convert errno " -- "to isc_result: %d: %s", -- posixerrno, strbuf); -+ if (dolog) { -+ isc__strerror(posixerrno, strbuf, sizeof(strbuf)); -+ UNEXPECTED_ERROR(file, line, "unable to convert errno " -+ "to isc_result: %d: %s", -+ posixerrno, strbuf); -+ } - /* - * XXXDCL would be nice if perhaps this function could - * return the system's error string, so the caller -diff --git a/lib/isc/unix/errno2result.h b/lib/isc/unix/errno2result.h -index 1e49ed1..9c6b052 100644 ---- a/lib/isc/unix/errno2result.h -+++ b/lib/isc/unix/errno2result.h -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id$ */ -- - #ifndef UNIX_ERRNO2RESULT_H - #define UNIX_ERRNO2RESULT_H 1 - -@@ -31,10 +29,11 @@ - - ISC_LANG_BEGINDECLS - --#define isc__errno2result(x) isc___errno2result(x, __FILE__, __LINE__) -+#define isc__errno2result(x) isc___errno2result(x, ISC_TRUE, __FILE__, __LINE__) - - isc_result_t --isc___errno2result(int posixerrno, const char *file, unsigned int line); -+isc___errno2result(int posixerrno, isc_boolean_t dolog, -+ const char *file, unsigned int line); - - ISC_LANG_ENDDECLS - -diff --git a/lib/isc/win32/Makefile.in b/lib/isc/win32/Makefile.in -index c129e31..9cd717d 100644 ---- a/lib/isc/win32/Makefile.in -+++ b/lib/isc/win32/Makefile.in -@@ -13,8 +13,6 @@ - # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - # PERFORMANCE OF THIS SOFTWARE. - --# $Id: Makefile.in,v 1.14 2009/12/05 23:31:41 each Exp $ -- - srcdir = @srcdir@ - VPATH = @srcdir@ - top_srcdir = @top_srcdir@ -@@ -27,11 +25,11 @@ CDEFINES = - CWARNINGS = - - # Alphabetically --OBJS = condition.@O@ dir.@O@ file.@O@ fsaccess.@O@ once.@O@ \ -- stdtime.@O@ thread.@O@ time.@O@ -+OBJS = condition.@O@ dir.@O@ errno.@O@ file.@O@ fsaccess.@O@ \ -+ once.@O@ stdtime.@O@ thread.@O@ time.@O@ - - # Alphabetically --SRCS = condition.c dir.c file.c once.c fsaccess.c \ -+SRCS = condition.c dir.c errno.c file.c once.c fsaccess.c \ - stdtime.c thread.c time.c - - SUBDIRS = include -diff --git a/lib/isc/win32/errno.c b/lib/isc/win32/errno.c -new file mode 100644 -index 0000000..5c45496 ---- /dev/null -+++ b/lib/isc/win32/errno.c -@@ -0,0 +1,18 @@ -+/* -+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include "errno2result.h" -+ -+isc_result_t -+isc_errno_toresult(int err) { -+ return (isc__errno2resultx(err, ISC_FALSE, 0, 0)); -+} -diff --git a/lib/isc/win32/errno2result.c b/lib/isc/win32/errno2result.c -index c3d54d6..c9a3ab5 100644 ---- a/lib/isc/win32/errno2result.c -+++ b/lib/isc/win32/errno2result.c -@@ -32,7 +32,9 @@ - * not already there. - */ - isc_result_t --isc__errno2resultx(int posixerrno, const char *file, int line) { -+isc__errno2resultx(int posixerrno, isc_boolean_t dolog, -+ const char *file, int line) -+{ - char strbuf[ISC_STRERRORSIZE]; - - switch (posixerrno) { -@@ -99,9 +101,13 @@ isc__errno2resultx(int posixerrno, const char *file, int line) { - case WSAENOBUFS: - return (ISC_R_NORESOURCES); - default: -- isc__strerror(posixerrno, strbuf, sizeof(strbuf)); -- UNEXPECTED_ERROR(file, line, "unable to convert errno " -- "to isc_result: %d: %s", posixerrno, strbuf); -+ if (dolog) { -+ isc__strerror(posixerrno, strbuf, sizeof(strbuf)); -+ UNEXPECTED_ERROR(file, line, -+ "unable to convert errno " -+ "to isc_result: %d: %s", -+ posixerrno, strbuf); -+ } - /* - * XXXDCL would be nice if perhaps this function could - * return the system's error string, so the caller -diff --git a/lib/isc/win32/errno2result.h b/lib/isc/win32/errno2result.h -index 41682db..cc9115e 100644 ---- a/lib/isc/win32/errno2result.h -+++ b/lib/isc/win32/errno2result.h -@@ -30,10 +30,11 @@ - ISC_LANG_BEGINDECLS - - #define isc__errno2result(posixerrno) \ -- isc__errno2resultx(posixerrno, __FILE__, __LINE__) -+ isc__errno2resultx(posixerrno, ISC_TRUE, __FILE__, __LINE__) - - isc_result_t --isc__errno2resultx(int posixerrno, const char *file, int line); -+isc__errno2resultx(int posixerrno, isc_boolean_t dolog, -+ const char *file, int line); - - ISC_LANG_ENDDECLS - -diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def -index 0c7a829..d7d2243 100644 ---- a/lib/isc/win32/libisc.def -+++ b/lib/isc/win32/libisc.def -@@ -183,6 +183,7 @@ isc_buffer_reinit - isc_bufferlist_availablecount - isc_bufferlist_usedcount - isc_commandline_parse -+isc_commandline_strtoargv - isc_condition_broadcast - isc_condition_destroy - isc_condition_init -@@ -258,6 +259,7 @@ isc_hash_ctxdetach - isc_hash_ctxinit - isc_hash_destroy - isc_hash_init -+isc_hashctx - isc_heap_create - isc_heap_decreased - isc_heap_delete -diff --git a/lib/isc/win32/libisc.dsp b/lib/isc/win32/libisc.dsp -index 0f14a89..156e23b 100644 ---- a/lib/isc/win32/libisc.dsp -+++ b/lib/isc/win32/libisc.dsp -@@ -115,6 +115,10 @@ SOURCE=.\entropy.c - # End Source File - # Begin Source File - -+SOURCE=.\errno.c -+# End Source File -+# Begin Source File -+ - SOURCE=.\errno2result.c - # End Source File - # Begin Source File -@@ -267,6 +271,10 @@ SOURCE=..\include\isc\entropy.h - # End Source File - # Begin Source File - -+SOURCE=..\include\isc\errno.h -+# End Source File -+# Begin Source File -+ - SOURCE=.\errno2result.h - # End Source File - # Begin Source File -diff --git a/lib/isc/win32/libisc.mak b/lib/isc/win32/libisc.mak -index 96e44e4..5923693 100644 ---- a/lib/isc/win32/libisc.mak -+++ b/lib/isc/win32/libisc.mak -@@ -128,6 +128,7 @@ CLEAN : - -@erase "$(INTDIR)\dir.obj" - -@erase "$(INTDIR)\DLLMain.obj" - -@erase "$(INTDIR)\entropy.obj" -+ -@erase "$(INTDIR)\errno.obj" - -@erase "$(INTDIR)\errno2result.obj" - -@erase "$(INTDIR)\error.obj" - -@erase "$(INTDIR)\event.obj" -@@ -219,6 +220,7 @@ LINK32_OBJS= \ - "$(INTDIR)\dir.obj" \ - "$(INTDIR)\DLLMain.obj" \ - "$(INTDIR)\entropy.obj" \ -+ "$(INTDIR)\errno.obj" \ - "$(INTDIR)\errno2result.obj" \ - "$(INTDIR)\file.obj" \ - "$(INTDIR)\fsaccess.obj" \ -@@ -341,6 +343,8 @@ CLEAN : - -@erase "$(INTDIR)\DLLMain.sbr" - -@erase "$(INTDIR)\entropy.obj" - -@erase "$(INTDIR)\entropy.sbr" -+ -@erase "$(INTDIR)\errno.obj" -+ -@erase "$(INTDIR)\errno.sbr" - -@erase "$(INTDIR)\errno2result.obj" - -@erase "$(INTDIR)\errno2result.sbr" - -@erase "$(INTDIR)\error.obj" -@@ -497,6 +501,7 @@ BSC32_SBRS= \ - "$(INTDIR)\dir.sbr" \ - "$(INTDIR)\DLLMain.sbr" \ - "$(INTDIR)\entropy.sbr" \ -+ "$(INTDIR)\errno.sbr" \ - "$(INTDIR)\errno2result.sbr" \ - "$(INTDIR)\file.sbr" \ - "$(INTDIR)\fsaccess.sbr" \ -@@ -588,6 +593,7 @@ LINK32_OBJS= \ - "$(INTDIR)\dir.obj" \ - "$(INTDIR)\DLLMain.obj" \ - "$(INTDIR)\entropy.obj" \ -+ "$(INTDIR)\errno.obj" \ - "$(INTDIR)\errno2result.obj" \ - "$(INTDIR)\file.obj" \ - "$(INTDIR)\fsaccess.obj" \ -@@ -793,6 +799,23 @@ SOURCE=.\entropy.c - - !ENDIF - -+SOURCE=.\errno.c -+ -+!IF "$(CFG)" == "libisc - @PLATFORM@ Release" -+ -+ -+"$(INTDIR)\errno.obj" : $(SOURCE) "$(INTDIR)" -+ -+ -+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" -+ -+ -+"$(INTDIR)\errno.obj" "$(INTDIR)\errno.sbr" : $(SOURCE) "$(INTDIR)" -+ -+ -+!ENDIF -+ -+ - SOURCE=.\errno2result.c - - !IF "$(CFG)" == "libisc - Win32 Release" -diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c -index f015974..5455dbf 100644 ---- a/lib/isc/win32/socket.c -+++ b/lib/isc/win32/socket.c -@@ -2480,7 +2480,7 @@ SocketIoThread(LPVOID ThreadContext) { - * Did the I/O operation complete? - */ - errstatus = GetLastError(); -- isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__); -+ isc_result = isc__errno2result(errstatus); - - LOCK(&sock->lock); - CONSISTENT(sock); -@@ -2532,7 +2532,7 @@ SocketIoThread(LPVOID ThreadContext) { - goto wait_again; - } else { - errstatus = GetLastError(); -- isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__); -+ isc_result = isc__errno2result(errstatus); - socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, - "restart_accept() failed: errstatus=%d isc_result=%d", - errstatus, isc_result); -diff --git a/lib/isccfg/include/isccfg/grammar.h b/lib/isccfg/include/isccfg/grammar.h -index 2d7080c..7df760a 100644 ---- a/lib/isccfg/include/isccfg/grammar.h -+++ b/lib/isccfg/include/isccfg/grammar.h -@@ -266,6 +266,7 @@ LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_uint64; - LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_qstring; - LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_astring; - LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_ustring; -+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_bracketed_text; - LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddr; - LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr; - LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr4; -diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c -index 1527575..62fcc96 100644 ---- a/lib/isccfg/namedconf.c -+++ b/lib/isccfg/namedconf.c -@@ -126,6 +126,7 @@ static cfg_type_t cfg_type_zoneopts; - static cfg_type_t cfg_type_dynamically_loadable_zones; - static cfg_type_t cfg_type_dynamically_loadable_zones_opts; - static cfg_type_t cfg_type_v4_aaaa; -+static cfg_type_t cfg_type_dyndb; - - /* - * Clauses that can be found in a 'dynamically loadable zones' statement -@@ -897,6 +898,7 @@ namedconf_or_view_clauses[] = { - { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI }, - /* only 1 DLZ per view allowed */ - { "dlz", &cfg_type_dynamically_loadable_zones, 0 }, -+ { "dyndb", &cfg_type_dyndb, CFG_CLAUSEFLAG_MULTI }, - { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI }, - { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI }, - { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI }, -@@ -1706,6 +1708,22 @@ static cfg_type_t cfg_type_dynamically_loadable_zones_opts = { - }; - - /*% -+ * The "dyndb" statement syntax. -+ */ -+ -+static cfg_tuplefielddef_t dyndb_fields[] = { -+ { "name", &cfg_type_astring, 0 }, -+ { "library", &cfg_type_qstring, 0 }, -+ { "parameters", &cfg_type_bracketed_text, 0 }, -+ { NULL, NULL, 0 } -+}; -+ -+static cfg_type_t cfg_type_dyndb = { -+ "dyndb", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, -+ &cfg_rep_tuple, dyndb_fields -+}; -+ -+/*% - * Clauses that can be found within the 'key' statement. - */ - static cfg_clausedef_t -diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c -index de0fa31..5dc1653 100644 ---- a/lib/isccfg/parser.c -+++ b/lib/isccfg/parser.c -@@ -762,6 +762,42 @@ cfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type, - return (result); - } - -+static isc_result_t -+parse_btext(cfg_parser_t *pctx, const cfg_type_t *type, -+ cfg_obj_t **ret) -+{ -+ isc_result_t result; -+ UNUSED(type); -+ -+ CHECK(cfg_gettoken(pctx, ISC_LEXOPT_BTEXT)); -+ if (pctx->token.type != isc_tokentype_btext) { -+ cfg_parser_error(pctx, CFG_LOG_NEAR, -+ "expected bracketed text"); -+ return (ISC_R_UNEXPECTEDTOKEN); -+ } -+ return (create_string(pctx, -+ TOKEN_STRING(pctx), -+ &cfg_type_bracketed_text, -+ ret)); -+ cleanup: -+ return (result); -+} -+ -+static void -+print_btext(cfg_printer_t *pctx, const cfg_obj_t *obj) { -+ cfg_print_cstr(pctx, "{"); -+ cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length); -+ print_close(pctx); -+} -+ -+static void -+doc_btext(cfg_printer_t *pctx, const cfg_type_t *type) { -+ UNUSED(type); -+ -+ cfg_print_cstr(pctx, "{ }"); -+} -+ -+ - isc_boolean_t - cfg_is_enum(const char *s, const char *const *enums) { - const char * const *p; -@@ -855,6 +891,16 @@ cfg_type_t cfg_type_astring = { - }; - - /* -+ * Text enclosed in brackets. Used to pass a block of configuration -+ * text to dynamic library or external application. Checked for -+ * bracket balance, but not otherwise parsed. -+ */ -+cfg_type_t cfg_type_bracketed_text = { -+ "bracketed_text", parse_btext, print_btext, doc_btext, -+ &cfg_rep_string, NULL -+}; -+ -+/* - * Booleans - */ - --- -2.9.3 - diff --git a/SOURCES/bind99-fips-tests.patch b/SOURCES/bind99-fips-tests.patch deleted file mode 100644 index 7a10f23..0000000 --- a/SOURCES/bind99-fips-tests.patch +++ /dev/null @@ -1,1978 +0,0 @@ -From 4a1bbbbe8ff1951dba9f5d6a69c42dcf274877d2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= -Date: Fri, 22 Jun 2018 14:05:43 +0200 -Subject: [PATCH 2/2] Squashed commit of the following: -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -commit d1de64d54126a9662b0f709adf1467f1ca3caa50 -Author: Petr Menšík -Date: Wed Jun 20 19:15:31 2018 +0200 - - Fix allow_query tests with hmac-256 keys - -commit 854606588f53ee403364461ad29dc1cfd29525a0 -Author: Petr Menšík -Date: Wed Mar 7 15:54:11 2018 +0100 - - Increase bitsize of DSA key to pass FIPS 140-2 mode. - -commit 98dae21d1f863fa26c125271392288730da52842 -Author: Petr Menšík -Date: Thu Apr 19 18:28:09 2018 +0200 - - Fix nsupdate, tsig and rndc tests. - Do not use md5 by default for rndc, skip gracefully md5 if not available. - - Rename md5 keys to rndc*.conf, to pass util/merge_copyrights change. - Fix dynamic ports merge. - -commit 0ec5e2522aa32931cda5abd07a757035078840ea -Author: Petr Menšík -Date: Wed Jun 20 19:34:20 2018 +0200 - - Use testcrypto for crypto detection. Generate random data per test into test directory. - -commit 0ca3c85fa6450ae8b347fa5585d0134ebe41682c -Author: Petr Menšík -Date: Wed Mar 7 13:21:00 2018 +0100 - - Add md5 availability detection to featuretest - -commit c1b104ccf66a1ec37e941e303a56675c7dcccbaa -Author: Petr Menšík -Date: Mon Jan 22 14:12:37 2018 +0100 - - Update system tests to detect MD5 disabled at runtime - -commit 743d24de87b6f022b99d14d3109958660b9ee07b -Author: Petr Menšík -Date: Fri Feb 23 21:57:11 2018 +0100 - - Make testcrypto FIPS compatible - - (cherry picked from commit 0e15cc7012c537a5d683c35534d33d23fcc4d942) - -commit 325dc1f4f37dc4b7133dd39d7780c10d183e4808 -Author: Evan Hunt -Date: Mon Oct 31 23:01:38 2016 -0700 - - [v9_9] 4496. [func] dig: add +idnout to control whether labels are - display in punycode or not. Requires idn support - to be enabled at compile time. [RT #43398] - - (cherry picked from commit 42470b0b87da24b18e0ff6ce78f3143e89df6d31) - (cherry picked from commit 6552f33198438390724c5823b8dbcf477ec9638c) - (cherry picked from commit 7aec46a5ef4074c3957d525643188257c7575841) - - Skip IDN part and import only feature-test from system tests - - (cherry picked from commit 61a01f48604ff6f5f84b64a5aaee722ebae8fadc) - -commit d435ac7bcf72117e75e534c23fca1852f4140eb8 -Author: Petr Menšík -Date: Wed Mar 7 10:44:23 2018 +0100 - - Use hmac-sha256 instead of default hmac-md5 for allow-query. - Do not use hmac-md5 in tests by default, make it pass with MD5 disabled. - -commit 067ca65156a9fadb191b7c9073904a43f57f1896 -Author: Evan Hunt -Date: Thu Feb 6 19:48:49 2014 -0800 - - [v9_9] add testcrypto.sh - - (cherry picked from commit e9a2673e85173d93be168f561c5c77184d4e839d) - -commit 3fd542379fa381b54381e07d6625ce53f9f9b1f0 -Author: Petr Menšík -Date: Thu Jun 21 12:00:35 2018 +0200 - - Revert "4450. [port] Provide more nuanced HSM support which better matches" - - This reverts commit f3b4d031c1f714ff6e862670663aa5a18650951e. - - Revert PK11_MD5_DISABLED also from remaining files. Keep documentation - changes. - -commit f90934f734796595135cdd7a5008555a615dfe8e -Author: Petr Menšík -Date: Wed Jun 20 19:31:19 2018 +0200 - - Fix rndc-confgen default algorithm, report true algorithm in usage. - -commit dd53212c12c6943a21a3c24d60995edd19e1d9f7 -Author: Petr Menšík -Date: Fri Feb 23 21:21:30 2018 +0100 - - Cleanup only if initialization was successful - -commit f163ea51c46bb22bf264a1ac983e2027e43845fa -Author: Petr Menšík -Date: Mon Feb 5 12:19:28 2018 +0100 - - Ensure dst backend is initialized first even before hmac algorithms. - -commit 58751b60bd39168b7c8f817ede70473842432081 -Author: Petr Menšík -Date: Mon Feb 5 12:17:54 2018 +0100 - - Skip initialization of MD5 based algorithms if not available. - -commit 0572b98430d3c80f4a0b0c592b1e3bf7fde9b768 -Author: Petr Menšík -Date: Mon Feb 5 10:21:27 2018 +0100 - - Change secalgs skipping to be more safe - -commit 994f497a032930fce1370d507a265fbb293c66f4 -Author: Petr Menšík -Date: Wed Jan 31 18:26:11 2018 +0100 - - Skip MD5 algorithm also in case of NULL name - -commit abd82fbd2507c4b8f20e1ade202fd66d224fd646 -Author: Petr Menšík -Date: Wed Jan 31 16:54:29 2018 +0100 - - Revert part of commit 1b5c641416eb6de7fc232fc89d31a40a4d439f3d related - to SHA1. - -commit b3c832d53a14a0779f598869bb99685c8e4b2bc0 -Author: Petr Menšík -Date: Wed Jan 31 11:38:12 2018 +0100 - - Make MD5 behave like unknown algorithm in TSIG. - -commit a64a3d6962ee93d6f8699b29bd6507dba0c244ed -Author: Petr Menšík -Date: Tue Nov 28 20:14:37 2017 +0100 - - Select token with most supported functions, instead of demanding it must support all functions - - Initialize PKCS#11 always until successfully initialized - -commit db118c6368668099ea1b6e75860cc12e178afa3b -Author: Petr Menšík -Date: Mon Jan 22 16:17:44 2018 +0100 - - Handle MD5 unavailability from DST - -commit 8f8824dca2f5b4d5a3a176d31ac3ee612321c4e3 -Author: Petr Menšík -Date: Mon Jan 22 14:11:16 2018 +0100 - - Check runtime flag from library and applications, fail gracefully. - -commit bd431384af7dcde8827e670c8749517ad677a967 -Author: Petr Menšík -Date: Mon Jan 22 08:39:08 2018 +0100 - - Modify libraries to use isc_md5_available() if PK11_MD5_DISABLE is not - defined. - TODO: pk11.c should accept slot without MD5 support. - -commit 160b13979ef3d0e92d2dd52d0987a3ec979be6cf -Author: Petr Menšík -Date: Mon Jan 22 07:21:04 2018 +0100 - - Add runtime detection whether MD5 is useable. - -commit 23b27ce0f2ad496c331ae40349cc1074a1b11804 -Author: Mark Andrews -Date: Fri Aug 19 08:25:54 2016 +1000 - - 4450. [port] Provide more nuanced HSM support which better matches - the specific PKCS11 providers capabilities. [RT #42458] - - (cherry picked from commit 8ee6f289d87851a5b898b24a64587f0e6bc225bc) ---- - bin/tests/system/Makefile.in | 25 +++- - bin/tests/system/acl/ns2/named1.conf | 4 +- - bin/tests/system/acl/ns2/named2.conf | 4 +- - bin/tests/system/acl/ns2/named3.conf | 6 +- - bin/tests/system/acl/ns2/named4.conf | 4 +- - bin/tests/system/acl/ns2/named5.conf | 4 +- - bin/tests/system/acl/tests.sh | 32 +++--- - bin/tests/system/allow_query/ns2/named10.conf | 2 +- - bin/tests/system/allow_query/ns2/named11.conf | 4 +- - bin/tests/system/allow_query/ns2/named12.conf | 2 +- - bin/tests/system/allow_query/ns2/named30.conf | 2 +- - bin/tests/system/allow_query/ns2/named31.conf | 4 +- - bin/tests/system/allow_query/ns2/named32.conf | 2 +- - bin/tests/system/allow_query/ns2/named40.conf | 4 +- - bin/tests/system/allow_query/tests.sh | 18 +-- - bin/tests/system/checkconf/bad-tsig.conf | 2 +- - bin/tests/system/conf.sh.in | 6 +- - bin/tests/system/digdelv/ns2/example.db | 15 ++- - bin/tests/system/digdelv/tests.sh | 4 +- - bin/tests/system/dlv/ns1/sign.sh | 4 +- - bin/tests/system/dlv/ns2/sign.sh | 4 +- - bin/tests/system/dlv/ns3/sign.sh | 68 +++++------ - bin/tests/system/dlv/ns6/sign.sh | 64 +++++------ - bin/tests/system/dnssec/ns2/sign.sh | 8 +- - bin/tests/system/dnssec/prereq.sh | 11 +- - bin/tests/system/feature-test.c | 159 ++++++++++++++++++++++++++ - bin/tests/system/filter-aaaa/ns1/sign.sh | 4 +- - bin/tests/system/filter-aaaa/ns4/sign.sh | 4 +- - bin/tests/system/keymgr/prereq.sh | 15 +-- - bin/tests/system/nsupdate/ns1/named.conf | 2 +- - bin/tests/system/nsupdate/ns2/named.conf | 2 +- - bin/tests/system/nsupdate/setup.sh | 7 +- - bin/tests/system/nsupdate/tests.sh | 11 +- - bin/tests/system/rndc/setup.sh | 4 +- - bin/tests/system/rndc/tests.sh | 22 ++-- - bin/tests/system/testcrypto.sh | 71 ++++++++++++ - bin/tests/system/tkey/keycreate.c | 3 + - bin/tests/system/tkey/keydelete.c | 18 ++- - bin/tests/system/tkey/prereq.sh | 11 +- - bin/tests/system/tsig/clean.sh | 1 + - bin/tests/system/tsig/ns1/named.conf | 12 +- - bin/tests/system/tsig/ns1/rndc5.conf.in | 22 ++++ - bin/tests/system/tsig/setup.sh | 25 ++++ - bin/tests/system/tsig/tests.sh | 75 +++++++----- - bin/tests/system/tsiggss/setup.sh | 2 +- - bin/tests/system/upforwd/ns1/named.conf | 2 +- - bin/tests/system/upforwd/tests.sh | 2 +- - 47 files changed, 547 insertions(+), 230 deletions(-) - create mode 100644 bin/tests/system/feature-test.c - create mode 100644 bin/tests/system/testcrypto.sh - create mode 100644 bin/tests/system/tsig/ns1/rndc5.conf.in - create mode 100644 bin/tests/system/tsig/setup.sh - -diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in -index 0c7fdffd01..afee71b2bb 100644 ---- a/bin/tests/system/Makefile.in -+++ b/bin/tests/system/Makefile.in -@@ -23,10 +23,31 @@ top_srcdir = @top_srcdir@ - - SUBDIRS = dlzexternal dyndb filter-aaaa geoip lwresd rpz rrl \ - rsabigexponent tkey tsiggss --TARGETS = -+CINCLUDES = ${ISC_INCLUDES} ${DNS_INCLUDES} -+ -+CDEFINES = @USE_GSSAPI@ -+CWARNINGS = -+ -+DNSLIBS = -+ISCLIBS = ../../../lib/isc/libisc.@A@ -+ -+DNSDEPLIBS = -+ISCDEPLIBS = -+ -+DEPLIBS = -+ -+LIBS = @LIBS@ -+ -+OBJS = feature-test.@O@ -+SRCS = feature-test.c -+ -+TARGETS = feature-test@EXEEXT@ - - @BIND9_MAKE_RULES@ - -+feature-test@EXEEXT@: feature-test.@O@ -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ feature-test.@O@ ${ISCLIBS} ${LIBS} -+ - # Running the scripts below is bypassed when a separate - # build directory is used. - -@@ -38,6 +59,8 @@ test: subdirs - testclean clean distclean:: - if test -f ./cleanall.sh; then sh ./cleanall.sh; fi - rm -f systests.output -+ rm -f ${TARGETS} -+ rm -f ${OBJS} - - distclean:: - rm -f conf.sh -diff --git a/bin/tests/system/acl/ns2/named1.conf b/bin/tests/system/acl/ns2/named1.conf -index b70d1dd761..9037a15c9d 100644 ---- a/bin/tests/system/acl/ns2/named1.conf -+++ b/bin/tests/system/acl/ns2/named1.conf -@@ -35,12 +35,12 @@ options { - include "../../common/controls.conf"; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key two { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/acl/ns2/named2.conf b/bin/tests/system/acl/ns2/named2.conf -index bcd7e0df19..648c5fdbdc 100644 ---- a/bin/tests/system/acl/ns2/named2.conf -+++ b/bin/tests/system/acl/ns2/named2.conf -@@ -35,12 +35,12 @@ options { - include "../../common/controls.conf"; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key two { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/acl/ns2/named3.conf b/bin/tests/system/acl/ns2/named3.conf -index ea2cbcb44a..546ecf6af4 100644 ---- a/bin/tests/system/acl/ns2/named3.conf -+++ b/bin/tests/system/acl/ns2/named3.conf -@@ -35,17 +35,17 @@ options { - include "../../common/controls.conf"; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key two { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key three { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/acl/ns2/named4.conf b/bin/tests/system/acl/ns2/named4.conf -index 99edf7ebe5..4c84d0f163 100644 ---- a/bin/tests/system/acl/ns2/named4.conf -+++ b/bin/tests/system/acl/ns2/named4.conf -@@ -35,12 +35,12 @@ options { - include "../../common/controls.conf"; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key two { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/acl/ns2/named5.conf b/bin/tests/system/acl/ns2/named5.conf -index d17e1cf7b7..52ae56300e 100644 ---- a/bin/tests/system/acl/ns2/named5.conf -+++ b/bin/tests/system/acl/ns2/named5.conf -@@ -36,12 +36,12 @@ options { - include "../../common/controls.conf"; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key two { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/acl/tests.sh b/bin/tests/system/acl/tests.sh -index 7207c5a1d3..753f9f6743 100644 ---- a/bin/tests/system/acl/tests.sh -+++ b/bin/tests/system/acl/tests.sh -@@ -28,13 +28,13 @@ echo "I:testing basic ACL processing" - # key "one" should fail - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:one:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; } - - # any other key should be fine - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:two:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; } - - cp -f ns2/named2.conf ns2/named.conf -@@ -44,18 +44,18 @@ sleep 5 - # prefix 10/8 should fail - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:one:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; } - - # any other address should work, as long as it sends key "one" - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 127.0.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 127.0.0.1 axfr -y hmac-sha256:two:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; } - - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 127.0.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 127.0.0.1 axfr -y hmac-sha256:one:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; } - - echo "I:testing nested ACL processing" -@@ -67,31 +67,31 @@ sleep 5 - # should succeed - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.2 axfr -y two:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.2 axfr -y hmac-sha256:two:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; } - - # should succeed - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.2 axfr -y one:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.2 axfr -y hmac-sha256:one:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; } - - # should succeed - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:two:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; } - - # should succeed - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:two:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; } - - # but only one or the other should fail - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 127.0.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 127.0.0.1 axfr -y hmac-sha256:one:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; } - - t=`expr $t + 1` -@@ -102,7 +102,7 @@ grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $tt failed" ; status=1; } - # and other values? right out - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 127.0.0.1 axfr -y three:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 127.0.0.1 axfr -y hmac-sha256:three:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; } - - # now we only allow 10.53.0.1 *and* key one, or 10.53.0.2 *and* key two -@@ -113,31 +113,31 @@ sleep 5 - # should succeed - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.2 axfr -y two:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.2 axfr -y hmac-sha256:two:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; } - - # should succeed - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:one:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; } - - # should fail - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.2 axfr -y one:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.2 axfr -y hmac-sha256:one:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; } - - # should fail - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.1 axfr -y hmac-sha256:two:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; } - - # should fail - t=`expr $t + 1` - $DIG $DIGOPTS tsigzone. \ -- @10.53.0.2 -b 10.53.0.3 axfr -y one:1234abcd8765 -p 5300 > dig.out -+ @10.53.0.2 -b 10.53.0.3 axfr -y hmac-sha256:one:1234abcd8765 -p 5300 > dig.out - grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; } - - echo "I:testing allow-query-on ACL processing" -diff --git a/bin/tests/system/allow_query/ns2/named10.conf b/bin/tests/system/allow_query/ns2/named10.conf -index 17786e6f87..918b185671 100644 ---- a/bin/tests/system/allow_query/ns2/named10.conf -+++ b/bin/tests/system/allow_query/ns2/named10.conf -@@ -20,7 +20,7 @@ - controls { /* empty */ }; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/allow_query/ns2/named11.conf b/bin/tests/system/allow_query/ns2/named11.conf -index 3d225bd9a2..2ccd8d4b3f 100644 ---- a/bin/tests/system/allow_query/ns2/named11.conf -+++ b/bin/tests/system/allow_query/ns2/named11.conf -@@ -20,12 +20,12 @@ - controls { /* empty */ }; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key two { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234efgh8765"; - }; - -diff --git a/bin/tests/system/allow_query/ns2/named12.conf b/bin/tests/system/allow_query/ns2/named12.conf -index e5e64184c8..fd322bb709 100644 ---- a/bin/tests/system/allow_query/ns2/named12.conf -+++ b/bin/tests/system/allow_query/ns2/named12.conf -@@ -19,7 +19,7 @@ - controls { /* empty */ }; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/allow_query/ns2/named30.conf b/bin/tests/system/allow_query/ns2/named30.conf -index 9182f21af3..585436f1d9 100644 ---- a/bin/tests/system/allow_query/ns2/named30.conf -+++ b/bin/tests/system/allow_query/ns2/named30.conf -@@ -20,7 +20,7 @@ - controls { /* empty */ }; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/allow_query/ns2/named31.conf b/bin/tests/system/allow_query/ns2/named31.conf -index 19efdf397e..d7f0e80616 100644 ---- a/bin/tests/system/allow_query/ns2/named31.conf -+++ b/bin/tests/system/allow_query/ns2/named31.conf -@@ -20,12 +20,12 @@ - controls { /* empty */ }; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key two { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234efgh8765"; - }; - -diff --git a/bin/tests/system/allow_query/ns2/named32.conf b/bin/tests/system/allow_query/ns2/named32.conf -index 3c207f3422..4d66a3812d 100644 ---- a/bin/tests/system/allow_query/ns2/named32.conf -+++ b/bin/tests/system/allow_query/ns2/named32.conf -@@ -19,7 +19,7 @@ - controls { /* empty */ }; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/allow_query/ns2/named40.conf b/bin/tests/system/allow_query/ns2/named40.conf -index cb81c79e5d..c581c5eefd 100644 ---- a/bin/tests/system/allow_query/ns2/named40.conf -+++ b/bin/tests/system/allow_query/ns2/named40.conf -@@ -23,12 +23,12 @@ acl accept { 10.53.0.2; }; - acl badaccept { 10.53.0.1; }; - - key one { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234abcd8765"; - }; - - key two { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "1234efgh8765"; - }; - -diff --git a/bin/tests/system/allow_query/tests.sh b/bin/tests/system/allow_query/tests.sh -index 0592c342d4..c5ef867451 100644 ---- a/bin/tests/system/allow_query/tests.sh -+++ b/bin/tests/system/allow_query/tests.sh -@@ -195,7 +195,7 @@ sleep 5 - - echo "I:test $n: key allowed - query allowed" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 - grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -@@ -209,7 +209,7 @@ sleep 5 - - echo "I:test $n: key not allowed - query refused" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1 - grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -@@ -223,7 +223,7 @@ sleep 5 - - echo "I:test $n: key disallowed - query refused" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 - grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -@@ -366,7 +366,7 @@ sleep 5 - - echo "I:test $n: views key allowed - query allowed" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 - grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.normal.example' dig.out.ns2.$n > /dev/null || ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -@@ -380,7 +380,7 @@ sleep 5 - - echo "I:test $n: views key not allowed - query refused" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:two:1234efgh8765 a.normal.example a > dig.out.ns2.$n || ret=1 - grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -@@ -394,7 +394,7 @@ sleep 5 - - echo "I:test $n: views key disallowed - query refused" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.normal.example a > dig.out.ns2.$n || ret=1 - grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.normal.example' dig.out.ns2.$n > /dev/null && ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -@@ -530,7 +530,7 @@ status=`expr $status + $ret` - n=`expr $n + 1` - echo "I:test $n: zone key allowed - query allowed" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.keyallow.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.keyallow.example a > dig.out.ns2.$n || ret=1 - grep 'status: NOERROR' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.keyallow.example' dig.out.ns2.$n > /dev/null || ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -@@ -540,7 +540,7 @@ status=`expr $status + $ret` - n=`expr $n + 1` - echo "I:test $n: zone key not allowed - query refused" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y two:1234efgh8765 a.keyallow.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:two:1234efgh8765 a.keyallow.example a > dig.out.ns2.$n || ret=1 - grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.keyallow.example' dig.out.ns2.$n > /dev/null && ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -@@ -550,7 +550,7 @@ status=`expr $status + $ret` - n=`expr $n + 1` - echo "I:test $n: zone key disallowed - query refused" - ret=0 --$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y one:1234abcd8765 a.keydisallow.example a > dig.out.ns2.$n || ret=1 -+$DIG $DIGOPTS @10.53.0.2 -b 10.53.0.2 -y hmac-sha256:one:1234abcd8765 a.keydisallow.example a > dig.out.ns2.$n || ret=1 - grep 'status: REFUSED' dig.out.ns2.$n > /dev/null || ret=1 - grep '^a.keydisallow.example' dig.out.ns2.$n > /dev/null && ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi -diff --git a/bin/tests/system/checkconf/bad-tsig.conf b/bin/tests/system/checkconf/bad-tsig.conf -index 8f0ecf7ea0..0e4718994f 100644 ---- a/bin/tests/system/checkconf/bad-tsig.conf -+++ b/bin/tests/system/checkconf/bad-tsig.conf -@@ -18,7 +18,7 @@ - - /* Bad secret */ - key "badtsig" { -- algorithm hmac-md5; -+ algorithm hmac-sha256; - secret "jEdD+BPKg=="; - }; - -diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in -index 930928b429..420320c737 100644 ---- a/bin/tests/system/conf.sh.in -+++ b/bin/tests/system/conf.sh.in -@@ -56,6 +56,10 @@ JOURNALPRINT=$TOP/bin/tools/named-journalprint - VERIFY=$TOP/bin/dnssec/dnssec-verify - ARPANAME=$TOP/bin/tools/arpaname - SAMPLE=$TOP/lib/export/samples/sample -+GENRANDOM=$TOP/bin/tools/genrandom -+FEATURETEST=$TOP/bin/tests/system/feature-test -+ -+RANDFILE=$TOP/bin/tests/system/random.data - - # The "stress" test is not run by default since it creates enough - # load on the machine to make it unusable to other users. -@@ -89,4 +93,4 @@ fi - - export NAMED LWRESD DIG NSUPDATE KEYGEN KEYFRLAB SIGNER KEYSIGNER KEYSETTOOL \ - PERL PYTHON SUBDIRS RNDC CHECKZONE PK11GEN PK11LIST PK11DEL TESTSOCK6 \ -- JOURNALPRINT ARPANAME SAMPLE -+ JOURNALPRINT ARPANAME SAMPLE FEATURETEST -diff --git a/bin/tests/system/digdelv/ns2/example.db b/bin/tests/system/digdelv/ns2/example.db -index 0a1aa5d615..fd3ed3a045 100644 ---- a/bin/tests/system/digdelv/ns2/example.db -+++ b/bin/tests/system/digdelv/ns2/example.db -@@ -41,10 +41,13 @@ foo SSHFP 2 1 123456789abcdef67890123456789abcdef67890 - ;; - ;; we are not testing DNSSEC behavior, so we don't care about the semantics - ;; of the following records. --dnskey 300 DNSKEY 256 3 1 ( -- AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg -- +Ge4noWROpTWOIBvm76zeJPWs4Zfqa1IsswD -- Ix5Mqeg0zwclz59uecKsKyx5w9IhtZ8plc4R -- b9VIE5x7KNHAYTvTO5d4S8M= -- ) -+dnskey 300 DNSKEY 256 3 8 ( -+ AwEAAaWmCoDpj2K59zcpqnmnQM7IC/XbjS6jIP7uTBR4X7p1bdQJzAeo -+ EnMhnpnxPp0j+20eZm4847DB2U+HuHy79Mvqd3aozTmfBJvzjKs9qyba -+ zY/ZHn6BDYxNJiFfjSS/VJ1KuQPDbpCzhm2hbvT5s9nSOaG0WyRk+d+R -+ qEca11E7ZKkmmNiGlyzMAgfmTTBwgxWBAAhvd9nU1GqD6eQ6Z63hpTc/ -+ KDIHnFTo7pOcZ4z5urIKUMCMcFytedETlEoR5CIWGPdQq2eIEEMfn5ld -+ QqdEZRHVErD9og8aluJ2s767HZb8LzjCfYgBFoT9/n48T75oZLEKtSkG -+ /idCeeQlaLU= -+ ) - -diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh -index a19256cde3..bdfacf9fb4 100644 ---- a/bin/tests/system/digdelv/tests.sh -+++ b/bin/tests/system/digdelv/tests.sh -@@ -59,7 +59,7 @@ if [ -x ${DIG} ] ; then - echo "I:checking dig +rrcomments works for DNSKEY($n)" - ret=0 - $DIG $DIGOPTS +tcp @10.53.0.3 +rrcomments DNSKEY dnskey.example > dig.out.test$n || ret=1 -- grep "; ZSK; alg = RSAMD5 *; key id = 30795" < dig.out.test$n > /dev/null || ret=1 -+ grep "; ZSK; alg = RSASHA256 *; key id = 36895$" < dig.out.test$n > /dev/null || ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` - -@@ -146,7 +146,7 @@ if [ -n "${DELV}" -a -x "${DELV}" ] ; then - echo "I:checking delv +rrcomments works for DNSKEY($n)" - ret=0 - $DELV $DELVOPTS @10.53.0.3 +rrcomments DNSKEY dnskey.example > delv.out.test$n || ret=1 -- grep "; ZSK; alg = RSAMD5 *; key id = 30795" < delv.out.test$n > /dev/null || ret=1 -+ grep "; ZSK; alg = RSASHA256 *; key id = 36895" < dig.out.test$n > /dev/null || ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` - -diff --git a/bin/tests/system/dlv/ns1/sign.sh b/bin/tests/system/dlv/ns1/sign.sh -index 9854f5b7ce..cf261c136c 100755 ---- a/bin/tests/system/dlv/ns1/sign.sh -+++ b/bin/tests/system/dlv/ns1/sign.sh -@@ -30,8 +30,8 @@ infile=root.db.in - zonefile=root.db - outfile=root.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -diff --git a/bin/tests/system/dlv/ns2/sign.sh b/bin/tests/system/dlv/ns2/sign.sh -index edcc8f21d4..4e142b00d8 100755 ---- a/bin/tests/system/dlv/ns2/sign.sh -+++ b/bin/tests/system/dlv/ns2/sign.sh -@@ -31,8 +31,8 @@ zonefile=druz.db - outfile=druz.pre - dlvzone=utld. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -diff --git a/bin/tests/system/dlv/ns3/sign.sh b/bin/tests/system/dlv/ns3/sign.sh -index 6bdc2f6cc5..64c5846f7d 100755 ---- a/bin/tests/system/dlv/ns3/sign.sh -+++ b/bin/tests/system/dlv/ns3/sign.sh -@@ -34,8 +34,8 @@ zonefile=child1.utld.db - outfile=child1.signed - dlvsets="$dlvsets dlvset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key ../ns6/dsset-grand.$zone >$zonefile - -@@ -49,8 +49,8 @@ zonefile=child3.utld.db - outfile=child3.signed - dlvsets="$dlvsets dlvset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key ../ns6/dsset-grand.$zone >$zonefile - -@@ -64,8 +64,8 @@ zonefile=child4.utld.db - outfile=child4.signed - dlvsets="$dlvsets dlvset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -79,8 +79,8 @@ zonefile=child5.utld.db - outfile=child5.signed - dlvsets="$dlvsets dlvset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key ../ns6/dsset-grand.$zone >$zonefile - -@@ -93,8 +93,8 @@ infile=child.db.in - zonefile=child7.utld.db - outfile=child7.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key ../ns6/dsset-grand.$zone >$zonefile - -@@ -107,8 +107,8 @@ infile=child.db.in - zonefile=child8.utld.db - outfile=child8.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -122,8 +122,8 @@ zonefile=child9.utld.db - outfile=child9.signed - dlvsets="$dlvsets dlvset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -136,8 +136,8 @@ zonefile=child10.utld.db - outfile=child10.signed - dlvsets="$dlvsets dlvset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -151,8 +151,8 @@ outfile=child1.druz.signed - dlvsets="$dlvsets dlvset-$zone" - dssets="$dssets dsset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key ../ns6/dsset-grand.$zone >$zonefile - -@@ -167,8 +167,8 @@ outfile=child3.druz.signed - dlvsets="$dlvsets dlvset-$zone" - dssets="$dssets dsset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key ../ns6/dsset-grand.$zone >$zonefile - -@@ -183,8 +183,8 @@ outfile=child4.druz.signed - dlvsets="$dlvsets dlvset-$zone" - dssets="$dssets dsset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -199,8 +199,8 @@ outfile=child5.druz.signed - dlvsets="$dlvsets dlvset-$zone" - dssets="$dssets dsset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key ../ns6/dsset-grand.$zone >$zonefile - -@@ -214,8 +214,8 @@ zonefile=child7.druz.db - outfile=child7.druz.signed - dssets="$dssets dsset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key ../ns6/dsset-grand.$zone >$zonefile - -@@ -228,8 +228,8 @@ infile=child.db.in - zonefile=child8.druz.db - outfile=child8.druz.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -243,8 +243,8 @@ zonefile=child9.druz.db - outfile=child9.druz.signed - dlvsets="$dlvsets dlvset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -258,8 +258,8 @@ outfile=child10.druz.signed - dlvsets="$dlvsets dlvset-$zone" - dssets="$dssets dsset-$zone" - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -272,8 +272,8 @@ infile=dlv.db.in - zonefile=dlv.utld.db - outfile=dlv.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $dlvsets $keyname1.key $keyname2.key >$zonefile - -diff --git a/bin/tests/system/dlv/ns6/sign.sh b/bin/tests/system/dlv/ns6/sign.sh -index 2bc133e5d6..227c1cb69f 100755 ---- a/bin/tests/system/dlv/ns6/sign.sh -+++ b/bin/tests/system/dlv/ns6/sign.sh -@@ -28,8 +28,8 @@ infile=child.db.in - zonefile=grand.child1.utld.db - outfile=grand.child1.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -43,8 +43,8 @@ zonefile=grand.child3.utld.db - outfile=grand.child3.signed - dlvzone=dlv.utld. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -58,8 +58,8 @@ zonefile=grand.child4.utld.db - outfile=grand.child4.signed - dlvzone=dlv.utld. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -73,8 +73,8 @@ zonefile=grand.child5.utld.db - outfile=grand.child5.signed - dlvzone=dlv.utld. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -88,8 +88,8 @@ zonefile=grand.child7.utld.db - outfile=grand.child7.signed - dlvzone=dlv.utld. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -103,8 +103,8 @@ zonefile=grand.child8.utld.db - outfile=grand.child8.signed - dlvzone=dlv.utld. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -118,8 +118,8 @@ zonefile=grand.child9.utld.db - outfile=grand.child9.signed - dlvzone=dlv.utld. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -132,8 +132,8 @@ zonefile=grand.child10.utld.db - outfile=grand.child10.signed - dlvzone=dlv.utld. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -145,8 +145,8 @@ infile=child.db.in - zonefile=grand.child1.druz.db - outfile=grand.child1.druz.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -160,8 +160,8 @@ zonefile=grand.child3.druz.db - outfile=grand.child3.druz.signed - dlvzone=dlv.druz. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -175,8 +175,8 @@ zonefile=grand.child4.druz.db - outfile=grand.child4.druz.signed - dlvzone=dlv.druz. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -190,8 +190,8 @@ zonefile=grand.child5.druz.db - outfile=grand.child5.druz.signed - dlvzone=dlv.druz. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -205,8 +205,8 @@ zonefile=grand.child7.druz.db - outfile=grand.child7.druz.signed - dlvzone=dlv.druz. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -220,8 +220,8 @@ zonefile=grand.child8.druz.db - outfile=grand.child8.druz.signed - dlvzone=dlv.druz. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -235,8 +235,8 @@ zonefile=grand.child9.druz.db - outfile=grand.child9.druz.signed - dlvzone=dlv.druz. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -249,8 +249,8 @@ zonefile=grand.child10.druz.db - outfile=grand.child10.druz.signed - dlvzone=dlv.druz. - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh -index 118b8a6d6b..0c4dcb4b19 100644 ---- a/bin/tests/system/dnssec/ns2/sign.sh -+++ b/bin/tests/system/dnssec/ns2/sign.sh -@@ -38,8 +38,8 @@ do - cp ../ns3/dsset-$subdomain.example. . - done - --keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone` --keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 768 -n zone $zone` -+keyname1=`$KEYGEN -q -r $RANDFILE -a DSA -b 1024 -n zone $zone` -+keyname2=`$KEYGEN -q -r $RANDFILE -a DSA -b 1024 -n zone $zone` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -@@ -98,7 +98,7 @@ privzone=private.secure.example. - privinfile=private.secure.example.db.in - privzonefile=private.secure.example.db - --privkeyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $privzone` -+privkeyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 1024 -n zone $privzone` - - cat $privinfile $privkeyname.key >$privzonefile - -@@ -111,7 +111,7 @@ dlvzone=dlv. - dlvinfile=dlv.db.in - dlvzonefile=dlv.db - --dlvkeyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $dlvzone` -+dlvkeyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 1024 -n zone $dlvzone` - - cat $dlvinfile $dlvkeyname.key dlvset-$privzone > $dlvzonefile - -diff --git a/bin/tests/system/dnssec/prereq.sh b/bin/tests/system/dnssec/prereq.sh -index 113e372c28..84630d8abc 100644 ---- a/bin/tests/system/dnssec/prereq.sh -+++ b/bin/tests/system/dnssec/prereq.sh -@@ -17,13 +17,4 @@ - - # $Id: prereq.sh,v 1.13 2009/10/28 00:27:10 marka Exp $ - --../../../tools/genrandom 400 random.data -- --if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1 --then -- rm -f Kfoo* --else -- echo "I:This test requires cryptography" >&2 -- echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 -- exit 1 --fi -+exec $SHELL ../testcrypto.sh -diff --git a/bin/tests/system/feature-test.c b/bin/tests/system/feature-test.c -new file mode 100644 -index 0000000000..495f46a32a ---- /dev/null -+++ b/bin/tests/system/feature-test.c -@@ -0,0 +1,159 @@ -+/* -+ * Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#ifdef WIN32 -+#include -+#endif -+ -+#ifndef MAXHOSTNAMELEN -+#ifdef HOST_NAME_MAX -+#define MAXHOSTNAMELEN HOST_NAME_MAX -+#else -+#define MAXHOSTNAMELEN 256 -+#endif -+#endif -+ -+static void -+usage() { -+ fprintf(stderr, "usage: feature-test \n"); -+ fprintf(stderr, "args:\n"); -+ fprintf(stderr, " --enable-filter-aaaa\n"); -+ fprintf(stderr, " --gethostname\n"); -+ fprintf(stderr, " --gssapi\n"); -+ fprintf(stderr, " --have-dlopen\n"); -+ fprintf(stderr, " --have-geoip\n"); -+ fprintf(stderr, " --have-libxml2\n"); -+ fprintf(stderr, " --md5\n"); -+ fprintf(stderr, " --rpz-nsip\n"); -+ fprintf(stderr, " --rpz-nsdname\n"); -+ fprintf(stderr, " --with-idn\n"); -+} -+ -+int -+main(int argc, char **argv) { -+ if (argc != 2) { -+ usage(); -+ return (1); -+ } -+ -+ if (strcmp(argv[1], "--enable-filter-aaaa") == 0) { -+#ifdef ALLOW_FILTER_AAAA -+ return (0); -+#else -+ return (1); -+#endif -+ } -+ -+ if (strcmp(argv[1], "--gethostname") == 0) { -+ char hostname[MAXHOSTNAMELEN]; -+ int n; -+#ifdef WIN32 -+ /* From lwres InitSocket() */ -+ WORD wVersionRequested; -+ WSADATA wsaData; -+ int err; -+ -+ wVersionRequested = MAKEWORD(2, 0); -+ err = WSAStartup( wVersionRequested, &wsaData ); -+ if (err != 0) { -+ fprintf(stderr, "WSAStartup() failed: %d\n", err); -+ exit(1); -+ } -+#endif -+ -+ n = gethostname(hostname, sizeof(hostname)); -+ if (n == -1) { -+ perror("gethostname"); -+ return(1); -+ } -+ fprintf(stdout, "%s\n", hostname); -+#ifdef WIN32 -+ WSACleanup(); -+#endif -+ return (0); -+ } -+ -+ if (strcmp(argv[1], "--gssapi") == 0) { -+#if defined(GSSAPI) -+ return (0); -+#else -+ return (1); -+#endif -+ } -+ -+ if (strcmp(argv[1], "--have-dlopen") == 0) { -+#if defined(HAVE_DLOPEN) && defined(ISC_DLZ_DLOPEN) -+ return (0); -+#else -+ return (1); -+#endif -+ } -+ -+ if (strcmp(argv[1], "--have-geoip") == 0) { -+#ifdef HAVE_GEOIP -+ return (0); -+#else -+ return (1); -+#endif -+ } -+ -+ if (strcmp(argv[1], "--have-libxml2") == 0) { -+#ifdef HAVE_LIBXML2 -+ return (0); -+#else -+ return (1); -+#endif -+ } -+ -+ if (strcmp(argv[1], "--md5") == 0) { -+ if (isc_md5_available()) { -+ return (0); -+ } else { -+ return (1); -+ } -+ } -+ -+ if (strcmp(argv[1], "--rpz-nsip") == 0) { -+#ifdef ENABLE_RPZ_NSIP -+ return (0); -+#else -+ return (1); -+#endif -+ } -+ -+ if (strcmp(argv[1], "--rpz-nsdname") == 0) { -+#ifdef ENABLE_RPZ_NSDNAME -+ return (0); -+#else -+ return (1); -+#endif -+ } -+ -+ if (strcmp(argv[1], "--with-idn") == 0) { -+#ifdef WITH_IDN -+ return (0); -+#else -+ return (1); -+#endif -+ } -+ -+ fprintf(stderr, "unknown arg: %s\n", argv[1]); -+ usage(); -+ return (1); -+} -diff --git a/bin/tests/system/filter-aaaa/ns1/sign.sh b/bin/tests/system/filter-aaaa/ns1/sign.sh -index 203e37ebfb..e0c696b986 100755 ---- a/bin/tests/system/filter-aaaa/ns1/sign.sh -+++ b/bin/tests/system/filter-aaaa/ns1/sign.sh -@@ -27,8 +27,8 @@ infile=signed.db.in - zonefile=signed.db.signed - outfile=signed.db.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -diff --git a/bin/tests/system/filter-aaaa/ns4/sign.sh b/bin/tests/system/filter-aaaa/ns4/sign.sh -index ff33b10a19..74d755763a 100755 ---- a/bin/tests/system/filter-aaaa/ns4/sign.sh -+++ b/bin/tests/system/filter-aaaa/ns4/sign.sh -@@ -27,8 +27,8 @@ infile=signed.db.in - zonefile=signed.db.signed - outfile=signed.db.signed - --keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` --keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone 2> /dev/null` -+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` -+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 1024 -n zone $zone 2> /dev/null` - - cat $infile $keyname1.key $keyname2.key >$zonefile - -diff --git a/bin/tests/system/keymgr/prereq.sh b/bin/tests/system/keymgr/prereq.sh -index be2546ec59..e71cc9f03a 100644 ---- a/bin/tests/system/keymgr/prereq.sh -+++ b/bin/tests/system/keymgr/prereq.sh -@@ -14,17 +14,4 @@ - # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - # PERFORMANCE OF THIS SOFTWARE. - --SYSTEMTESTTOP=.. --. $SYSTEMTESTTOP/conf.sh -- --../../../tools/genrandom 400 random.data -- --if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1 --then -- rm -f Kfoo* --else -- echo "I:This test requires cryptography" >&2 -- echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 -- exit 1 --fi --#exec $SHELL ../testcrypto.sh -+exec $SHELL ../testcrypto.sh -diff --git a/bin/tests/system/nsupdate/ns1/named.conf b/bin/tests/system/nsupdate/ns1/named.conf -index 86fe91d070..c53da11685 100644 ---- a/bin/tests/system/nsupdate/ns1/named.conf -+++ b/bin/tests/system/nsupdate/ns1/named.conf -@@ -42,7 +42,7 @@ controls { - }; - - key altkey { -- algorithm hmac-md5; -+ algorithm hmac-sha512; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/nsupdate/ns2/named.conf b/bin/tests/system/nsupdate/ns2/named.conf -index 6db32202ff..68022656ec 100644 ---- a/bin/tests/system/nsupdate/ns2/named.conf -+++ b/bin/tests/system/nsupdate/ns2/named.conf -@@ -33,7 +33,7 @@ options { - }; - - key altkey { -- algorithm hmac-md5; -+ algorithm hmac-sha512; - secret "1234abcd8765"; - }; - -diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh -index bb015142da..e97406956a 100644 ---- a/bin/tests/system/nsupdate/setup.sh -+++ b/bin/tests/system/nsupdate/setup.sh -@@ -53,8 +53,13 @@ EOF - - ../../../tools/genrandom 400 random.data - $DDNSCONFGEN -q -r random.data -z example.nil > ns1/ddns.key -+if $FEATURETEST --md5; then -+ $DDNSCONFGEN -q -r random.data -a hmac-md5 -k md5-key -z keytests.nil > ns1/md5.key -+else -+ echo -n > ns1/md5.key -+fi -+ - --$DDNSCONFGEN -q -r random.data -a hmac-md5 -k md5-key -z keytests.nil > ns1/md5.key - $DDNSCONFGEN -q -r random.data -a hmac-sha1 -k sha1-key -z keytests.nil > ns1/sha1.key - $DDNSCONFGEN -q -r random.data -a hmac-sha224 -k sha224-key -z keytests.nil > ns1/sha224.key - $DDNSCONFGEN -q -r random.data -a hmac-sha256 -k sha256-key -z keytests.nil > ns1/sha256.key -diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh -index b9a1c90536..821d7a65e2 100644 ---- a/bin/tests/system/nsupdate/tests.sh -+++ b/bin/tests/system/nsupdate/tests.sh -@@ -516,7 +516,14 @@ fi - n=`expr $n + 1` - ret=0 - echo "I:check TSIG key algorithms ($n)" --for alg in md5 sha1 sha224 sha256 sha384 sha512; do -+if $FEATURETEST --md5 -+then -+ ALGS="md5 sha1 sha224 sha256 sha384 sha512" -+else -+ ALGS="sha1 sha224 sha256 sha384 sha512" -+ echo_i "skipping disabled md5 algorithm" -+fi -+for alg in $ALGS; do - $NSUPDATE -k ns1/${alg}.key < /dev/null || ret=1 - server 10.53.0.1 5300 - update add ${alg}.keytests.nil. 600 A 10.10.10.3 -@@ -524,7 +531,7 @@ send - END - done - sleep 2 --for alg in md5 sha1 sha224 sha256 sha384 sha512; do -+for alg in $ALGS; do - $DIG +short @10.53.0.1 -p 5300 ${alg}.keytests.nil | grep 10.10.10.3 > /dev/null 2>&1 || ret=1 - done - if [ $ret -ne 0 ]; then -diff --git a/bin/tests/system/rndc/setup.sh b/bin/tests/system/rndc/setup.sh -index ce80005faf..a7c66841cc 100644 ---- a/bin/tests/system/rndc/setup.sh -+++ b/bin/tests/system/rndc/setup.sh -@@ -22,7 +22,7 @@ SYSTEMTESTTOP=.. - - sh clean.sh - --../../../tools/genrandom 400 random.data -+../../../tools/genrandom 800 random.data - - sh ../genzone.sh 2 >ns2/nil.db - sh ../genzone.sh 2 >ns2/other.db -@@ -37,7 +37,7 @@ make_key () { - sed 's/allow { 10.53.0.4/allow { any/' >> ns4/named.conf - } - --make_key 1 hmac-md5 -+$FEATURETEST --md5 && make_key 1 hmac-md5 - make_key 2 hmac-sha1 - make_key 3 hmac-sha224 - make_key 4 hmac-sha256 -diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh -index 01dbc811ae..20a90850d1 100644 ---- a/bin/tests/system/rndc/tests.sh -+++ b/bin/tests/system/rndc/tests.sh -@@ -246,14 +246,20 @@ if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` - - echo "I:testing rndc with hmac-md5" --ret=0 --$RNDC -s 10.53.0.4 -p 9951 -c ns4/key1.conf status > /dev/null 2>&1 || ret=1 --for i in 2 3 4 5 6 --do -- $RNDC -s 10.53.0.4 -p 9951 -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1 --done --if [ $ret != 0 ]; then echo "I:failed"; fi --status=`expr $status + $ret` -+if $FEATURETEST --md5 -+then -+ echo "I:testing rndc with hmac-md5" -+ ret=0 -+ $RNDC -s 10.53.0.4 -p 9951 -c ns4/key1.conf status > /dev/null 2>&1 || ret=1 -+ for i in 2 3 4 5 6 -+ do -+ $RNDC -s 10.53.0.4 -p 9951 -c ns4/key${i}.conf status > /dev/null 2>&1 && ret=1 -+ done -+ if [ $ret != 0 ]; then echo_i "failed"; fi -+ status=`expr $status + $ret` -+else -+ echo "W:skipping rndc with hmac-md5" -+fi - - echo "I:testing rndc with hmac-sha1" - ret=0 -diff --git a/bin/tests/system/testcrypto.sh b/bin/tests/system/testcrypto.sh -new file mode 100644 -index 0000000000..e21f18b5f5 ---- /dev/null -+++ b/bin/tests/system/testcrypto.sh -@@ -0,0 +1,71 @@ -+#!/bin/sh -+# -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+SYSTEMTESTTOP=${SYSTEMTESTTOP:=..} -+. $SYSTEMTESTTOP/conf.sh -+ -+# Unlike 9.11, keep generated data in current directory -+RANDFILE=random.data -+ -+test -r $RANDFILE || $GENRANDOM 800 $RANDFILE -+ -+prog=$0 -+ -+args="-r $RANDFILE" -+alg="-a RSASHA1 -b 2048" -+quiet=0 -+ -+msg1="cryptography" -+msg2="--with-openssl, or --enable-native-pkcs11 --with-pkcs11" -+while test "$#" -gt 0; do -+ case $1 in -+ -q) -+ args="$args -q" -+ quiet=1 -+ ;; -+ rsa|RSA) -+ alg="" -+ msg1="RSA cryptography" -+ ;; -+ gost|GOST) -+ alg="-a eccgost" -+ msg1="GOST cryptography" -+ msg2="--with-gost" -+ ;; -+ ecdsa|ECDSA) -+ alg="-a ecdsap256sha256" -+ msg1="ECDSA cryptography" -+ msg2="--with-ecdsa" -+ ;; -+ *) -+ echo "${prog}: unknown argument" -+ exit 1 -+ ;; -+ esac -+ shift -+done -+ -+ -+if $KEYGEN $args $alg foo > /dev/null 2>&1 -+then -+ rm -f Kfoo* -+else -+ if test $quiet -eq 0; then -+ echo "I:This test requires support for $msg1" >&2 -+ echo "I:configure with $msg2" >&2 -+ fi -+ exit 255 -+fi -diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c -index af17582096..b61b5d0796 100644 ---- a/bin/tests/system/tkey/keycreate.c -+++ b/bin/tests/system/tkey/keycreate.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -143,6 +144,8 @@ sendquery(isc_task_t *task, isc_event_t *event) { - static char keystr[] = "0123456789ab"; - - isc_event_free(&event); -+ if (isc_md5_available() == ISC_FALSE) -+ CHECK("MD5 was disabled", ISC_R_NOTIMPLEMENTED); - - result = ISC_R_FAILURE; - if (inet_pton(AF_INET, "10.53.0.1", &inaddr) != 1) -diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c -index 1bb33e85fe..da4b1c3c09 100644 ---- a/bin/tests/system/tkey/keydelete.c -+++ b/bin/tests/system/tkey/keydelete.c -@@ -228,12 +228,18 @@ main(int argc, char **argv) { - type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY; - result = dst_key_fromnamedfile(keyname, NULL, type, mctx, &dstkey); - CHECK("dst_key_fromnamedfile", result); -- result = dns_tsigkey_createfromkey(dst_key_name(dstkey), -- DNS_TSIG_HMACMD5_NAME, -- dstkey, ISC_TRUE, NULL, 0, 0, -- mctx, ring, &tsigkey); -- dst_key_free(&dstkey); -- CHECK("dns_tsigkey_createfromkey", result); -+ if (isc_md5_available()) { -+ result = dns_tsigkey_createfromkey(dst_key_name(dstkey), -+ DNS_TSIG_HMACMD5_NAME, -+ dstkey, ISC_TRUE, -+ NULL, 0, 0, -+ mctx, ring, &tsigkey); -+ dst_key_free(&dstkey); -+ CHECK("dns_tsigkey_createfromkey", result); -+ } else { -+ dst_key_free(&dstkey); -+ CHECK("MD5 was disabled", ISC_R_NOTIMPLEMENTED); -+ } - - (void)isc_app_run(); - -diff --git a/bin/tests/system/tkey/prereq.sh b/bin/tests/system/tkey/prereq.sh -index 66295fee90..310849f08e 100644 ---- a/bin/tests/system/tkey/prereq.sh -+++ b/bin/tests/system/tkey/prereq.sh -@@ -17,13 +17,4 @@ - - # $Id: prereq.sh,v 1.12 2009/03/02 23:47:43 tbox Exp $ - --../../../tools/genrandom 400 random.data -- --if $KEYGEN -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1 --then -- rm -f foo* --else -- echo "I:This test requires cryptography" >&2 -- echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2 -- exit 1 --fi -+exec $SHELL ../testcrypto.sh -diff --git a/bin/tests/system/tsig/clean.sh b/bin/tests/system/tsig/clean.sh -index 0e98b4047b..b11a378006 100644 ---- a/bin/tests/system/tsig/clean.sh -+++ b/bin/tests/system/tsig/clean.sh -@@ -23,3 +23,4 @@ - rm -f dig.out.* - rm -f */named.memstats - rm -f */named.run -+rm -f ns1/rndc5.conf -diff --git a/bin/tests/system/tsig/ns1/named.conf b/bin/tests/system/tsig/ns1/named.conf -index b48de835f4..e7e568acc7 100644 ---- a/bin/tests/system/tsig/ns1/named.conf -+++ b/bin/tests/system/tsig/ns1/named.conf -@@ -30,10 +30,7 @@ options { - notify no; - }; - --key "md5" { -- secret "97rnFx24Tfna4mHPfgnerA=="; -- algorithm hmac-md5; --}; -+# md5 key included from rndc5.conf - - key "sha1" { - secret "FrSt77yPTFx6hTs4i2tKLB9LmE0="; -@@ -60,10 +57,7 @@ key "sha512" { - algorithm hmac-sha512; - }; - --key "md5-trunc" { -- secret "97rnFx24Tfna4mHPfgnerA=="; -- algorithm hmac-md5-80; --}; -+# md5-trunc key included from rndc5.conf - - key "sha1-trunc" { - secret "FrSt77yPTFx6hTs4i2tKLB9LmE0="; -@@ -94,3 +88,5 @@ zone "example.nil" { - type master; - file "example.db"; - }; -+ -+include "rndc5.conf"; -diff --git a/bin/tests/system/tsig/ns1/rndc5.conf.in b/bin/tests/system/tsig/ns1/rndc5.conf.in -new file mode 100644 -index 0000000000..f9b17d6e8e ---- /dev/null -+++ b/bin/tests/system/tsig/ns1/rndc5.conf.in -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC") -+ * -+ * This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ * -+ * See the COPYRIGHT file distributed with this work for additional -+ * information regarding copyright ownership. -+ */ -+ -+/* These md5 keys are used only when MD5 is not disabled in build */ -+key "md5" { -+ secret "97rnFx24Tfna4mHPfgnerA=="; -+ algorithm hmac-md5; -+}; -+ -+key "md5-trunc" { -+ secret "97rnFx24Tfna4mHPfgnerA=="; -+ algorithm hmac-md5-80; -+}; -+ -diff --git a/bin/tests/system/tsig/setup.sh b/bin/tests/system/tsig/setup.sh -new file mode 100644 -index 0000000000..7f9049ae76 ---- /dev/null -+++ b/bin/tests/system/tsig/setup.sh -@@ -0,0 +1,25 @@ -+#!/bin/sh -+# -+# Copyright (C) Internet Systems Consortium, Inc. ("ISC") -+# -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+# -+# See the COPYRIGHT file distributed with this work for additional -+# information regarding copyright ownership. -+ -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+ -+$SHELL clean.sh -+ -+test -r $RANDFILE || $GENRANDOM 800 $RANDFILE -+ -+if $FEATURETEST --md5 -+then -+ # Include MD5 keys only if it is -+ cp ns1/rndc5.conf.in ns1/rndc5.conf -+else -+ echo "# MD5 disabled" > ns1/rndc5.conf -+fi -diff --git a/bin/tests/system/tsig/tests.sh b/bin/tests/system/tsig/tests.sh -index 50ac8d23e6..bd502dd718 100644 ---- a/bin/tests/system/tsig/tests.sh -+++ b/bin/tests/system/tsig/tests.sh -@@ -31,22 +31,27 @@ sha512="jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4f - - status=0 - --echo "I:fetching using hmac-md5 (old form)" --ret=0 --$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\ -- -y "md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.old || ret=1 --grep -i "md5.*TSIG.*NOERROR" dig.out.md5.old > /dev/null || ret=1 --if [ $ret -eq 1 ] ; then -- echo "I: failed"; status=1 --fi -- --echo "I:fetching using hmac-md5 (new form)" --ret=0 --$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\ -- -y "hmac-md5:md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.new || ret=1 --grep -i "md5.*TSIG.*NOERROR" dig.out.md5.new > /dev/null || ret=1 --if [ $ret -eq 1 ] ; then -- echo "I: failed"; status=1 -+if $FEATURETEST --md5 -+then -+ echo "I:fetching using hmac-md5 (old form)" -+ ret=0 -+ $DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\ -+ -y "md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.old || ret=1 -+ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.old > /dev/null || ret=1 -+ if [ $ret -eq 1 ] ; then -+ echo "I: failed"; status=1 -+ fi -+ -+ echo "I:fetching using hmac-md5 (new form)" -+ ret=0 -+ $DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\ -+ -y "hmac-md5:md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.new || ret=1 -+ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.new > /dev/null || ret=1 -+ if [ $ret -eq 1 ] ; then -+ echo_i "failed"; status=1 -+ fi -+else -+ echo_i "skipping using hmac-md5" - fi - - echo "I:fetching using hmac-sha1" -@@ -99,13 +104,19 @@ fi - # Truncated TSIG - # - # -+ -+if $FEATURETEST --md5 -+then - echo "I:fetching using hmac-md5 (trunc)" --ret=0 --$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\ -- -y "hmac-md5-80:md5-trunc:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.trunc || ret=1 --grep -i "md5-trunc.*TSIG.*NOERROR" dig.out.md5.trunc > /dev/null || ret=1 --if [ $ret -eq 1 ] ; then -- echo "I: failed"; status=1 -+ ret=0 -+ $DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\ -+ -y "hmac-md5-80:md5-trunc:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.trunc || ret=1 -+ grep -i "md5-trunc.*TSIG.*NOERROR" dig.out.md5.trunc > /dev/null || ret=1 -+ if [ $ret -eq 1 ] ; then -+ echo "I: failed"; status=1 -+ fi -+else -+ echo "W:skipping using hmac-md5 (trunc)" - fi - - echo "I:fetching using hmac-sha1 (trunc)" -@@ -159,13 +170,19 @@ fi - # Check for bad truncation. - # - # --echo "I:fetching using hmac-md5-80 (BADTRUNC)" --ret=0 --$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\ -- -y "hmac-md5-80:md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5-80 || ret=1 --grep -i "md5.*TSIG.*BADTRUNC" dig.out.md5-80 > /dev/null || ret=1 --if [ $ret -eq 1 ] ; then -- echo "I: failed"; status=1 -+ -+if $FEATURETEST --md5 -+then -+ echo "I:fetching using hmac-md5-80 (BADTRUNC)" -+ ret=0 -+ $DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\ -+ -y "hmac-md5-80:md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5-80 || ret=1 -+ grep -i "md5.*TSIG.*BADTRUNC" dig.out.md5-80 > /dev/null || ret=1 -+ if [ $ret -eq 1 ] ; then -+ echo "I: failed"; status=1 -+ fi -+else -+ echo "W:skipping using hmac-md5-80 (BADTRUNC)" - fi - - echo "I:fetching using hmac-sha1-80 (BADTRUNC)" -diff --git a/bin/tests/system/tsiggss/setup.sh b/bin/tests/system/tsiggss/setup.sh -index 00222bad05..e795df3bff 100644 ---- a/bin/tests/system/tsiggss/setup.sh -+++ b/bin/tests/system/tsiggss/setup.sh -@@ -26,5 +26,5 @@ rm -f ns1/*.jnl ns1/K*.key ns1/K*.private ns1/_default.tsigkeys - - ../../../tools/genrandom 400 $RANDFILE - --key=`$KEYGEN -Cq -K ns1 -a DSA -b 512 -r $RANDFILE -n HOST -T KEY key.example.nil.` -+key=`$KEYGEN -Cq -K ns1 -a DSA -b 1024 -r $RANDFILE -n HOST -T KEY key.example.nil.` - cat ns1/example.nil.db.in ns1/${key}.key > ns1/example.nil.db -diff --git a/bin/tests/system/upforwd/ns1/named.conf b/bin/tests/system/upforwd/ns1/named.conf -index 8d9d2fa0d9..c3c0238073 100644 ---- a/bin/tests/system/upforwd/ns1/named.conf -+++ b/bin/tests/system/upforwd/ns1/named.conf -@@ -18,7 +18,7 @@ - /* $Id: named.conf,v 1.11 2007/06/18 23:47:31 tbox Exp $ */ - - key "update.example." { -- algorithm "hmac-md5"; -+ algorithm "hmac-sha256"; - secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; - }; - -diff --git a/bin/tests/system/upforwd/tests.sh b/bin/tests/system/upforwd/tests.sh -index a138649ac3..e14a592db6 100644 ---- a/bin/tests/system/upforwd/tests.sh -+++ b/bin/tests/system/upforwd/tests.sh -@@ -68,7 +68,7 @@ if [ $ret != 0 ] ; then echo "I:failed"; status=`expr $status + $ret`; fi - - echo "I:updating zone (signed)" - ret=0 --$NSUPDATE -y update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K -- - < -Date: Fri, 22 Jun 2018 14:05:18 +0200 -Subject: [PATCH 1/2] Squashed commit of the following: -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -commit 3fd542379fa381b54381e07d6625ce53f9f9b1f0 -Author: Petr Menšík -Date: Thu Jun 21 12:00:35 2018 +0200 - - Revert "4450. [port] Provide more nuanced HSM support which better matches" - - This reverts commit f3b4d031c1f714ff6e862670663aa5a18650951e. - - Revert PK11_MD5_DISABLED also from remaining files. Keep documentation - changes. - -commit f90934f734796595135cdd7a5008555a615dfe8e -Author: Petr Menšík -Date: Wed Jun 20 19:31:19 2018 +0200 - - Fix rndc-confgen default algorithm, report true algorithm in usage. - -commit dd53212c12c6943a21a3c24d60995edd19e1d9f7 -Author: Petr Menšík -Date: Fri Feb 23 21:21:30 2018 +0100 - - Cleanup only if initialization was successful - -commit f163ea51c46bb22bf264a1ac983e2027e43845fa -Author: Petr Menšík -Date: Mon Feb 5 12:19:28 2018 +0100 - - Ensure dst backend is initialized first even before hmac algorithms. - -commit 58751b60bd39168b7c8f817ede70473842432081 -Author: Petr Menšík -Date: Mon Feb 5 12:17:54 2018 +0100 - - Skip initialization of MD5 based algorithms if not available. - -commit 0572b98430d3c80f4a0b0c592b1e3bf7fde9b768 -Author: Petr Menšík -Date: Mon Feb 5 10:21:27 2018 +0100 - - Change secalgs skipping to be more safe - -commit 994f497a032930fce1370d507a265fbb293c66f4 -Author: Petr Menšík -Date: Wed Jan 31 18:26:11 2018 +0100 - - Skip MD5 algorithm also in case of NULL name - -commit abd82fbd2507c4b8f20e1ade202fd66d224fd646 -Author: Petr Menšík -Date: Wed Jan 31 16:54:29 2018 +0100 - - Revert part of commit 1b5c641416eb6de7fc232fc89d31a40a4d439f3d related - to SHA1. - -commit b3c832d53a14a0779f598869bb99685c8e4b2bc0 -Author: Petr Menšík -Date: Wed Jan 31 11:38:12 2018 +0100 - - Make MD5 behave like unknown algorithm in TSIG. - -commit a64a3d6962ee93d6f8699b29bd6507dba0c244ed -Author: Petr Menšík -Date: Tue Nov 28 20:14:37 2017 +0100 - - Select token with most supported functions, instead of demanding it must support all functions - - Initialize PKCS#11 always until successfully initialized - -commit db118c6368668099ea1b6e75860cc12e178afa3b -Author: Petr Menšík -Date: Mon Jan 22 16:17:44 2018 +0100 - - Handle MD5 unavailability from DST - -commit 8f8824dca2f5b4d5a3a176d31ac3ee612321c4e3 -Author: Petr Menšík -Date: Mon Jan 22 14:11:16 2018 +0100 - - Check runtime flag from library and applications, fail gracefully. - -commit bd431384af7dcde8827e670c8749517ad677a967 -Author: Petr Menšík -Date: Mon Jan 22 08:39:08 2018 +0100 - - Modify libraries to use isc_md5_available() if PK11_MD5_DISABLE is not - defined. - TODO: pk11.c should accept slot without MD5 support. - -commit 160b13979ef3d0e92d2dd52d0987a3ec979be6cf -Author: Petr Menšík -Date: Mon Jan 22 07:21:04 2018 +0100 - - Add runtime detection whether MD5 is useable. - -commit 23b27ce0f2ad496c331ae40349cc1074a1b11804 -Author: Mark Andrews -Date: Fri Aug 19 08:25:54 2016 +1000 - - 4450. [port] Provide more nuanced HSM support which better matches - the specific PKCS11 providers capabilities. [RT #42458] - - (cherry picked from commit 8ee6f289d87851a5b898b24a64587f0e6bc225bc) - -Fix compiler warnings ---- - bin/confgen/keygen.c | 10 +++++- - bin/confgen/rndc-confgen.c | 12 ++++--- - bin/confgen/rndc-confgen.docbook | 3 +- - bin/dig/dig.c | 5 ++- - bin/dig/dig.docbook | 6 ++-- - bin/dig/dighost.c | 14 ++++++-- - bin/dnssec/dnssec-keyfromlabel.c | 9 +++++ - bin/dnssec/dnssec-keygen.c | 19 +++++++++-- - bin/named/config.c | 23 +++++++++++-- - bin/nsupdate/nsupdate.c | 20 +++++++---- - bin/nsupdate/nsupdate.docbook | 9 ++++- - bin/rndc/rndc.c | 3 +- - bin/tests/hashes/t_hashes.c | 20 ++++++----- - lib/bind9/check.c | 8 +++++ - lib/dns/dst_api.c | 23 +++++++++---- - lib/dns/dst_internal.h | 3 +- - lib/dns/dst_parse.c | 12 ++++++- - lib/dns/hmac_link.c | 2 +- - lib/dns/opensslrsa_link.c | 4 +++ - lib/dns/pkcs11rsa_link.c | 25 ++++++++++++-- - lib/dns/rcode.c | 19 +++++++++-- - lib/dns/tests/tsig_test.c | 1 + - lib/dns/tkey.c | 9 +++++ - lib/dns/tsec.c | 8 ++++- - lib/dns/tsig.c | 22 +++++------- - lib/isc/include/isc/md5.h | 3 ++ - lib/isc/md5.c | 59 ++++++++++++++++++++++++++++++++ - lib/isc/pk11.c | 72 +++++++++++++++++++++++++++++++--------- - lib/isccc/cc.c | 48 ++++++++++++++++----------- - 29 files changed, 373 insertions(+), 98 deletions(-) - -diff --git a/bin/confgen/keygen.c b/bin/confgen/keygen.c -index d0cdafed36..4eb027e723 100644 ---- a/bin/confgen/keygen.c -+++ b/bin/confgen/keygen.c -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -69,7 +70,7 @@ alg_totext(dns_secalg_t alg) { - */ - dns_secalg_t - alg_fromtext(const char *name) { -- if (strcmp(name, "hmac-md5") == 0) -+ if (strcmp(name, "hmac-md5") == 0 && isc_md5_available()) - return DST_ALG_HMACMD5; - if (strcmp(name, "hmac-sha1") == 0) - return DST_ALG_HMACSHA1; -@@ -126,6 +127,13 @@ generate_key(isc_mem_t *mctx, const char *randomfile, dns_secalg_t alg, - - switch (alg) { - case DST_ALG_HMACMD5: -+ if (isc_md5_available() == ISC_FALSE) { -+ fatal("unsupported algorithm %d\n", alg); -+ } else if (keysize < 1 || keysize > 512) { -+ fatal("keysize %d out of range (must be 1-512)\n", -+ keysize); -+ } -+ break; - case DST_ALG_HMACSHA1: - case DST_ALG_HMACSHA224: - case DST_ALG_HMACSHA256: -diff --git a/bin/confgen/rndc-confgen.c b/bin/confgen/rndc-confgen.c -index 3fd54fe2bb..c48a38f094 100644 ---- a/bin/confgen/rndc-confgen.c -+++ b/bin/confgen/rndc-confgen.c -@@ -41,6 +41,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -66,7 +67,7 @@ const char *progname; - - isc_boolean_t verbose = ISC_FALSE; - --const char *keyfile, *keydef; -+const char *keyfile, *keydef, *algdef; - - ISC_PLATFORM_NORETURN_PRE static void - usage(int status) ISC_PLATFORM_NORETURN_POST; -@@ -79,7 +80,7 @@ Usage:\n\ - %s [-a] [-b bits] [-c keyfile] [-k keyname] [-p port] [-r randomfile] \ - [-s addr] [-t chrootdir] [-u user]\n\ - -a: generate just the key clause and write it to keyfile (%s)\n\ -- -A alg: algorithm (default hmac-md5)\n\ -+ -A alg: algorithm (default %s)\n\ - -b bits: from 1 through 512, default 256; total length of the secret\n\ - -c keyfile: specify an alternate key file (requires -a)\n\ - -k keyname: the name as it will be used in named.conf and rndc.conf\n\ -@@ -88,7 +89,7 @@ Usage:\n\ - -s addr: the address to which rndc should connect\n\ - -t chrootdir: write a keyfile in chrootdir as well (requires -a)\n\ - -u user: set the keyfile owner to \"user\" (requires -a)\n", -- progname, keydef); -+ progname, keydef, algdef); - - exit (status); - } -@@ -124,9 +125,12 @@ main(int argc, char **argv) { - progname = program; - - keyname = DEFAULT_KEYNAME; -- alg = DST_ALG_HMACMD5; - serveraddr = DEFAULT_SERVER; - port = DEFAULT_PORT; -+ alg = DST_ALG_HMACSHA256; -+ if (isc_md5_available()) -+ alg = DST_ALG_HMACMD5; -+ algdef = alg_totext(alg); - - isc_commandline_errprint = ISC_FALSE; - -diff --git a/bin/confgen/rndc-confgen.docbook b/bin/confgen/rndc-confgen.docbook -index f367b94aae..add8d7357f 100644 ---- a/bin/confgen/rndc-confgen.docbook -+++ b/bin/confgen/rndc-confgen.docbook -@@ -136,7 +136,8 @@ - - Specifies the algorithm to use for the TSIG key. Available - choices are: hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, -- hmac-sha384 and hmac-sha512. The default is hmac-md5. -+ hmac-sha384 and hmac-sha512. The default is hmac-md5 or -+ if MD5 was disabled hmac-sha256. - - - -diff --git a/bin/dig/dig.c b/bin/dig/dig.c -index 634ccfbfbf..4db0e6430f 100644 ---- a/bin/dig/dig.c -+++ b/bin/dig/dig.c -@@ -25,6 +25,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -1426,7 +1427,9 @@ dash_option(char *option, char *next, dig_lookup_t **lookup, - ptr = ptr2; - ptr2 = ptr3; - } else { -- hmacname = DNS_TSIG_HMACMD5_NAME; -+ hmacname = DNS_TSIG_HMACSHA256_NAME; -+ if (isc_md5_available()) -+ hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = 0; - } - strncpy(keynametext, ptr, sizeof(keynametext)); -diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook -index 028f0fcd73..6ee5bd90bc 100644 ---- a/bin/dig/dig.docbook -+++ b/bin/dig/dig.docbook -@@ -309,9 +309,11 @@ - responses using transaction signatures (TSIG), specify a TSIG key file - using the option. You can also specify the TSIG - key itself on the command line using the option; -- hmac is the type of the TSIG, default HMAC-MD5, -+ hmac is the type of the TSIG, - name is the name of the TSIG key and -- key is the actual key. The key is a -+ key is the actual key. If hmac -+ is not specified, the default is hmac-md5 -+ or if MD5 was disabled hmac-sha256. The key is a - base-64 - encoded string, typically generated by - -diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c -index 3a066c68c9..3998a81a5d 100644 ---- a/bin/dig/dighost.c -+++ b/bin/dig/dighost.c -@@ -81,6 +81,7 @@ - #include - #include - #include -+#include - #include - #ifdef DIG_SIGCHASE - #include -@@ -1025,9 +1026,10 @@ parse_hmac(const char *hmac) { - - digestbits = 0; - -- if (strcasecmp(buf, "hmac-md5") == 0) { -+ if (strcasecmp(buf, "hmac-md5") == 0 && isc_md5_available()) { - hmacname = DNS_TSIG_HMACMD5_NAME; -- } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { -+ } else if (strncasecmp(buf, "hmac-md5-", 9) == 0 && -+ isc_md5_available()) { - hmacname = DNS_TSIG_HMACMD5_NAME; - digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128); - } else if (strcasecmp(buf, "hmac-sha1") == 0) { -@@ -1145,7 +1147,13 @@ setup_file_key(void) { - - switch (dst_key_alg(dstkey)) { - case DST_ALG_HMACMD5: -- hmacname = DNS_TSIG_HMACMD5_NAME; -+ if (isc_md5_available()) { -+ hmacname = DNS_TSIG_HMACMD5_NAME; -+ } else { -+ printf(";; Couldn't create key %s: bad algorithm\n", -+ keynametext); -+ goto failure; -+ } - break; - case DST_ALG_HMACSHA1: - hmacname = DNS_TSIG_HMACSHA1_NAME; -diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c -index cc212e1ed1..a5854a1f4c 100644 ---- a/bin/dnssec/dnssec-keyfromlabel.c -+++ b/bin/dnssec/dnssec-keyfromlabel.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -379,6 +380,11 @@ main(int argc, char **argv) { - if (freeit != NULL) - free(freeit); - return (1); -+ } else if (strcasecmp(algname, "RSAMD5") == 0 && isc_md5_available() == ISC_FALSE) { -+ fprintf(stderr, "The use of RSAMD5 was disabled\n"); -+ if (freeit != NULL) -+ free(freeit); -+ return (1); - } else { - r.base = algname; - r.length = strlen(algname); -@@ -412,6 +418,9 @@ main(int argc, char **argv) { - fatal("invalid type %s", type); - } - -+ if (alg == DST_ALG_RSAMD5 && isc_md5_available() == ISC_FALSE) -+ fatal("Key uses disabled RSAMD5"); -+ - if (nametype == NULL) { - if ((options & DST_TYPE_KEY) != 0) /* KEY */ - fatal("no nametype specified"); -diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c -index 97b96ee1dc..c147bb4e6c 100644 ---- a/bin/dnssec/dnssec-keygen.c -+++ b/bin/dnssec/dnssec-keygen.c -@@ -42,6 +42,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -548,9 +549,21 @@ main(int argc, char **argv) { - "\"-a RSAMD5\"\n"); - INSIST(freeit == NULL); - return (1); -- } else if (strcasecmp(algname, "HMAC-MD5") == 0) -- alg = DST_ALG_HMACMD5; -- else if (strcasecmp(algname, "HMAC-SHA1") == 0) -+ } else if (strcasecmp(algname, "HMAC-MD5") == 0) { -+ if (isc_md5_available()) { -+ alg = DST_ALG_HMACMD5; -+ } else { -+ fprintf(stderr, -+ "The use of HMAC-MD5 was disabled\n"); -+ INSIST(freeit == NULL); -+ return (1); -+ } -+ } else if (strcasecmp(algname, "RSAMD5") == 0 && -+ isc_md5_available() == ISC_FALSE) { -+ fprintf(stderr, "The use of RSAMD5 was disabled\n"); -+ INSIST(freeit == NULL); -+ return (1); -+ } else if (strcasecmp(algname, "HMAC-SHA1") == 0) - alg = DST_ALG_HMACSHA1; - else if (strcasecmp(algname, "HMAC-SHA224") == 0) - alg = DST_ALG_HMACSHA224; -diff --git a/bin/named/config.c b/bin/named/config.c -index 818ed3797a..22d8a85405 100644 ---- a/bin/named/config.c -+++ b/bin/named/config.c -@@ -25,6 +25,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -828,6 +829,19 @@ ns_config_getkeyalgorithm(const char *str, dns_name_t **name, - return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits)); - } - -+static inline int -+algorithms_start() { -+ if (isc_md5_available() == ISC_FALSE) { -+ int i = 0; -+ while (algorithms[i].str != NULL && -+ algorithms[i].hmac == hmacmd5) { -+ i++; -+ } -+ return i; -+ } -+ return 0; -+} -+ - isc_result_t - ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, - unsigned int *typep, isc_uint16_t *digestbits) -@@ -837,7 +851,7 @@ ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, - isc_uint16_t bits; - isc_result_t result; - -- for (i = 0; algorithms[i].str != NULL; i++) { -+ for (i = algorithms_start(); algorithms[i].str != NULL; i++) { - len = strlen(algorithms[i].str); - if (strncasecmp(algorithms[i].str, str, len) == 0 && - (str[len] == '\0' || -@@ -859,7 +873,12 @@ ns_config_getkeyalgorithm2(const char *str, dns_name_t **name, - - if (name != NULL) { - switch (algorithms[i].hmac) { -- case hmacmd5: *name = dns_tsig_hmacmd5_name; break; -+ case hmacmd5: -+ if (isc_md5_available()) { -+ *name = dns_tsig_hmacmd5_name; break; -+ } else { -+ return (ISC_R_NOTFOUND); -+ } - case hmacsha1: *name = dns_tsig_hmacsha1_name; break; - case hmacsha224: *name = dns_tsig_hmacsha224_name; break; - case hmacsha256: *name = dns_tsig_hmacsha256_name; break; -diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c -index 644e3d9fc0..336597a95d 100644 ---- a/bin/nsupdate/nsupdate.c -+++ b/bin/nsupdate/nsupdate.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -440,9 +441,10 @@ parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) { - strncpy(buf, hmacstr, len); - buf[len] = 0; - -- if (strcasecmp(buf, "hmac-md5") == 0) { -+ if (strcasecmp(buf, "hmac-md5") == 0 && isc_md5_available()) { - *hmac = DNS_TSIG_HMACMD5_NAME; -- } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) { -+ } else if (strncasecmp(buf, "hmac-md5-", 9) == 0 && -+ isc_md5_available()) { - *hmac = DNS_TSIG_HMACMD5_NAME; - result = isc_parse_uint16(&digestbits, &buf[9], 10); - if (result != ISC_R_SUCCESS || digestbits > 128) -@@ -538,7 +540,9 @@ setup_keystr(void) { - secretstr = n + 1; - digestbits = parse_hmac(&hmacname, keystr, s - keystr); - } else { -- hmacname = DNS_TSIG_HMACMD5_NAME; -+ hmacname = DNS_TSIG_HMACSHA256_NAME; -+ if (isc_md5_available()) -+ hmacname = DNS_TSIG_HMACMD5_NAME; - name = keystr; - n = s; - } -@@ -670,7 +674,8 @@ setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) { - - switch (dst_key_alg(dstkey)) { - case DST_ALG_HMACMD5: -- hmacname = DNS_TSIG_HMACMD5_NAME; -+ if (isc_md5_available()) -+ hmacname = DNS_TSIG_HMACMD5_NAME; - break; - case DST_ALG_HMACSHA1: - hmacname = DNS_TSIG_HMACSHA1_NAME; -@@ -1462,8 +1467,11 @@ evaluate_key(char *cmdline) { - if (n != NULL) { - digestbits = parse_hmac(&hmacname, namestr, n - namestr); - namestr = n + 1; -- } else -- hmacname = DNS_TSIG_HMACMD5_NAME; -+ } else { -+ hmacname = DNS_TSIG_HMACSHA256_NAME; -+ if (isc_md5_available()) -+ hmacname = DNS_TSIG_HMACMD5_NAME; -+ } - - isc_buffer_init(&b, namestr, strlen(namestr)); - isc_buffer_add(&b, strlen(namestr)); -diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook -index bbcc68110f..7d8e78f894 100644 ---- a/bin/nsupdate/nsupdate.docbook -+++ b/bin/nsupdate/nsupdate.docbook -@@ -158,6 +158,9 @@ - hmac:keyname:secret. - keyname is the name of the key, and - secret is the base64 encoded shared secret. -+ If hmac is not specified, -+ the default is hmac-md5 -+ or if MD5 was disabled hmac-sha256. - Use of the option is discouraged because the - shared secret is supplied as a command line argument in clear text. - This may be visible in the output from -@@ -371,13 +374,17 @@ - - - key -- name -+ hmac:name - secret - - - - Specifies that all updates are to be TSIG-signed using the - keyname keysecret pair. -+ If hmac is specified, then it sets the -+ signing algorithm in use; the default is -+ hmac-md5 or if MD5 was disabled -+ hmac-sha256. - The key command - overrides any key specified on the command line via - or . -diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c -index 81e629f15c..0fd192d3a5 100644 ---- a/bin/rndc/rndc.c -+++ b/bin/rndc/rndc.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -607,7 +608,7 @@ parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, - secretstr = cfg_obj_asstring(secretobj); - algorithmstr = cfg_obj_asstring(algorithmobj); - -- if (strcasecmp(algorithmstr, "hmac-md5") == 0) -+ if (strcasecmp(algorithmstr, "hmac-md5") == 0 && isc_md5_available()) - algorithm = ISCCC_ALG_HMACMD5; - else if (strcasecmp(algorithmstr, "hmac-sha1") == 0) - algorithm = ISCCC_ALG_HMACSHA1; -diff --git a/bin/tests/hashes/t_hashes.c b/bin/tests/hashes/t_hashes.c -index 47d08c572d..965271ad67 100644 ---- a/bin/tests/hashes/t_hashes.c -+++ b/bin/tests/hashes/t_hashes.c -@@ -353,8 +353,10 @@ t_hashes(IN *in, OUT *out_sha1, OUT *out_sha224, OUT *out_md5) - t_hash("SHA1", (HASH_INIT)isc_sha1_init, (UPDATE)isc_sha1_update, - (FINAL)isc_sha1_final, in, out_sha1); - t_sha224(in, out_sha224); -- t_hash("md5", (HASH_INIT)isc_md5_init, (UPDATE)isc_md5_update, -- (FINAL)isc_md5_final, in, out_md5); -+ if (isc_md5_available()) { -+ t_hash("md5", (HASH_INIT)isc_md5_init, (UPDATE)isc_md5_update, -+ (FINAL)isc_md5_final, in, out_md5); -+ } - } - - -@@ -435,12 +437,14 @@ t1(void) - t_hashes(&abc, &abc_sha1, &abc_sha224, &abc_md5); - t_hashes(&abc_blah, &abc_blah_sha1, &abc_blah_sha224, &abc_blah_md5); - -- /* -- * three HMAC-md5 examples from RFC 2104 -- */ -- t_md5hmac(&rfc2104_1, &rfc2104_1_hmac); -- t_md5hmac(&rfc2104_2, &rfc2104_2_hmac); -- t_md5hmac(&rfc2104_3, &rfc2104_3_hmac); -+ if (isc_md5_available()) { -+ /* -+ * three HMAC-md5 examples from RFC 2104 -+ */ -+ t_md5hmac(&rfc2104_1, &rfc2104_1_hmac); -+ t_md5hmac(&rfc2104_2, &rfc2104_2_hmac); -+ t_md5hmac(&rfc2104_3, &rfc2104_3_hmac); -+ } - - /* - * four HMAC-SHA tests from RFC 4634 starting on page 86 -diff --git a/lib/bind9/check.c b/lib/bind9/check.c -index 5131b521f4..00c4b3e509 100644 ---- a/lib/bind9/check.c -+++ b/lib/bind9/check.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1895,6 +1896,13 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) { - } - - algorithm = cfg_obj_asstring(algobj); -+ /* Skip hmac-md5* algorithms */ -+ if (isc_md5_available() == ISC_FALSE && -+ strncasecmp(algorithm, "hmac-md5", 8) == 0) { -+ cfg_obj_log(algobj, logctx, ISC_LOG_ERROR, -+ "disabled algorithm '%s'", algorithm); -+ return (ISC_R_DISABLED); -+ } - for (i = 0; algorithms[i].name != NULL; i++) { - len = strlen(algorithms[i].name); - if (strncasecmp(algorithms[i].name, algorithm, len) == 0 && -diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c -index e71f2026e5..e6375cf406 100644 ---- a/lib/dns/dst_api.c -+++ b/lib/dns/dst_api.c -@@ -202,6 +202,12 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, - dst_result_register(); - - memset(dst_t_func, 0, sizeof(dst_t_func)); -+ -+#ifdef OPENSSL -+ RETERR(dst__openssl_init(engine)); -+#elif PKCS11CRYPTO -+ RETERR(dst__pkcs11_init(mctx, engine)); -+#endif - RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5])); - RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1])); - RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224])); -@@ -209,7 +215,6 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, - RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384])); - RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512])); - #ifdef OPENSSL -- RETERR(dst__openssl_init(engine)); - RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5], - DST_ALG_RSAMD5)); - RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1], -@@ -233,12 +238,16 @@ dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, - RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); - #endif - #elif PKCS11CRYPTO -- RETERR(dst__pkcs11_init(mctx, engine)); -- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5])); -- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1])); -- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1])); -- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256])); -- RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512])); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5], -+ DST_ALG_RSAMD5)); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1], -+ DST_ALG_RSASHA1)); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1], -+ DST_ALG_NSEC3RSASHA1)); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256], -+ DST_ALG_RSASHA256)); -+ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512], -+ DST_ALG_RSASHA512)); - RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_DSA])); - RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); - RETERR(dst__pkcs11dh_init(&dst_t_func[DST_ALG_DH])); -diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h -index b15135e634..66d322a278 100644 ---- a/lib/dns/dst_internal.h -+++ b/lib/dns/dst_internal.h -@@ -232,7 +232,8 @@ isc_result_t dst__hmacsha384_init(struct dst_func **funcp); - isc_result_t dst__hmacsha512_init(struct dst_func **funcp); - isc_result_t dst__opensslrsa_init(struct dst_func **funcp, - unsigned char algorithm); --isc_result_t dst__pkcs11rsa_init(struct dst_func **funcp); -+isc_result_t dst__pkcs11rsa_init(struct dst_func **funcp, -+ unsigned char algorithm); - isc_result_t dst__openssldsa_init(struct dst_func **funcp); - isc_result_t dst__pkcs11dsa_init(struct dst_func **funcp); - isc_result_t dst__openssldh_init(struct dst_func **funcp); -diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c -index ec622d9603..0e889cc740 100644 ---- a/lib/dns/dst_parse.c -+++ b/lib/dns/dst_parse.c -@@ -40,6 +40,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -353,6 +354,10 @@ check_data(const dst_private_t *priv, const unsigned int alg, - /* XXXVIX this switch statement is too sparse to gen a jump table. */ - switch (alg) { - case DST_ALG_RSAMD5: -+ if (isc_md5_available()) -+ return (check_rsa(priv, external)); -+ else -+ return (DST_R_UNSUPPORTEDALG); - case DST_ALG_RSASHA1: - case DST_ALG_NSEC3RSASHA1: - case DST_ALG_RSASHA256: -@@ -369,7 +374,10 @@ check_data(const dst_private_t *priv, const unsigned int alg, - case DST_ALG_ECDSA384: - return (check_ecdsa(priv, external)); - case DST_ALG_HMACMD5: -- return (check_hmac_md5(priv, old)); -+ if (isc_md5_available()) -+ return (check_hmac_md5(priv, old)); -+ else -+ return (DST_R_UNSUPPORTEDALG); - case DST_ALG_HMACSHA1: - return (check_hmac_sha(priv, HMACSHA1_NTAGS, alg)); - case DST_ALG_HMACSHA224: -@@ -587,6 +595,8 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, - goto fail; - } - -+ if (isc_md5_available() == ISC_FALSE && alg == DST_ALG_RSA) -+ alg = DST_ALG_RSASHA1; - check = check_data(priv, alg, ISC_TRUE, external); - if (check < 0) { - ret = DST_R_INVALIDPRIVATEKEY; -diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c -index 3ac01a8c20..6b6801af1c 100644 ---- a/lib/dns/hmac_link.c -+++ b/lib/dns/hmac_link.c -@@ -340,7 +340,7 @@ static dst_func_t hmacmd5_functions = { - isc_result_t - dst__hmacmd5_init(dst_func_t **funcp) { - REQUIRE(funcp != NULL); -- if (*funcp == NULL) -+ if (*funcp == NULL && isc_md5_available()) - *funcp = &hmacmd5_functions; - return (ISC_R_SUCCESS); - } -diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c -index 53c6d4bdd9..08291af016 100644 ---- a/lib/dns/opensslrsa_link.c -+++ b/lib/dns/opensslrsa_link.c -@@ -1484,6 +1484,10 @@ dst__opensslrsa_init(dst_func_t **funcp, unsigned char algorithm) { - - if (*funcp == NULL) { - switch (algorithm) { -+ case DST_ALG_RSAMD5: -+ if (isc_md5_available()) -+ *funcp = &opensslrsa_functions; -+ break; - case DST_ALG_RSASHA256: - #if defined(HAVE_EVP_SHA256) || !USE_EVP - *funcp = &opensslrsa_functions; -diff --git a/lib/dns/pkcs11rsa_link.c b/lib/dns/pkcs11rsa_link.c -index 010d4b64fc..6b556bcd11 100644 ---- a/lib/dns/pkcs11rsa_link.c -+++ b/lib/dns/pkcs11rsa_link.c -@@ -89,6 +89,9 @@ pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { - key->key_alg == DST_ALG_RSASHA256 || - key->key_alg == DST_ALG_RSASHA512); - -+ if (key->key_alg == DST_ALG_RSAMD5 && isc_md5_available() == ISC_FALSE) -+ return (ISC_R_FAILURE); -+ - rsa = key->keydata.pkey; - - pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -@@ -216,6 +219,8 @@ pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { - - switch (dctx->key->key_alg) { - case DST_ALG_RSAMD5: -+ if (isc_md5_available() == ISC_FALSE) -+ return (ISC_R_FAILURE); - mech.mechanism = CKM_MD5_RSA_PKCS; - break; - case DST_ALG_RSASHA1: -@@ -297,6 +302,9 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits, - key->key_alg == DST_ALG_RSASHA256 || - key->key_alg == DST_ALG_RSASHA512); - -+ if (key->key_alg == DST_ALG_RSAMD5 && isc_md5_available() == ISC_FALSE) -+ return (ISC_R_FAILURE); -+ - rsa = key->keydata.pkey; - - pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, -@@ -350,6 +358,8 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits, - - switch (dctx->key->key_alg) { - case DST_ALG_RSAMD5: -+ if (isc_md5_available() == ISC_FALSE) -+ return (ISC_R_FAILURE); - mech.mechanism = CKM_MD5_RSA_PKCS; - break; - case DST_ALG_RSASHA1: -@@ -1565,11 +1575,20 @@ static dst_func_t pkcs11rsa_functions = { - }; - - isc_result_t --dst__pkcs11rsa_init(dst_func_t **funcp) { -+dst__pkcs11rsa_init(dst_func_t **funcp, unsigned char algorithm) { - REQUIRE(funcp != NULL); - -- if (*funcp == NULL) -- *funcp = &pkcs11rsa_functions; -+ if (*funcp == NULL) { -+ switch (algorithm) { -+ case DST_ALG_RSAMD5: -+ if (isc_md5_available()) -+ *funcp = &pkcs11rsa_functions; -+ break; -+ default: -+ *funcp = &pkcs11rsa_functions; -+ break; -+ } -+ } - return (ISC_R_SUCCESS); - } - -diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c -index 091b3c70fb..c1251225d5 100644 ---- a/lib/dns/rcode.c -+++ b/lib/dns/rcode.c -@@ -21,6 +21,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -310,17 +311,31 @@ dns_cert_totext(dns_cert_t cert, isc_buffer_t *target) { - return (dns_mnemonic_totext(cert, target, certs)); - } - -+static inline struct tbl * -+secalgs_tbl_start() { -+ struct tbl *algs = secalgs; -+ -+ if (isc_md5_available() == ISC_FALSE) { -+ while (algs->name != NULL && -+ algs->value == DNS_KEYALG_RSAMD5) -+ ++algs; -+ } -+ return algs; -+} -+ - isc_result_t - dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) { - unsigned int value; -- RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff)); -+ -+ RETERR(dns_mnemonic_fromtext(&value, source, -+ secalgs_tbl_start(), 0xff)); - *secalgp = value; - return (ISC_R_SUCCESS); - } - - isc_result_t - dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) { -- return (dns_mnemonic_totext(secalg, target, secalgs)); -+ return (dns_mnemonic_totext(secalg, target, secalgs_tbl_start())); - } - - void -diff --git a/lib/dns/tests/tsig_test.c b/lib/dns/tests/tsig_test.c -index 956e4a0469..c4b2f84837 100644 ---- a/lib/dns/tests/tsig_test.c -+++ b/lib/dns/tests/tsig_test.c -@@ -10,6 +10,7 @@ - - #include - #include -+#include - #include - - #include -diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c -index 7343b4c26f..59a78c8dca 100644 ---- a/lib/dns/tkey.c -+++ b/lib/dns/tkey.c -@@ -230,6 +230,9 @@ compute_secret(isc_buffer_t *shared, isc_region_t *queryrandomness, - unsigned char digests[32]; - unsigned int i; - -+ if (isc_md5_available() == ISC_FALSE) -+ return (ISC_R_NOTIMPLEMENTED); -+ - isc_buffer_usedregion(shared, &r); - - /* -@@ -298,6 +301,12 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, - return (DNS_R_REFUSED); - } - -+ if (isc_md5_available() == ISC_FALSE) { -+ tkey_log("process_dhtkey: MD5 was disabled"); -+ tkeyout->error = dns_tsigerror_badalg; -+ return (ISC_R_SUCCESS); -+ } -+ - if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) { - tkey_log("process_dhtkey: algorithms other than " - "hmac-md5 are not supported"); -diff --git a/lib/dns/tsec.c b/lib/dns/tsec.c -index bfa6195d0d..fad645668c 100644 ---- a/lib/dns/tsec.c -+++ b/lib/dns/tsec.c -@@ -18,6 +18,7 @@ - - #include - -+#include - #include - - #include -@@ -66,7 +67,12 @@ dns_tsec_create(isc_mem_t *mctx, dns_tsectype_t type, dst_key_t *key, - case dns_tsectype_tsig: - switch (dst_key_alg(key)) { - case DST_ALG_HMACMD5: -- algname = dns_tsig_hmacmd5_name; -+ if (isc_md5_available()) { -+ algname = dns_tsig_hmacmd5_name; -+ } else { -+ isc_mem_put(mctx, tsec, sizeof(*tsec)); -+ return (DNS_R_BADALG); -+ } - break; - case DST_ALG_HMACSHA1: - algname = dns_tsig_hmacsha1_name; -diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c -index 325c901f93..804ef821f0 100644 ---- a/lib/dns/tsig.c -+++ b/lib/dns/tsig.c -@@ -24,6 +24,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -316,7 +317,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, - goto cleanup_key; - (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); - -- if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { -+ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && isc_md5_available()) { - tkey->algorithm = DNS_TSIG_HMACMD5_NAME; - if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) { - ret = DNS_R_BADALG; -@@ -539,7 +540,7 @@ destroyring(dns_tsig_keyring_t *ring) { - - static unsigned int - dst_alg_fromname(dns_name_t *algorithm) { -- if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { -+ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && isc_md5_available()) { - return (DST_ALG_HMACMD5); - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { - return (DST_ALG_HMACSHA1); -@@ -724,7 +725,7 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, - if (length > 0) - REQUIRE(secret != NULL); - -- if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { -+ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME) && isc_md5_available()) { - if (secret != NULL) { - isc_buffer_t b; - -@@ -1322,7 +1323,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - ret = dst_key_sigsize(key, &siglen); - if (ret != ISC_R_SUCCESS) - return (ret); -- if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || -+ if ((alg == DST_ALG_HMACMD5 && isc_md5_available()) || -+ alg == DST_ALG_HMACSHA1 || - alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || - alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) - { -@@ -1484,9 +1486,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - } - - if ( --#ifndef PK11_MD5_DISABLE -- alg == DST_ALG_HMACMD5 || --#endif -+ (alg == DST_ALG_HMACMD5 && isc_md5_available()) || - alg == DST_ALG_HMACSHA1 || - alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || - alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) -@@ -1626,9 +1626,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - if (ret != ISC_R_SUCCESS) - goto cleanup_querystruct; - if ( --#ifndef PK11_MD5_DISABLE -- alg == DST_ALG_HMACMD5 || --#endif -+ (alg == DST_ALG_HMACMD5 && isc_md5_available()) || - alg == DST_ALG_HMACSHA1 || - alg == DST_ALG_HMACSHA224 || - alg == DST_ALG_HMACSHA256 || -@@ -1801,9 +1799,7 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - if ( --#ifndef PK11_MD5_DISABLE -- alg == DST_ALG_HMACMD5 || --#endif -+ (alg == DST_ALG_HMACMD5 && isc_md5_available()) || - alg == DST_ALG_HMACSHA1 || - alg == DST_ALG_HMACSHA224 || - alg == DST_ALG_HMACSHA256 || -diff --git a/lib/isc/include/isc/md5.h b/lib/isc/include/isc/md5.h -index a2e00b382a..d4c2b8ab48 100644 ---- a/lib/isc/include/isc/md5.h -+++ b/lib/isc/include/isc/md5.h -@@ -83,6 +83,9 @@ isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len); - void - isc_md5_final(isc_md5_t *ctx, unsigned char *digest); - -+isc_boolean_t -+isc_md5_available(void); -+ - ISC_LANG_ENDDECLS - - #endif /* ISC_MD5_H */ -diff --git a/lib/isc/md5.c b/lib/isc/md5.c -index 2e3cf9a4a3..a5113df4b8 100644 ---- a/lib/isc/md5.c -+++ b/lib/isc/md5.c -@@ -38,6 +38,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -51,6 +52,9 @@ - - #ifdef ISC_PLATFORM_OPENSSLHASH - -+static isc_once_t available_once = ISC_ONCE_INIT; -+static isc_boolean_t available = ISC_FALSE; -+ - void - isc_md5_init(isc_md5_t *ctx) { - EVP_DigestInit(ctx, EVP_md5()); -@@ -71,8 +75,33 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { - EVP_DigestFinal(ctx, digest, NULL); - } - -+static void -+do_detect_available() { -+ isc_md5_t local; -+ isc_md5_t *ctx = &local; -+ unsigned char digest[ISC_MD5_DIGESTLENGTH]; -+ -+ ctx->ctx = EVP_MD_CTX_new(); -+ RUNTIME_CHECK(ctx->ctx != NULL); -+ available = ISC_TF(EVP_DigestInit(ctx->ctx, EVP_md5()) == 1); -+ if (available) -+ (void)EVP_DigestFinal(ctx->ctx, digest, NULL); -+ EVP_MD_CTX_free(ctx->ctx); -+ ctx->ctx = NULL; -+} -+ -+isc_boolean_t -+isc_md5_available() { -+ RUNTIME_CHECK(isc_once_do(&available_once, do_detect_available) -+ == ISC_R_SUCCESS); -+ return available; -+} -+ - #elif PKCS11CRYPTO - -+static isc_once_t available_once = ISC_ONCE_INIT; -+static isc_boolean_t available = ISC_FALSE; -+ - void - isc_md5_init(isc_md5_t *ctx) { - CK_RV rv; -@@ -115,6 +144,31 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { - pk11_return_session(ctx); - } - -+static void -+do_detect_available() { -+ isc_md5_t local; -+ isc_md5_t *ctx = &local; -+ CK_RV rv; -+ CK_MECHANISM mech = { CKM_MD5, NULL, 0 }; -+ -+ if (pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE, -+ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS) -+ { -+ rv = pkcs_C_DigestInit(ctx->session, &mech); -+ isc_md5_invalidate(ctx); -+ available = (ISC_TF(rv == CKR_OK)); -+ } else { -+ available = ISC_FALSE; -+ } -+} -+ -+isc_boolean_t -+isc_md5_available() { -+ RUNTIME_CHECK(isc_once_do(&available_once, do_detect_available) -+ == ISC_R_SUCCESS); -+ return available; -+} -+ - #else - - static void -@@ -324,4 +378,9 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) { - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(isc_md5_t)); /* In case it's sensitive */ - } -+ -+isc_boolean_t -+isc_md5_available() { -+ return ISC_TRUE; -+} - #endif -diff --git a/lib/isc/pk11.c b/lib/isc/pk11.c -index de4479b7b0..6cce70f0cf 100644 ---- a/lib/isc/pk11.c -+++ b/lib/isc/pk11.c -@@ -139,6 +139,8 @@ - #define PK11_NO_LOGERR 1 - #endif - -+LIBISC_EXTERNAL_DATA isc_boolean_t pk11_verbose_init = ISC_FALSE; -+ - static isc_once_t once = ISC_ONCE_INIT; - static isc_mem_t *pk11_mctx = NULL; - static isc_int32_t allocsize = 0; -@@ -283,13 +285,12 @@ pk11_initialize(isc_mem_t *mctx, const char *engine) { - LOCK(&alloclock); - if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0)) - isc_mem_attach(mctx, &pk11_mctx); -+ UNLOCK(&alloclock); -+ -+ LOCK(&sessionlock); - if (initialized) { -- UNLOCK(&alloclock); -- return (ISC_R_SUCCESS); -- } else { -- LOCK(&sessionlock); -- initialized = ISC_TRUE; -- UNLOCK(&alloclock); -+ result = ISC_R_SUCCESS; -+ goto unlock; - } - - ISC_LIST_INIT(tokens); -@@ -327,6 +328,7 @@ pk11_initialize(isc_mem_t *mctx, const char *engine) { - } - #endif - #endif /* PKCS11CRYPTO */ -+ initialized = ISC_TRUE; - result = ISC_R_SUCCESS; - unlock: - UNLOCK(&sessionlock); -@@ -363,9 +365,14 @@ pk11_finalize(void) { - pk11_mem_put(token, sizeof(*token)); - token = next; - } -+ LOCK(&alloclock); - if (pk11_mctx != NULL) - isc_mem_detach(&pk11_mctx); -+ UNLOCK(&alloclock); -+ -+ LOCK(&sessionlock); - initialized = ISC_FALSE; -+ UNLOCK(&sessionlock); - return (ret); - } - -@@ -655,6 +662,15 @@ token_login(pk11_session_t *sp) { - return (ret); - } - -+#define PK11_TRACE(fmt) \ -+ if (pk11_verbose_init) fprintf(stderr, fmt) -+#define PK11_TRACE1(fmt, arg) \ -+ if (pk11_verbose_init) fprintf(stderr, fmt, arg) -+#define PK11_TRACE2(fmt, arg1, arg2) \ -+ if (pk11_verbose_init) fprintf(stderr, fmt, arg1, arg2) -+#define PK11_TRACEM(mech) \ -+ if (pk11_verbose_init) fprintf(stderr, #mech ": 0x%lx\n", rv) -+ - static void - choose_slots(void) { - CK_MECHANISM_INFO mechInfo; -@@ -665,6 +681,8 @@ choose_slots(void) { - CK_ULONG slotCount; - pk11_token_t *token; - unsigned int i; -+ unsigned int best_rsa_algorithms = 0; -+ unsigned int best_digest_algorithms = 0; - - slotCount = 0; - PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount)); -@@ -676,6 +694,8 @@ choose_slots(void) { - PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount)); - - for (i = 0; i < slotCount; i++) { -+ unsigned int rsa_algorithms = 0; -+ unsigned int digest_algorithms = 0; - slot = slotList[i]; - - rv = pkcs_C_GetTokenInfo(slot, &tokenInfo); -@@ -708,8 +728,11 @@ choose_slots(void) { - &mechInfo); - if ((rv != CKR_OK) || - ((mechInfo.flags & CKF_SIGN) == 0) || -- ((mechInfo.flags & CKF_VERIFY) == 0)) -- goto try_dsa; -+ ((mechInfo.flags & CKF_VERIFY) == 0)) { -+ PK11_TRACEM(CKM_MD5_RSA_PKCS); -+ } -+ else -+ ++rsa_algorithms; - rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS, - &mechInfo); - if ((rv != CKR_OK) || -@@ -729,8 +752,14 @@ choose_slots(void) { - ((mechInfo.flags & CKF_VERIFY) == 0)) - goto try_dsa; - token->operations |= 1 << OP_RSA; -- if (best_rsa_token == NULL) -+ if (best_rsa_token == NULL) { - best_rsa_token = token; -+ best_rsa_algorithms = rsa_algorithms; -+ } else if (rsa_algorithms > best_rsa_algorithms) { -+ pk11_mem_put(best_rsa_token, sizeof(*best_rsa_token)); -+ best_rsa_token = token; -+ best_rsa_algorithms = rsa_algorithms; -+ } - - try_dsa: - rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_PARAMETER_GEN, -@@ -773,8 +802,11 @@ choose_slots(void) { - - try_digest: - rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5, &mechInfo); -- if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) -- continue; -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) { -+ PK11_TRACEM(CKM_MD5); -+ } -+ else -+ ++digest_algorithms; - rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1, &mechInfo); - if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0)) - continue; -@@ -792,13 +824,15 @@ choose_slots(void) { - continue; - #ifdef PKCS11CRYPTOWITHHMAC - rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_HMAC, &mechInfo); -- if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) -- continue; -+ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) { -+ PK11_TRACEM(CKM_MD5_HMAC); -+ } -+ else -+ ++digest_algorithms; - #endif - rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1_HMAC, &mechInfo); - if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) - continue; -- rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224_HMAC, &mechInfo); - if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) - continue; - rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_HMAC, &mechInfo); -@@ -811,8 +845,14 @@ choose_slots(void) { - if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0)) - continue; - token->operations |= 1 << OP_DIGEST; -- if (digest_token == NULL) -- digest_token = token; -+ if (digest_token == NULL) { -+ digest_token = token; -+ best_digest_algorithms = digest_algorithms; -+ } else if (digest_algorithms > best_digest_algorithms) { -+ pk11_mem_put(digest_token, sizeof(*digest_token)); -+ digest_token = token; -+ best_digest_algorithms = digest_algorithms; -+ } - - /* ECDSA requires digest */ - rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_KEY_PAIR_GEN, -diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c -index 9428374cc1..ca3cff27c9 100644 ---- a/lib/isccc/cc.c -+++ b/lib/isccc/cc.c -@@ -254,11 +254,15 @@ sign(unsigned char *data, unsigned int length, unsigned char *hmac, - - switch (algorithm) { - case ISCCC_ALG_HMACMD5: -- isc_hmacmd5_init(&ctx.hmd5, secret->rstart, -- REGION_SIZE(*secret)); -- isc_hmacmd5_update(&ctx.hmd5, data, length); -- isc_hmacmd5_sign(&ctx.hmd5, digest); -- source.rend = digest + ISC_MD5_DIGESTLENGTH; -+ if (isc_md5_available()) { -+ isc_hmacmd5_init(&ctx.hmd5, secret->rstart, -+ REGION_SIZE(*secret)); -+ isc_hmacmd5_update(&ctx.hmd5, data, length); -+ isc_hmacmd5_sign(&ctx.hmd5, digest); -+ source.rend = digest + ISC_MD5_DIGESTLENGTH; -+ } else { -+ return (ISC_R_FAILURE); -+ } - break; - - case ISCCC_ALG_HMACSHA1: -@@ -329,14 +333,14 @@ isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target, - { - unsigned char *hmac_rstart, *signed_rstart; - isc_result_t result; -+ const isc_boolean_t md5 = ISC_TF(algorithm == ISCCC_ALG_HMACMD5); - -- if (algorithm == ISCCC_ALG_HMACMD5) { -- if (REGION_SIZE(*target) < 4 + sizeof(auth_hmd5)) -- return (ISC_R_NOSPACE); -- } else { -- if (REGION_SIZE(*target) < 4 + sizeof(auth_hsha)) -- return (ISC_R_NOSPACE); -- } -+ if (md5 && isc_md5_available() == ISC_FALSE) -+ return (ISC_R_NOTIMPLEMENTED); -+ if (REGION_SIZE(*target) < 4 + ((md5) ? -+ sizeof(auth_hmd5) : -+ sizeof(auth_hsha))) -+ return (ISC_R_NOSPACE); - - /* - * Emit protocol version. -@@ -348,7 +352,7 @@ isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target, - * We'll replace the zeros with the real signature once - * we know what it is. - */ -- if (algorithm == ISCCC_ALG_HMACMD5) { -+ if (md5) { - hmac_rstart = target->rstart + HMD5_OFFSET; - PUT_MEM(auth_hmd5, sizeof(auth_hmd5), target->rstart); - } else { -@@ -404,7 +408,7 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, - _auth = isccc_alist_lookup(alist, "_auth"); - if (!isccc_alist_alistp(_auth)) - return (ISC_R_FAILURE); -- if (algorithm == ISCCC_ALG_HMACMD5) -+ if (algorithm == ISCCC_ALG_HMACMD5 && isc_md5_available()) - hmac = isccc_alist_lookup(_auth, "hmd5"); - else - hmac = isccc_alist_lookup(_auth, "hsha"); -@@ -417,12 +421,16 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, - target.rstart = digestb64; - switch (algorithm) { - case ISCCC_ALG_HMACMD5: -- isc_hmacmd5_init(&ctx.hmd5, secret->rstart, -- REGION_SIZE(*secret)); -- isc_hmacmd5_update(&ctx.hmd5, data, length); -- isc_hmacmd5_sign(&ctx.hmd5, digest); -- source.rend = digest + ISC_MD5_DIGESTLENGTH; -- break; -+ if (isc_md5_available()) { -+ isc_hmacmd5_init(&ctx.hmd5, secret->rstart, -+ REGION_SIZE(*secret)); -+ isc_hmacmd5_update(&ctx.hmd5, data, length); -+ isc_hmacmd5_sign(&ctx.hmd5, digest); -+ source.rend = digest + ISC_MD5_DIGESTLENGTH; -+ break; -+ } else { -+ return (ISC_R_FAILURE); -+ } - - case ISCCC_ALG_HMACSHA1: - isc_hmacsha1_init(&ctx.hsha, secret->rstart, --- -2.14.4 - diff --git a/SOURCES/bind99-forward.patch b/SOURCES/bind99-forward.patch deleted file mode 100644 index 0392103..0000000 --- a/SOURCES/bind99-forward.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up bind-9.9.0b2/lib/dns/include/dns/Makefile.in.forward bind-9.9.0b2/lib/dns/include/dns/Makefile.in ---- bind-9.9.0b2/lib/dns/include/dns/Makefile.in.forward 2011-12-07 16:17:50.822438237 +0100 -+++ bind-9.9.0b2/lib/dns/include/dns/Makefile.in 2011-12-07 16:18:00.374455261 +0100 -@@ -31,7 +31,8 @@ HEADERS = acl.h adb.h byaddr.h cache.h c - rdataslab.h rdatatype.h request.h resolver.h result.h \ - rootns.h rpz.h sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h \ - tcpmsg.h time.h tkey.h tsig.h ttl.h types.h \ -- validator.h version.h view.h xfrin.h zone.h zonekey.h zt.h -+ validator.h version.h view.h xfrin.h zone.h zonekey.h zt.h \ -+ forward.h - - GENHEADERS = enumclass.h enumtype.h rdatastruct.h - diff --git a/SOURCES/bind99-libidn4.patch b/SOURCES/bind99-libidn4.patch deleted file mode 100644 index 99c1f13..0000000 --- a/SOURCES/bind99-libidn4.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff -up bind-9.7.0-P2/bin/dig/dig.docbook.rh811566 bind-9.7.0-P2/bin/dig/dig.docbook ---- bind-9.7.0-P2/bin/dig/dig.docbook.rh811566 2012-06-20 15:50:03.206839118 +0200 -+++ bind-9.7.0-P2/bin/dig/dig.docbook 2012-06-20 15:50:28.368558830 +0200 -@@ -912,8 +912,8 @@ dig +qr www.isc.org any -x 127.0.0.1 isc - dig appropriately converts character encoding of - domain name before sending a request to DNS server or displaying a - reply from the server. -- If you'd like to turn off the IDN support for some reason, defines -- the IDN_DISABLE environment variable. -+ If you'd like to turn off the IDN support for some reason, define -+ the CHARSET=ASCII environment variable. - The IDN support is disabled if the variable is set when - dig runs. - diff --git a/SOURCES/bind99-nta.patch b/SOURCES/bind99-nta.patch deleted file mode 100644 index 4d07104..0000000 --- a/SOURCES/bind99-nta.patch +++ /dev/null @@ -1,8290 +0,0 @@ -From 819ae187b1e3229baa33f475b940df01766b2a74 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= -Date: Thu, 9 Nov 2017 15:21:34 +0100 -Subject: [PATCH] Squashed commit of the following: - -commit a1d088bf6565826029187ff89e58694eaa236877 -Author: Mukund Sivaraman -Date: Mon Jan 12 09:04:16 2015 +0530 - - Add NTA persistence (#37087) - - 4034. [func] When added, negative trust anchors (NTA) are now - saved to files (viewname.nta), in order to - persist across restarts of the named server. - [RT #37087] - - (cherry picked from commit a6f0e9c985220f0e4509777e6528afb64e0ad576) - -commit 326288911b82bc42d3fe2b3de7a07e0060ebc840 -Author: Mark Andrews -Date: Sat Oct 18 10:07:24 2014 +1100 - - 3979. [bug] Negative trust anchor fetches where not properly managed. [RT #37488] - - (cherry picked from commit 48f97c23b7d59c925fc3f4280972e50b8ef67c35) - -commit b9facfeab727ae4d6d64cf9f09998b9d4df183ce -Author: Mark Andrews -Date: Thu Jul 10 10:24:47 2014 +1000 - - hold a nta reference while fetching - - (cherry picked from commit dcc7a2738ff7f68535f9d265df61298e4634055c) - -commit a8cf1c6ac1500f7f292ebe5a4d314285f76e8eae -Author: Mark Andrews -Date: Wed Jul 2 14:12:46 2014 +1000 - - be consistent about expire time - - (cherry picked from commit 7dbd30979997031ddd539f3543c6d2f9234f7978) - -commit 0ebf7e0e4b61113a694e88674865cdf086a4b5c1 -Author: Mark Andrews -Date: Thu Jun 19 10:20:34 2014 +1000 - - add #include - - (cherry picked from commit 3a37159a95e961066b90c493c5a4c92d3e0ec029) - -commit 410c729b2a457334a3d2202777c00a1af1f07f82 -Author: Evan Hunt -Date: Wed Jun 18 16:47:22 2014 -0700 - - complete NTA work - - 3882. [func] By default, negative trust anchors will be tested - periodically to see whether data below them can be - validated, and if so, they will be allowed to - expire early. The "rndc nta -force" option - overrides this behvaior. The default NTA lifetime - and the recheck frequency can be configured by the - "nta-lifetime" and "nta-recheck" options. [RT #36146] - - (cherry picked from commit b8a9632333a92d73a503afe1aaa7990016c8bee9) - -commit 0ef07209d5140c2fe395a4a7db25dbb860161e62 -Author: Mark Andrews -Date: Wed Jun 4 11:45:09 2014 +1000 - - bad size on isc_mem_put - - (cherry picked from commit f4db7287da3a6d9d15141d674732d98d39aa2461) - -commit 1d0a452481b92508cd1a7b4de9ab68e22db69a18 -Author: Evan Hunt -Date: Thu May 29 22:22:53 2014 -0700 - - rndc nta - - 3867. [func] "rndc nta" can now be used to set a temporary - negative trust anchor, which disables DNSSEC - validation below a specified name for a specified - period of time (not exceeding 24 hours). This - can be used when validation for a domain is known - to be failing due to a configuration error on - the part of the domain owner rather than a - spoofing attack. [RT #29358] - - (cherry picked from 0cfb24736841b3e98bb25853229a0efabab88bdd) - -delve - -3741. [func] "delve" (domain entity lookup and validation engine): - A new tool with dig-like semantics for performing DNS - lookups, with internal DNSSEC validation, using the - same resolver and validator logic as named. This - allows easy validation of DNSSEC data in environments - with untrustworthy resolvers, and assists with - troubleshooting of DNSSEC problems. (Note: not yet - available on win32.) [RT #32406] - -Additional fixes to adapt to 9.9 codebase - -fix possible rndc secroots crash - -3765. [bug] Fixed a bug in "rndc secroots" that could crash - named when dumping an empty keynode. [RT #35469] - -3761. [bug] Address dangling reference bug in dns_keytable_add. [RT #35471] - -add "rndc nta" options to "rndc -h" output - -rt38571: handle Time::Piece not being supported by perl - -(cherry-picked from 2b4860c4dc2d700c85f1edd16e6d5c27ccdb4080) - -NTAs did not survive reoad/reconfig - -4251. [bug] NTAs were deleted when the server was reconfigured - or reloaded. [RT #41058] - -Log path of nta file used into log file - -Revert some irrelevant parts - -Return NTA persistent not implemented in export libraries - -Fix name of nta file in tests - -update NTA limit to a week - -3940. [func] "rndc nta" now allows negative trust anchors to be - set for up to one week. [RT #37069] - -complete change #3882 - -Parse arguments to "rndc nta" so they can be either -long or shortened (i.e., both "-dump" and "-d" will work). - -"rndc nta -r" could hang - -3930. [bug] "rndc nta -r" could cause a server hang if the - NTA was not found. [RT #36909] - -allow 1-week nta-lifetime/nta-recheck - -3983. [bug] Change #3940 was incomplete: negative trust anchors - could be set to last up to a week, but the - "nta-lifetime" and "nta-recheck" options were - still limted to one day. [RT #37522] - -Address warnings and uninitialized variables - -checking that default nta's were lifted due to lifetime were not robust - -Reset return codes for separate dnssec tests - -oops, nta lifetime change broke dnssec test - -remove remains of file_sanitize not backported - -Always terminate after NTA entry, even in case all entries would not fit ---- - bin/delve/Makefile.in | 84 ++ - bin/delve/delve.1 | 388 ++++++ - bin/delve/delve.c | 1609 ++++++++++++++++++++++ - bin/delve/delve.docbook | 639 +++++++++ - bin/delve/delve.html | 445 ++++++ - bin/named/config.c | 2 + - bin/named/control.c | 2 + - bin/named/include/named/control.h | 1 + - bin/named/include/named/server.h | 19 + - bin/named/server.c | 343 ++++- - bin/rndc/rndc.c | 12 + - bin/rndc/rndc.docbook | 82 +- - bin/tests/system/checkconf/good.conf | 2 + - bin/tests/system/checkconf/tests.sh | 2 - - bin/tests/system/dlvauto/tests.sh | 2 +- - bin/tests/system/dnssec/clean.sh | 1 + - bin/tests/system/dnssec/ns2/example.db.in | 4 + - bin/tests/system/dnssec/ns2/sign.sh | 9 +- - bin/tests/system/dnssec/ns3/bogus.example.db.in | 1 + - bin/tests/system/dnssec/ns3/named.conf | 6 + - bin/tests/system/dnssec/ns3/secure.example.db.in | 4 + - bin/tests/system/dnssec/ns3/sign.sh | 16 + - bin/tests/system/dnssec/ns4/named1.conf | 3 + - bin/tests/system/dnssec/ntadiff.pl | 13 + - bin/tests/system/dnssec/setup.sh | 2 + - bin/tests/system/dnssec/tests.sh | 396 +++++- - bin/tests/system/rndc/tests.sh | 6 + - configure.in | 3 + - doc/arm/Bv9ARM-book.xml | 74 +- - lib/bind9/check.c | 33 + - lib/dns/Makefile.in | 7 +- - lib/dns/adb.c | 6 +- - lib/dns/client.c | 82 +- - lib/dns/include/dns/client.h | 26 +- - lib/dns/include/dns/keytable.h | 10 +- - lib/dns/include/dns/log.h | 2 + - lib/dns/include/dns/masterdump.h | 9 + - lib/dns/include/dns/message.h | 12 + - lib/dns/include/dns/nta.h | 220 +++ - lib/dns/include/dns/resolver.h | 5 +- - lib/dns/include/dns/result.h | 3 +- - lib/dns/include/dns/types.h | 2 + - lib/dns/include/dns/validator.h | 7 +- - lib/dns/include/dns/view.h | 88 +- - lib/dns/keytable.c | 16 +- - lib/dns/log.c | 2 + - lib/dns/masterdump.c | 26 + - lib/dns/message.c | 48 + - lib/dns/nta.c | 683 +++++++++ - lib/dns/resolver.c | 135 +- - lib/dns/result.c | 3 +- - lib/dns/tests/Makefile.in | 10 +- - lib/dns/tests/dnstest.c | 22 +- - lib/dns/tests/dnstest.h | 3 + - lib/dns/tests/keytable_test.c | 611 ++++++++ - lib/dns/validator.c | 52 +- - lib/dns/view.c | 237 +++- - lib/export/dns/Makefile.in | 4 +- - lib/isc/include/isc/log.h | 6 +- - lib/isc/log.c | 20 +- - lib/isc/unix/app.c | 1 - - lib/isccfg/namedconf.c | 45 + - make/includes.in | 3 + - make/rules.in | 3 +- - 64 files changed, 6453 insertions(+), 159 deletions(-) - create mode 100644 bin/delve/Makefile.in - create mode 100644 bin/delve/delve.1 - create mode 100644 bin/delve/delve.c - create mode 100644 bin/delve/delve.docbook - create mode 100644 bin/delve/delve.html - create mode 100755 bin/tests/system/dnssec/ntadiff.pl - create mode 100644 lib/dns/include/dns/nta.h - create mode 100644 lib/dns/nta.c - create mode 100644 lib/dns/tests/keytable_test.c - -diff --git a/bin/delve/Makefile.in b/bin/delve/Makefile.in -new file mode 100644 -index 0000000000..bfd5adfea6 ---- /dev/null -+++ b/bin/delve/Makefile.in -@@ -0,0 +1,84 @@ -+# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_VERSION@ -+ -+@BIND9_MAKE_INCLUDES@ -+ -+CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${ISC_INCLUDES} \ -+ ${IRS_INCLUDES} ${ISCCFG_INCLUDES} -+ -+CDEFINES = -DVERSION=\"${VERSION}\" -DSYSCONFDIR=\"${sysconfdir}\" -+CWARNINGS = -+ -+ISCCFGLIBS = ../../lib/export/isccfg/libisccfg-export.@A@ -+DNSLIBS = ../../lib/export/dns/libdns-export.@A@ @DNS_CRYPTO_LIBS@ -+ISCNOSYMLIBS = ../../lib/export/isc/libisc-export.@A@ -+ISCLIBS = ../../lib/export/isc/libisc-export.@A@ -+IRSLIBS = ../../lib/export/irs/libirs-export.@A@ -+ -+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ -+DNSDEPLIBS = ../../lib/export/dns/libdns-export.@A@ -+ISCDEPLIBS = ../../lib/export/isc/libisc-export.@A@ -+IRSDEPLIBS = ../../lib/export/irs/libirs-export.@A@ -+ -+DEPLIBS = ${DNSDEPLIBS} ${IRSDEPLIBS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} -+ -+LIBS = ${DNSLIBS} ${IRSLIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ -+NOSYMLIBS = ${DNSLIBS} ${IRSLIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@ -+ -+SUBDIRS = -+ -+TARGETS = delve@EXEEXT@ -+ -+OBJS = delve.@O@ -+ -+SRCS = delve.c -+ -+MANPAGES = delve.1 -+ -+HTMLPAGES = delve.html -+ -+MANOBJS = ${MANPAGES} ${HTMLPAGES} -+ -+@BIND9_MAKE_RULES@ -+ -+delve@EXEEXT@: delve.@O@ ${DEPLIBS} -+ export BASEOBJS="delve.@O@"; \ -+ export LIBS0="${DNSLIBS}"; \ -+ ${FINALBUILDCMD} -+ -+# ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ -+# delve.@O@ ${LIBS} -+ -+installdirs: -+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} -+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1 -+ -+install:: delve@EXEEXT@ -+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \ -+ delve@EXEEXT@ ${DESTDIR}${bindir} -+ ${INSTALL_DATA} ${srcdir}/delve.1 ${DESTDIR}${mandir}/man1 -+ -+doc man:: ${MANOBJS} -+ -+docclean manclean maintainer-clean:: -+ rm -f ${MANOBJS} -+ -+clean distclean maintainer-clean:: -+ rm -f ${TARGETS} -diff --git a/bin/delve/delve.1 b/bin/delve/delve.1 -new file mode 100644 -index 0000000000..54abfcce7e ---- /dev/null -+++ b/bin/delve/delve.1 -@@ -0,0 +1,388 @@ -+.\" Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+.\" -+.\" Permission to use, copy, modify, and/or distribute this software for any -+.\" purpose with or without fee is hereby granted, provided that the above -+.\" copyright notice and this permission notice appear in all copies. -+.\" -+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+.\" PERFORMANCE OF THIS SOFTWARE. -+.\" -+.\" $Id$ -+.\" -+.hy 0 -+.ad l -+.\" Title: delve -+.\" Author: -+.\" Generator: DocBook XSL Stylesheets v1.71.1 -+.\" Date: February 12, 2014 -+.\" Manual: BIND9 -+.\" Source: BIND9 -+.\" -+.TH "DELVE" "1" "February 12, 2014" "BIND9" "BIND9" -+.\" disable hyphenation -+.nh -+.\" disable justification (adjust text to left margin only) -+.ad l -+.SH "NAME" -+delve \- DNS lookup and validation utility -+.SH "SYNOPSIS" -+.HP 6 -+\fBdelve\fR [@server] [\fB\-4\fR] [\fB\-6\fR] [\fB\-a\ \fR\fB\fIanchor\-file\fR\fR] [\fB\-b\ \fR\fB\fIaddress\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-d\ \fR\fB\fIlevel\fR\fR] [\fB\-i\fR] [\fB\-m\fR] [\fB\-p\ \fR\fB\fIport#\fR\fR] [\fB\-q\ \fR\fB\fIname\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-x\ \fR\fB\fIaddr\fR\fR] [name] [type] [class] [queryopt...] -+.HP 6 -+\fBdelve\fR [\fB\-h\fR] -+.HP 6 -+\fBdelve\fR [queryopt...] [query...] -+.SH "DESCRIPTION" -+.PP -+\fBdelve\fR -+(Domain Entity Lookup & Validation Engine) is a tool for sending DNS queries and validating the results, using the the same internal resolver and validator logic as -+\fBnamed\fR. -+.PP -+\fBdelve\fR -+will send to a specified name server all queries needed to fetch and validate the requested data; this includes the original requested query, subsequent queries to follow CNAME or DNAME chains, and queries for DNSKEY, DS and DLV records to establish a chain of trust for DNSSEC validation. It does not perform iterative resolution, but simulates the behavior of a name server configured for DNSSEC validating and forwarding. -+.PP -+By default, responses are validated using built\-in DNSSEC trust anchors for the root zone (".") and for the ISC DNSSEC lookaside validation zone ("dlv.isc.org"). Records returned by -+\fBdelve\fR -+are either fully validated or were not signed. If validation fails, an explanation of the failure is included in the output; the validation process can be traced in detail. Because -+\fBdelve\fR -+does not rely on an external server to carry out validation, it can be used to check the validity of DNS responses in environments where local name servers may not be trustworthy. -+.PP -+Unless it is told to query a specific name server, -+\fBdelve\fR -+will try each of the servers listed in -+\fI/etc/resolv.conf\fR. If no usable server addresses are found, -+\fBdelve\fR -+will send queries to the localhost addresses (127.0.0.1 for IPv4, ::1 for IPv6). -+.PP -+When no command line arguments or options are given, -+\fBdelve\fR -+will perform an NS query for "." (the root zone). -+.SH "SIMPLE USAGE" -+.PP -+A typical invocation of -+\fBdelve\fR -+looks like: -+.sp -+.RS 4 -+.nf -+ delve @server name type -+.fi -+.RE -+.sp -+where: -+.PP -+\fBserver\fR -+.RS 4 -+is the name or IP address of the name server to query. This can be an IPv4 address in dotted\-decimal notation or an IPv6 address in colon\-delimited notation. When the supplied -+\fIserver\fR -+argument is a hostname, -+\fBdelve\fR -+resolves that name before querying that name server (note, however, that this initial lookup is -+\fInot\fR -+validated by DNSSEC). -+.sp -+If no -+\fIserver\fR -+argument is provided, -+\fBdelve\fR -+consults -+\fI/etc/resolv.conf\fR; if an address is found there, it queries the name server at that address. If either of the -+\fB\-4\fR -+or -+\fB\-6\fR -+options are in use, then only addresses for the corresponding transport will be tried. If no usable addresses are found, -+\fBdelve\fR -+will send queries to the localhost addresses (127.0.0.1 for IPv4, ::1 for IPv6). -+.RE -+.PP -+\fBname\fR -+.RS 4 -+is the domain name to be looked up. -+.RE -+.PP -+\fBtype\fR -+.RS 4 -+indicates what type of query is required \(em ANY, A, MX, etc. -+\fItype\fR -+can be any valid query type. If no -+\fItype\fR -+argument is supplied, -+\fBdelve\fR -+will perform a lookup for an A record. -+.RE -+.SH "OPTIONS" -+.PP -+\-a -+.RS 4 -+Specifies a file from which to read DNSSEC trust anchors. The default is -+\fI/etc/bind.keys\fR, which is included with -+BIND -+9 and contains trust anchors for the root zone (".") and for the ISC DNSSEC lookaside validation zone ("dlv.isc.org"). -+.sp -+Keys that do not match the root or DLV trust\-anchor names are ignored; these key names can be overridden using the -+\fB+dlv=NAME\fR -+or -+\fB+root=NAME\fR -+options. -+.sp -+Note: When reading the trust anchor file, -+\fBdelve\fR -+treats -+\fBmanaged\-keys\fR -+statements and -+\fBtrusted\-keys\fR -+statements identically. That is, for a managed key, it is the -+\fIinitial\fR -+key that is trusted; RFC 5011 key management is not supported. -+\fBdelve\fR -+will not consult the managed\-keys database maintained by -+\fBnamed\fR. This means that if either of the keys in -+\fI/etc/bind.keys\fR -+is revoked and rolled over, it will be necessary to update -+\fI/etc/bind.keys\fR -+to use DNSSEC validation in -+\fBdelve\fR. -+.RE -+.PP -+\-b -+.RS 4 -+Sets the source IP address of the query to -+\fIaddress\fR. This must be a valid address on one of the host's network interfaces or "0.0.0.0" or "::". An optional source port may be specified by appending "#" -+.RE -+.PP -+\-c -+.RS 4 -+Sets the query class for the requested data. Currently, only class "IN" is supported in -+\fBdelve\fR -+and any other value is ignored. -+.RE -+.PP -+\-i -+.RS 4 -+Insecure mode. This disables internal DNSSEC validation. (Note, however, this does not set the CD bit on upstream queries. If the server being queried is performing DNSSEC validation, then it will not return invalid data; this can cause -+\fBdelve\fR -+to time out. When it is necessary to examine invalid data to debug a DNSSEC problem, use -+\fBdig +cd\fR.) -+.RE -+.PP -+\-m -+.RS 4 -+Enables memory usage debugging. -+.RE -+.PP -+\-p -+.RS 4 -+Specifies a destination port to use for queries instead of the standard DNS port number 53. This option would be used with a name server that has been configured to listen for queries on a non\-standard port number. -+.RE -+.PP -+\-4 -+.RS 4 -+Forces -+\fBdelve\fR -+to only use IPv4. -+.RE -+.PP -+\-6 -+.RS 4 -+Forces -+\fBdelve\fR -+to only use IPv6. -+.RE -+.PP -+\-q -+.RS 4 -+Sets the query name to -+\fIname\fR. While the query name can be specified without using the -+\fB\-q\fR, it is sometimes necessary to disambiguate names from types or classes (for example, when looking up the name "ns", which could be misinterpreted as the type NS, or "ch", which could be misinterpreted as class CH). -+.RE -+.PP -+\-t -+.RS 4 -+Sets the query type to -+\fItype\fR, which can be any valid query type supported in BIND 9 except for zone transfer types AXFR and IXFR. As with -+\fB\-q\fR, this is useful to distinguish query name type or class when they are ambiguous. it is sometimes necessary to disambiguate names from types. -+.sp -+The default query type is "A", unless the -+\fB\-x\fR -+option is supplied to indicate a reverse lookup, in which case it is "PTR". -+.RE -+.PP -+\-x -+.RS 4 -+Performs a reverse lookup, mapping an addresses to a name. -+\fIaddr\fR -+is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address. When -+\fB\-x\fR -+is used, there is no need to provide the -+\fIname\fR -+or -+\fItype\fR -+arguments. -+\fBdelve\fR -+automatically performs a lookup for a name like -+11.12.13.10.in\-addr.arpa -+and sets the query type to PTR. IPv6 addresses are looked up using nibble format under the IP6.ARPA domain. -+.RE -+.SH "QUERY OPTIONS" -+.PP -+\fBdelve\fR -+provides a number of query options which affect the way results are displayed, and in some cases the way lookups are performed. -+.PP -+Each query option is identified by a keyword preceded by a plus sign (+). Some keywords set or reset an option. These may be preceded by the string -+no -+to negate the meaning of that keyword. Other keywords assign values to options like the timeout interval. They have the form -+\fB+keyword=value\fR. The query options are: -+.PP -+\fB+[no]cdflag\fR -+.RS 4 -+Controls whether to set the CD (checking disabled) bit in queries sent by -+\fBdelve\fR. This may be useful when troubleshooting DNSSEC problems from behind a validating resolver. A validating resolver will block invalid responses, making it difficult to retrieve them for analysis. Setting the CD flag on queries will cause the resolver to return invalid responses, which -+\fBdelve\fR -+can then validate internally and report the errors in detail. -+.RE -+.PP -+\fB+[no]class\fR -+.RS 4 -+Controls whether to display the CLASS when printing a record. The default is to display the CLASS. -+.RE -+.PP -+\fB+[no]ttl\fR -+.RS 4 -+Controls whether to display the TTL when printing a record. The default is to display the TTL. -+.RE -+.PP -+\fB+[no]rtrace\fR -+.RS 4 -+Toggle resolver fetch logging. This reports the name and type of each query sent by -+\fBdelve\fR -+in the process of carrying out the resolution and validation process: this includes including the original query and all subsequent queries to follow CNAMEs and to establish a chain of trust for DNSSEC validation. -+.sp -+This is equivalent to setting the debug level to 1 in the "resolver" logging category. Setting the systemwide debug level to 1 using the -+\fB\-d\fR -+option will product the same output (but will affect other logging categories as well). -+.RE -+.PP -+\fB+[no]mtrace\fR -+.RS 4 -+Toggle message logging. This produces a detailed dump of the responses received by -+\fBdelve\fR -+in the process of carrying out the resolution and validation process. -+.sp -+This is equivalent to setting the debug level to 10 for the the "packets" module of the "resolver" logging category. Setting the systemwide debug level to 10 using the -+\fB\-d\fR -+option will produce the same output (but will affect other logging categories as well). -+.RE -+.PP -+\fB+[no]vtrace\fR -+.RS 4 -+Toggle validation logging. This shows the internal process of the validator as it determines whether an answer is validly signed, unsigned, or invalid. -+.sp -+This is equivalent to setting the debug level to 3 for the the "validator" module of the "dnssec" logging category. Setting the systemwide debug level to 3 using the -+\fB\-d\fR -+option will produce the same output (but will affect other logging categories as well). -+.RE -+.PP -+\fB+[no]short\fR -+.RS 4 -+Provide a terse answer. The default is to print the answer in a verbose form. -+.RE -+.PP -+\fB+[no]comments\fR -+.RS 4 -+Toggle the display of comment lines in the output. The default is to print comments. -+.RE -+.PP -+\fB+[no]rrcomments\fR -+.RS 4 -+Toggle the display of per\-record comments in the output (for example, human\-readable key information about DNSKEY records). The default is to print per\-record comments. -+.RE -+.PP -+\fB+[no]crypto\fR -+.RS 4 -+Toggle the display of cryptographic fields in DNSSEC records. The contents of these field are unnecessary to debug most DNSSEC validation failures and removing them makes it easier to see the common failures. The default is to display the fields. When omitted they are replaced by the string "[omitted]" or in the DNSKEY case the key id is displayed as the replacement, e.g. "[ key id = value ]". -+.RE -+.PP -+\fB+[no]trust\fR -+.RS 4 -+Controls whether to display the trust level when printing a record. The default is to display the trust level. -+.RE -+.PP -+\fB+[no]split[=W]\fR -+.RS 4 -+Split long hex\- or base64\-formatted fields in resource records into chunks of -+\fIW\fR -+characters (where -+\fIW\fR -+is rounded up to the nearest multiple of 4). -+\fI+nosplit\fR -+or -+\fI+split=0\fR -+causes fields not to be split at all. The default is 56 characters, or 44 characters when multiline mode is active. -+.RE -+.PP -+\fB+[no]all\fR -+.RS 4 -+Set or clear the display options -+\fB+[no]comments\fR, -+\fB+[no]rrcomments\fR, and -+\fB+[no]trust\fR -+as a group. -+.RE -+.PP -+\fB+[no]multiline\fR -+.RS 4 -+Print long records (such as RRSIG, DNSKEY, and SOA records) in a verbose multi\-line format with human\-readable comments. The default is to print each record on a single line, to facilitate machine parsing of the -+\fBdelve\fR -+output. -+.RE -+.PP -+\fB+[no]dnssec\fR -+.RS 4 -+Indicates whether to display RRSIG records in the -+\fBdelve\fR -+output. The default is to do so. Note that (unlike in -+\fBdig\fR) this does -+\fInot\fR -+control whether to request DNSSEC records or whether to validate them. DNSSEC records are always requested, and validation will always occur unless suppressed by the use of -+\fB\-i\fR -+or -+\fB+noroot\fR -+and -+\fB+nodlv\fR. -+.RE -+.PP -+\fB+[no]root[=ROOT]\fR -+.RS 4 -+Indicates whether to perform conventional (non\- lookaside) DNSSEC validation, and if so, specifies the name of a trust anchor. The default is to validate using a trust anchor of "." (the root zone), for which there is a built\-in key. If specifying a different trust anchor, then -+\fB\-a\fR -+must be used to specify a file containing the key. -+.RE -+.PP -+\fB+[no]dlv[=DLV]\fR -+.RS 4 -+Indicates whether to perform DNSSEC lookaside validation, and if so, specifies the name of the DLV trust anchor. The default is to perform lookaside validation using a trust anchor of "dlv.isc.org", for which there is a built\-in key. If specifying a different name, then -+\fB\-a\fR -+must be used to specify a file containing the DLV key. -+.RE -+.SH "FILES" -+.PP -+\fI/etc/bind.keys\fR -+.PP -+\fI/etc/resolv.conf\fR -+.SH "SEE ALSO" -+.PP -+\fBdig\fR(1), -+\fBnamed\fR(8), -+RFC4034, -+RFC4035, -+RFC4431, -+RFC5074, -+RFC5155. -+.SH "COPYRIGHT" -+Copyright \(co 2014 Internet Systems Consortium, Inc. ("ISC") -+.br -diff --git a/bin/delve/delve.c b/bin/delve/delve.c -new file mode 100644 -index 0000000000..9816cff1e4 ---- /dev/null -+++ b/bin/delve/delve.c -@@ -0,0 +1,1609 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#define CHECK(r) \ -+ do { \ -+ result = (r); \ -+ if (result != ISC_R_SUCCESS) \ -+ goto cleanup; \ -+ } while (0) -+ -+#define MAXNAME (DNS_NAME_MAXTEXT+1) -+ -+/* Variables used internally by delve. */ -+char *progname; -+static isc_mem_t *mctx = NULL; -+static isc_log_t *lctx = NULL; -+ -+/* Configurables */ -+static char *server = NULL; -+static const char *port = "53"; -+static isc_sockaddr_t *srcaddr4 = NULL, *srcaddr6 = NULL; -+static char *curqname = NULL, *qname = NULL; -+static isc_boolean_t classset = ISC_FALSE; -+static dns_rdatatype_t qtype = dns_rdatatype_none; -+static isc_boolean_t typeset = ISC_FALSE; -+ -+static unsigned int styleflags = 0; -+static isc_uint32_t splitwidth = 0xffffffff; -+static isc_boolean_t -+ showcomments = ISC_TRUE, -+ showdnssec = ISC_TRUE, -+ showtrust = ISC_TRUE, -+ rrcomments = ISC_TRUE, -+ noclass = ISC_FALSE, -+ nocrypto = ISC_FALSE, -+ nottl = ISC_FALSE, -+ multiline = ISC_FALSE, -+ short_form = ISC_FALSE; -+ -+static isc_boolean_t -+ resolve_trace = ISC_FALSE, -+ validator_trace = ISC_FALSE, -+ message_trace = ISC_FALSE; -+ -+static isc_boolean_t -+ use_ipv4 = ISC_TRUE, -+ use_ipv6 = ISC_TRUE; -+ -+static isc_boolean_t -+ cdflag = ISC_FALSE, -+ no_sigs = ISC_FALSE, -+ root_validation = ISC_TRUE, -+ dlv_validation = ISC_TRUE; -+ -+static char *anchorfile = NULL; -+static char *trust_anchor = NULL; -+static char *dlv_anchor = NULL; -+static int trusted_keys = 0; -+ -+static dns_fixedname_t afn, dfn; -+static dns_name_t *anchor_name = NULL, *dlv_name = NULL; -+ -+/* Default bind.keys contents */ -+static char anchortext[] = MANAGED_KEYS; -+ -+/* -+ * Static function prototypes -+ */ -+static isc_result_t -+get_reverse(char *reverse, size_t len, char *value, isc_boolean_t strict); -+ -+static isc_result_t -+parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, -+ const char *desc); -+ -+static void -+usage(void) { -+ fputs( -+"Usage: delve [@server] {q-opt} {d-opt} [domain] [q-type] [q-class]\n" -+"Where: domain is in the Domain Name System\n" -+" q-class is one of (in,hs,ch,...) [default: in]\n" -+" q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n" -+" q-opt is one of:\n" -+" -x dot-notation (shortcut for reverse lookups)\n" -+" -d level (set debugging level)\n" -+" -a anchor-file (specify root and dlv trust anchors)\n" -+" -b address[#port] (bind to source address/port)\n" -+" -p port (specify port number)\n" -+" -q name (specify query name)\n" -+" -t type (specify query type)\n" -+" -c class (specify query class)\n" -+" -4 (use IPv4 query transport only)\n" -+" -6 (use IPv6 query transport only)\n" -+" -i (disable DNSSEC validation)\n" -+" -m (enable memory usage debugging)\n" -+" d-opt is of the form +keyword[=value], where keyword is:\n" -+" +[no]all (Set or clear all display flags)\n" -+" +[no]class (Control display of class)\n" -+" +[no]crypto (Control display of cryptographic\n" -+" fields in records)\n" -+" +[no]multiline (Print records in an expanded format)\n" -+" +[no]comments (Control display of comment lines)\n" -+" +[no]rrcomments (Control display of per-record " -+ "comments)\n" -+" +[no]short (Short form answer)\n" -+" +[no]split=## (Split hex/base64 fields into chunks)\n" -+" +[no]ttl (Control display of ttls in records)\n" -+" +[no]trust (Control display of trust level)\n" -+" +[no]rtrace (Trace resolver fetches)\n" -+" +[no]mtrace (Trace messages received)\n" -+" +[no]vtrace (Trace validation process)\n" -+" +[no]dlv (DNSSEC lookaside validation anchor)\n" -+" +[no]root (DNSSEC validation trust anchor)\n" -+" +[no]dnssec (Display DNSSEC records)\n" -+" -h (print help and exit)\n" -+" -v (print version and exit)\n", -+ stderr); -+ exit(1); -+} -+ -+static void -+fatal(const char *format, ...) { -+ va_list args; -+ -+ fflush(stdout); -+ fprintf(stderr, "%s: ", progname); -+ va_start(args, format); -+ vfprintf(stderr, format, args); -+ va_end(args); -+ fprintf(stderr, "\n"); -+ exit(1); -+} -+ -+static void -+warn(const char *format, ...) { -+ va_list args; -+ -+ fflush(stdout); -+ fprintf(stderr, "%s: warning: ", progname); -+ va_start(args, format); -+ vfprintf(stderr, format, args); -+ va_end(args); -+ fprintf(stderr, "\n"); -+} -+ -+static isc_logcategory_t categories[] = { -+ { "delve", 0 }, -+ { NULL, 0 } -+}; -+#define LOGCATEGORY_DEFAULT (&categories[0]) -+#define LOGMODULE_DEFAULT (&modules[0]) -+ -+static isc_logmodule_t modules[] = { -+ { "delve", 0 }, -+ { NULL, 0 } -+}; -+ -+static void -+delve_log(int level, const char *fmt, ...) { -+ va_list ap; -+ char msgbuf[2048]; -+ -+ if (! isc_log_wouldlog(lctx, level)) -+ return; -+ -+ va_start(ap, fmt); -+ -+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); -+ isc_log_write(lctx, LOGCATEGORY_DEFAULT, LOGMODULE_DEFAULT, -+ level, "%s", msgbuf); -+ va_end(ap); -+} -+ -+static int loglevel = 0; -+ -+static void -+setup_logging(FILE *errout) { -+ isc_result_t result; -+ isc_logdestination_t destination; -+ isc_logconfig_t *logconfig = NULL; -+ -+ result = isc_log_create(mctx, &lctx, &logconfig); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't set up logging"); -+ -+ isc_log_registercategories(lctx, categories); -+ isc_log_registermodules(lctx, modules); -+ isc_log_setcontext(lctx); -+ dns_log_init(lctx); -+ dns_log_setcontext(lctx); -+ cfg_log_init(lctx); -+ -+ destination.file.stream = errout; -+ destination.file.name = NULL; -+ destination.file.versions = ISC_LOG_ROLLNEVER; -+ destination.file.maximum_size = 0; -+ -+ result = isc_log_createchannel(logconfig, "stderr", -+ ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, -+ &destination, ISC_LOG_PRINTPREFIX); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't set up log channel 'stderr'"); -+ -+ isc_log_setdebuglevel(lctx, loglevel); -+ -+ result = isc_log_settag(logconfig, ";; "); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't set log tag"); -+ -+ result = isc_log_usechannel(logconfig, "stderr", -+ ISC_LOGCATEGORY_DEFAULT, NULL); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't attach to log channel 'stderr'"); -+ -+ if (resolve_trace && loglevel < 1) { -+ result = isc_log_createchannel(logconfig, "resolver", -+ ISC_LOG_TOFILEDESC, -+ ISC_LOG_DEBUG(1), -+ &destination, -+ ISC_LOG_PRINTPREFIX); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't set up log channel 'resolver'"); -+ -+ result = isc_log_usechannel(logconfig, "resolver", -+ DNS_LOGCATEGORY_RESOLVER, -+ DNS_LOGMODULE_RESOLVER); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't attach to log channel 'resolver'"); -+ } -+ -+ if (validator_trace && loglevel < 3) { -+ result = isc_log_createchannel(logconfig, "validator", -+ ISC_LOG_TOFILEDESC, -+ ISC_LOG_DEBUG(3), -+ &destination, -+ ISC_LOG_PRINTPREFIX); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't set up log channel 'validator'"); -+ -+ result = isc_log_usechannel(logconfig, "validator", -+ DNS_LOGCATEGORY_DNSSEC, -+ DNS_LOGMODULE_VALIDATOR); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't attach to log channel 'validator'"); -+ } -+ -+ if (message_trace && loglevel < 10) { -+ result = isc_log_createchannel(logconfig, "messages", -+ ISC_LOG_TOFILEDESC, -+ ISC_LOG_DEBUG(10), -+ &destination, -+ ISC_LOG_PRINTPREFIX); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't set up log channel 'messages'"); -+ -+ result = isc_log_usechannel(logconfig, "messages", -+ DNS_LOGCATEGORY_RESOLVER, -+ DNS_LOGMODULE_PACKETS); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't attach to log channel 'messagse'"); -+ } -+} -+ -+static void -+print_status(dns_rdataset_t *rdataset) { -+ const char *astr = "", *tstr = ""; -+ -+ REQUIRE(rdataset != NULL); -+ -+ if (!showtrust || !dns_rdataset_isassociated(rdataset)) -+ return; -+ -+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) -+ astr = "negative response, "; -+ -+ switch (rdataset->trust) { -+ case dns_trust_none: -+ tstr = "untrusted"; -+ break; -+ case dns_trust_pending_additional: -+ tstr = "signed additional data, pending validation"; -+ break; -+ case dns_trust_pending_answer: -+ tstr = "signed answer, pending validation"; -+ break; -+ case dns_trust_additional: -+ tstr = "unsigned additional data"; -+ break; -+ case dns_trust_glue: -+ tstr = "glue data"; -+ break; -+ case dns_trust_answer: -+ if (root_validation || dlv_validation) -+ tstr = "unsigned answer"; -+ else -+ tstr = "answer not validated"; -+ break; -+ case dns_trust_authauthority: -+ tstr = "authority data"; -+ break; -+ case dns_trust_authanswer: -+ tstr = "authoritative"; -+ break; -+ case dns_trust_secure: -+ tstr = "fully validated"; -+ break; -+ case dns_trust_ultimate: -+ tstr = "ultimate trust"; -+ break; -+ } -+ -+ printf("; %s%s\n", astr, tstr); -+} -+ -+static isc_result_t -+printdata(dns_rdataset_t *rdataset, dns_name_t *owner, -+ dns_master_style_t *style) -+{ -+ isc_result_t result = ISC_R_SUCCESS; -+ static dns_trust_t trust; -+ static isc_boolean_t first = ISC_TRUE; -+ isc_buffer_t target; -+ isc_region_t r; -+ char *t = NULL; -+ int len = 2048; -+ -+ if (!dns_rdataset_isassociated(rdataset)) { -+ char namebuf[DNS_NAME_FORMATSIZE]; -+ dns_name_format(owner, namebuf, sizeof(namebuf)); -+ delve_log(ISC_LOG_DEBUG(4), -+ "WARN: empty rdataset %s", namebuf); -+ return (ISC_R_SUCCESS); -+ } -+ -+ if (!showdnssec && rdataset->type == dns_rdatatype_rrsig) -+ return (ISC_R_SUCCESS); -+ -+ isc_buffer_init(&target, t, sizeof(t)); -+ -+ if (first || rdataset->trust != trust) { -+ if (!first && showtrust && !short_form) -+ putchar('\n'); -+ print_status(rdataset); -+ trust = rdataset->trust; -+ first = ISC_FALSE; -+ } -+ -+ do { -+ t = isc_mem_get(mctx, len); -+ if (t == NULL) -+ return (ISC_R_NOMEMORY); -+ -+ isc_buffer_init(&target, t, len); -+ if (short_form) { -+ dns_rdata_t rdata = DNS_RDATA_INIT; -+ for (result = dns_rdataset_first(rdataset); -+ result == ISC_R_SUCCESS; -+ result = dns_rdataset_next(rdataset)) -+ { -+ isc_region_t r; -+ -+ if ((rdataset->attributes & -+ DNS_RDATASETATTR_NEGATIVE) != 0) -+ continue; -+ -+ dns_rdataset_current(rdataset, &rdata); -+ result = dns_rdata_tofmttext(&rdata, -+ dns_rootname, -+ styleflags, -+ 0, 60, " ", -+ &target); -+ if (result != ISC_R_SUCCESS) -+ break; -+ -+ isc_buffer_availableregion(&target, &r); -+ if (r.length < 1) { -+ result = ISC_R_NOSPACE; -+ break; -+ } -+ -+ r.base[0] = '\n'; -+ isc_buffer_add(&target, 1); -+ -+ dns_rdata_reset(&rdata); -+ } -+ } else { -+ if ((rdataset->attributes & -+ DNS_RDATASETATTR_NEGATIVE) != 0) -+ isc_buffer_putstr(&target, "; "); -+ -+ result = dns_master_rdatasettotext(owner, rdataset, -+ style, &target); -+ } -+ -+ if (result == ISC_R_NOSPACE) { -+ isc_mem_put(mctx, t, len); -+ len += 1024; -+ } else -+ CHECK(result); -+ } while (result == ISC_R_NOSPACE); -+ -+ isc_buffer_usedregion(&target, &r); -+ printf("%.*s", (int)r.length, (char *)r.base); -+ -+ cleanup: -+ if (t != NULL) -+ isc_mem_put(mctx, t, len); -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+setup_style(dns_master_style_t **stylep) { -+ isc_result_t result; -+ dns_master_style_t *style = NULL; -+ -+ REQUIRE(stylep != NULL || *stylep == NULL); -+ -+ styleflags |= DNS_STYLEFLAG_REL_OWNER; -+ if (showcomments) -+ styleflags |= DNS_STYLEFLAG_COMMENT; -+ if (rrcomments) -+ styleflags |= DNS_STYLEFLAG_RRCOMMENT; -+ if (nottl) -+ styleflags |= DNS_STYLEFLAG_NO_TTL; -+ if (noclass) -+ styleflags |= DNS_STYLEFLAG_NO_CLASS; -+#if 0 -+ if (nocrypto) -+ styleflags |= DNS_STYLEFLAG_NOCRYPTO; -+#endif -+ if (multiline) { -+ styleflags |= DNS_STYLEFLAG_MULTILINE; -+ styleflags |= DNS_STYLEFLAG_COMMENT; -+ } -+ -+ if (multiline || (nottl && noclass)) -+ result = dns_master_stylecreate2(&style, styleflags, -+ 24, 24, 24, 32, 80, 8, -+ splitwidth, mctx); -+ else if (nottl || noclass) -+ result = dns_master_stylecreate2(&style, styleflags, -+ 24, 24, 32, 40, 80, 8, -+ splitwidth, mctx); -+ else -+ result = dns_master_stylecreate2(&style, styleflags, -+ 24, 32, 40, 48, 80, 8, -+ splitwidth, mctx); -+ -+ if (result == ISC_R_SUCCESS) -+ *stylep = style; -+ return (result); -+} -+ -+static isc_result_t -+convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) { -+ isc_result_t result; -+ isc_buffer_t b; -+ dns_name_t *n; -+ size_t len; -+ -+ REQUIRE(fn != NULL && name != NULL && text != NULL); -+ len = strlen(text); -+ -+ isc_buffer_constinit(&b, text, len); -+ isc_buffer_add(&b, len); -+ dns_fixedname_init(fn); -+ n = dns_fixedname_name(fn); -+ -+ result = dns_name_fromtext(n, &b, dns_rootname, 0, NULL); -+ if (result != ISC_R_SUCCESS) { -+ delve_log(ISC_LOG_ERROR, "failed to convert QNAME %s: %s", -+ text, isc_result_totext(result)); -+ return (result); -+ } -+ -+ *name = n; -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+key_fromconfig(const cfg_obj_t *key, dns_client_t *client) { -+ dns_rdata_dnskey_t keystruct; -+ isc_uint32_t flags, proto, alg; -+ const char *keystr, *keynamestr; -+ unsigned char keydata[4096]; -+ isc_buffer_t keydatabuf; -+ unsigned char rrdata[4096]; -+ isc_buffer_t rrdatabuf; -+ isc_region_t r; -+ dns_fixedname_t fkeyname; -+ dns_name_t *keyname; -+ isc_result_t result; -+ isc_boolean_t match_root, match_dlv; -+ -+ keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); -+ CHECK(convert_name(&fkeyname, &keyname, keynamestr)); -+ -+ if (!root_validation && !dlv_validation) -+ return (ISC_R_SUCCESS); -+ -+ match_root = dns_name_equal(keyname, anchor_name); -+ match_dlv = dns_name_equal(keyname, dlv_name); -+ -+ if (!match_root && !match_dlv) -+ return (ISC_R_SUCCESS); -+ if ((!root_validation && match_root) || (!dlv_validation && match_dlv)) -+ return (ISC_R_SUCCESS); -+ -+ if (match_root) -+ delve_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", -+ trust_anchor); -+ if (match_dlv) -+ delve_log(ISC_LOG_DEBUG(3), "adding DLV trust anchor %s", -+ dlv_anchor); -+ -+ flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); -+ proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); -+ alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); -+ -+ keystruct.common.rdclass = dns_rdataclass_in; -+ keystruct.common.rdtype = dns_rdatatype_dnskey; -+ /* -+ * The key data in keystruct is not dynamically allocated. -+ */ -+ keystruct.mctx = NULL; -+ -+ ISC_LINK_INIT(&keystruct.common, link); -+ -+ if (flags > 0xffff) -+ CHECK(ISC_R_RANGE); -+ if (proto > 0xff) -+ CHECK(ISC_R_RANGE); -+ if (alg > 0xff) -+ CHECK(ISC_R_RANGE); -+ -+ keystruct.flags = (isc_uint16_t)flags; -+ keystruct.protocol = (isc_uint8_t)proto; -+ keystruct.algorithm = (isc_uint8_t)alg; -+ -+ isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); -+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); -+ -+ keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); -+ CHECK(isc_base64_decodestring(keystr, &keydatabuf)); -+ isc_buffer_usedregion(&keydatabuf, &r); -+ keystruct.datalen = r.length; -+ keystruct.data = r.base; -+ -+ CHECK(dns_rdata_fromstruct(NULL, -+ keystruct.common.rdclass, -+ keystruct.common.rdtype, -+ &keystruct, &rrdatabuf)); -+ -+ CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in, -+ keyname, &rrdatabuf)); -+ trusted_keys++; -+ -+ cleanup: -+ if (result == DST_R_NOCRYPTO) -+ cfg_obj_log(key, lctx, ISC_LOG_ERROR, "no crypto support"); -+ else if (result == DST_R_UNSUPPORTEDALG) { -+ cfg_obj_log(key, lctx, ISC_LOG_WARNING, -+ "skipping trusted key '%s': %s", -+ keynamestr, isc_result_totext(result)); -+ result = ISC_R_SUCCESS; -+ } else if (result != ISC_R_SUCCESS) { -+ cfg_obj_log(key, lctx, ISC_LOG_ERROR, -+ "failed to add trusted key '%s': %s", -+ keynamestr, isc_result_totext(result)); -+ result = ISC_R_FAILURE; -+ } -+ -+ return (result); -+} -+ -+static isc_result_t -+load_keys(const cfg_obj_t *keys, dns_client_t *client) { -+ const cfg_listelt_t *elt, *elt2; -+ const cfg_obj_t *key, *keylist; -+ isc_result_t result = ISC_R_SUCCESS; -+ -+ for (elt = cfg_list_first(keys); -+ elt != NULL; -+ elt = cfg_list_next(elt)) -+ { -+ keylist = cfg_listelt_value(elt); -+ -+ for (elt2 = cfg_list_first(keylist); -+ elt2 != NULL; -+ elt2 = cfg_list_next(elt2)) -+ { -+ key = cfg_listelt_value(elt2); -+ CHECK(key_fromconfig(key, client)); -+ } -+ } -+ -+ cleanup: -+ if (result == DST_R_NOCRYPTO) -+ result = ISC_R_SUCCESS; -+ return (result); -+} -+ -+static isc_result_t -+setup_dnsseckeys(dns_client_t *client) { -+ isc_result_t result; -+ cfg_parser_t *parser = NULL; -+ const cfg_obj_t *keys = NULL; -+ const cfg_obj_t *managed_keys = NULL; -+ cfg_obj_t *bindkeys = NULL; -+ const char *filename = anchorfile; -+ -+ if (!root_validation && !dlv_validation) -+ return (ISC_R_SUCCESS); -+ -+ if (filename == NULL) -+ filename = SYSCONFDIR "/bind.keys"; -+ -+ if (trust_anchor == NULL) -+ trust_anchor = isc_mem_strdup(mctx, "."); -+ if (dlv_anchor == NULL) -+ dlv_anchor = isc_mem_strdup(mctx, "dlv.isc.org"); -+ -+ CHECK(convert_name(&afn, &anchor_name, trust_anchor)); -+ CHECK(convert_name(&dfn, &dlv_name, dlv_anchor)); -+ -+ CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); -+ -+ if (access(filename, R_OK) != 0) { -+ if (anchorfile != NULL) -+ fatal("Unable to read key file '%s'", anchorfile); -+ } else { -+ result = cfg_parse_file(parser, filename, -+ &cfg_type_bindkeys, &bindkeys); -+ if (result != ISC_R_SUCCESS) -+ if (anchorfile != NULL) -+ fatal("Unable to load keys from '%s'", -+ anchorfile); -+ } -+ -+ if (bindkeys == NULL) { -+ isc_buffer_t b; -+ -+ isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1); -+ isc_buffer_add(&b, sizeof(anchortext) - 1); -+ result = cfg_parse_buffer(parser, &b, &cfg_type_bindkeys, -+ &bindkeys); -+ if (result != ISC_R_SUCCESS) -+ fatal("Unable to parse built-in keys"); -+ } -+ -+ INSIST(bindkeys != NULL); -+ cfg_map_get(bindkeys, "trusted-keys", &keys); -+ cfg_map_get(bindkeys, "managed-keys", &managed_keys); -+ -+ if (keys != NULL) -+ CHECK(load_keys(keys, client)); -+ if (managed_keys != NULL) -+ CHECK(load_keys(managed_keys, client)); -+ result = ISC_R_SUCCESS; -+ -+ if (trusted_keys == 0) -+ fatal("No trusted keys were loaded"); -+ -+ if (dlv_validation) -+ dns_client_setdlv(client, dns_rdataclass_in, dlv_anchor); -+ -+ cleanup: -+ if (result != ISC_R_SUCCESS) -+ delve_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s", -+ isc_result_totext(result)); -+ return (result); -+} -+ -+static isc_result_t -+addserver(dns_client_t *client) { -+ struct addrinfo hints, *res, *cur; -+ int gai_error; -+ struct in_addr in4; -+ struct in6_addr in6; -+ isc_sockaddr_t *sa; -+ isc_sockaddrlist_t servers; -+ isc_uint32_t destport; -+ isc_result_t result; -+ dns_name_t *name = NULL; -+ -+ result = parse_uint(&destport, port, 0xffff, "port"); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't parse port number"); -+ -+ ISC_LIST_INIT(servers); -+ -+ if (use_ipv4 && inet_pton(AF_INET, server, &in4) == 1) { -+ sa = isc_mem_get(mctx, sizeof(*sa)); -+ ISC_LINK_INIT(sa, link); -+ isc_sockaddr_fromin(sa, &in4, destport); -+ ISC_LIST_APPEND(servers, sa, link); -+ } else if (use_ipv6 && inet_pton(AF_INET6, server, &in6) == 1) { -+ sa = isc_mem_get(mctx, sizeof(*sa)); -+ ISC_LINK_INIT(sa, link); -+ isc_sockaddr_fromin6(sa, &in6, destport); -+ ISC_LIST_APPEND(servers, sa, link); -+ } else { -+ memset(&hints, 0, sizeof(hints)); -+ if (!use_ipv6) -+ hints.ai_family = AF_INET; -+ else if (!use_ipv4) -+ hints.ai_family = AF_INET6; -+ else -+ hints.ai_family = AF_UNSPEC; -+ hints.ai_socktype = SOCK_DGRAM; -+ hints.ai_protocol = IPPROTO_UDP; -+ gai_error = getaddrinfo(server, port, &hints, &res); -+ if (gai_error != 0) { -+ delve_log(ISC_LOG_ERROR, -+ "getaddrinfo failed: %s", -+ gai_strerror(gai_error)); -+ return (ISC_R_FAILURE); -+ } -+ -+ for (cur = res; cur != NULL; cur = res->ai_next) { -+ sa = isc_mem_get(mctx, sizeof(*sa)); -+ memset(sa, 0, sizeof(*sa)); -+ ISC_LINK_INIT(sa, link); -+ memmove(&sa->type, res->ai_addr, res->ai_addrlen); -+ sa->length = res->ai_addrlen; -+ ISC_LIST_APPEND(servers, sa, link); -+ freeaddrinfo(res); -+ } -+ } -+ -+ -+ CHECK(dns_client_setservers(client, dns_rdataclass_in, name, &servers)); -+ -+ cleanup: -+ while (!ISC_LIST_EMPTY(servers)) { -+ sa = ISC_LIST_HEAD(servers); -+ ISC_LIST_UNLINK(servers, sa, link); -+ isc_mem_put(mctx, sa, sizeof(*sa)); -+ } -+ -+ if (result != ISC_R_SUCCESS) -+ delve_log(ISC_LOG_ERROR, "addserver: %s", -+ isc_result_totext(result)); -+ -+ return (result); -+} -+ -+static isc_result_t -+findserver(dns_client_t *client) { -+ isc_result_t result; -+ irs_resconf_t *resconf = NULL; -+ isc_sockaddrlist_t *nameservers; -+ isc_sockaddr_t *sa, *next; -+ -+ result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); -+ if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { -+ delve_log(ISC_LOG_ERROR, "irs_resconf_load: %s", -+ isc_result_totext(result)); -+ goto cleanup; -+ } -+ -+ /* Get nameservers from resolv.conf */ -+ nameservers = irs_resconf_getnameservers(resconf); -+ -+ /* Remove nameservers using incompatible protocol family */ -+ for (sa = ISC_LIST_HEAD(*nameservers); sa != NULL; sa = next) { -+ next = ISC_LIST_NEXT(sa, link); -+ if (!use_ipv4 && sa->type.sa.sa_family == AF_INET) { -+ ISC_LIST_UNLINK(*nameservers, sa, link); -+ isc_mem_put(mctx, sa, sizeof(*sa)); -+ } -+ if (!use_ipv6 && sa->type.sa.sa_family == AF_INET6) { -+ ISC_LIST_UNLINK(*nameservers, sa, link); -+ isc_mem_put(mctx, sa, sizeof(*sa)); -+ } -+ } -+ -+ /* None found, use localhost */ -+ if (ISC_LIST_EMPTY(*nameservers)) { -+ isc_uint32_t destport; -+ result = parse_uint(&destport, port, 0xffff, "port"); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't parse port number"); -+ -+ if (use_ipv4) { -+ struct in_addr localhost; -+ localhost.s_addr = htonl(INADDR_LOOPBACK); -+ sa = isc_mem_get(mctx, sizeof(*sa)); -+ if (sa == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup; -+ } -+ isc_sockaddr_fromin(sa, &localhost, destport); -+ -+ ISC_LINK_INIT(sa, link); -+ ISC_LIST_APPEND(*nameservers, sa, link); -+ } -+ -+ if (use_ipv6) { -+ sa = isc_mem_get(mctx, sizeof(*sa)); -+ if (sa == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup; -+ } -+ isc_sockaddr_fromin6(sa, &in6addr_loopback, -+ destport); -+ -+ ISC_LINK_INIT(sa, link); -+ ISC_LIST_APPEND(*nameservers, sa, link); -+ } -+ } -+ -+ result = dns_client_setservers(client, dns_rdataclass_in, NULL, -+ nameservers); -+ if (result != ISC_R_SUCCESS) -+ delve_log(ISC_LOG_ERROR, "dns_client_setservers: %s", -+ isc_result_totext(result)); -+ -+cleanup: -+ if (resconf != NULL) -+ irs_resconf_destroy(&resconf); -+ return (result); -+} -+ -+static char * -+next_token(char **stringp, const char *delim) { -+ char *res; -+ -+ do { -+ res = strsep(stringp, delim); -+ if (res == NULL) -+ break; -+ } while (*res == '\0'); -+ return (res); -+} -+ -+static isc_result_t -+parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, -+ const char *desc) { -+ isc_uint32_t n; -+ isc_result_t result = isc_parse_uint32(&n, value, 10); -+ if (result == ISC_R_SUCCESS && n > max) -+ result = ISC_R_RANGE; -+ if (result != ISC_R_SUCCESS) { -+ printf("invalid %s '%s': %s\n", desc, -+ value, isc_result_totext(result)); -+ return (result); -+ } -+ *uip = n; -+ return (ISC_R_SUCCESS); -+} -+ -+static void -+plus_option(char *option) { -+ isc_result_t result; -+ char option_store[256]; -+ char *cmd, *value, *ptr; -+ isc_boolean_t state = ISC_TRUE; -+ -+ strncpy(option_store, option, sizeof(option_store)); -+ option_store[sizeof(option_store)-1]=0; -+ ptr = option_store; -+ cmd = next_token(&ptr,"="); -+ if (cmd == NULL) { -+ printf(";; Invalid option %s\n", option_store); -+ return; -+ } -+ value = ptr; -+ if (strncasecmp(cmd, "no", 2)==0) { -+ cmd += 2; -+ state = ISC_FALSE; -+ } -+ -+#define FULLCHECK(A) \ -+ do { \ -+ size_t _l = strlen(cmd); \ -+ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ -+ goto invalid_option; \ -+ } while (0) -+ -+ switch (cmd[0]) { -+ case 'a': /* all */ -+ FULLCHECK("all"); -+ showcomments = state; -+ rrcomments = state; -+ showtrust = state; -+ break; -+ case 'c': -+ switch (cmd[1]) { -+ case 'd': /* cdflag */ -+ FULLCHECK("cdflag"); -+ cdflag = state; -+ break; -+ case 'l': /* class */ -+ FULLCHECK("class"); -+ noclass = ISC_TF(!state); -+ break; -+ case 'o': /* comments */ -+ FULLCHECK("comments"); -+ showcomments = state; -+ break; -+ case 'r': /* crypto */ -+ FULLCHECK("crypto"); -+ nocrypto = ISC_TF(!state); -+ break; -+ default: -+ goto invalid_option; -+ } -+ break; -+ case 'd': -+ switch (cmd[1]) { -+ case 'l': /* dlv */ -+ FULLCHECK("dlv"); -+ if (state && no_sigs) -+ break; -+ dlv_validation = state; -+ if (value != NULL) -+ dlv_anchor = isc_mem_strdup(mctx, value); -+ break; -+ case 'n': /* dnssec */ -+ FULLCHECK("dnssec"); -+ showdnssec = state; -+ break; -+ default: -+ goto invalid_option; -+ } -+ break; -+ case 'm': -+ switch (cmd[1]) { -+ case 't': /* mtrace */ -+ message_trace = state; -+ if (state) -+ resolve_trace = state; -+ break; -+ case 'u': /* multiline */ -+ FULLCHECK("multiline"); -+ multiline = state; -+ break; -+ default: -+ goto invalid_option; -+ } -+ break; -+ case 'r': -+ switch (cmd[1]) { -+ case 'o': /* root */ -+ FULLCHECK("root"); -+ if (state && no_sigs) -+ break; -+ root_validation = state; -+ if (value != NULL) -+ trust_anchor = isc_mem_strdup(mctx, value); -+ break; -+ case 'r': /* rrcomments */ -+ FULLCHECK("rrcomments"); -+ rrcomments = state; -+ break; -+ case 't': /* rtrace */ -+ FULLCHECK("rtrace"); -+ resolve_trace = state; -+ break; -+ default: -+ goto invalid_option; -+ } -+ break; -+ case 's': -+ switch (cmd[1]) { -+ case 'h': /* short */ -+ FULLCHECK("short"); -+ short_form = state; -+ if (short_form) { -+ multiline = ISC_FALSE; -+ showcomments = ISC_FALSE; -+ showtrust = ISC_FALSE; -+ showdnssec = ISC_FALSE; -+ } -+ break; -+ case 'p': /* split */ -+ FULLCHECK("split"); -+ if (value != NULL && !state) -+ goto invalid_option; -+ if (!state) { -+ splitwidth = 0; -+ break; -+ } else if (value == NULL) -+ break; -+ -+ result = parse_uint(&splitwidth, value, -+ 1023, "split"); -+ if (splitwidth % 4 != 0) { -+ splitwidth = ((splitwidth + 3) / 4) * 4; -+ warn("split must be a multiple of 4; " -+ "adjusting to %d", splitwidth); -+ } -+ /* -+ * There is an adjustment done in the -+ * totext_() functions which causes -+ * splitwidth to shrink. This is okay when we're -+ * using the default width but incorrect in this -+ * case, so we correct for it -+ */ -+ if (splitwidth) -+ splitwidth += 3; -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't parse split"); -+ break; -+ default: -+ goto invalid_option; -+ } -+ break; -+ case 't': -+ switch (cmd[1]) { -+ case 'r': /* trust */ -+ FULLCHECK("trust"); -+ showtrust = state; -+ break; -+ case 't': /* ttl */ -+ FULLCHECK("ttl"); -+ nottl = ISC_TF(!state); -+ break; -+ default: -+ goto invalid_option; -+ } -+ break; -+ case 'v': /* vtrace */ -+ FULLCHECK("vtrace"); -+ validator_trace = state; -+ if (state) -+ resolve_trace = state; -+ break; -+ default: -+ invalid_option: -+ /* -+ * We can also add a "need_value:" case here if we ever -+ * add a plus-option that requires a specified value -+ */ -+ fprintf(stderr, "Invalid option: +%s\n", option); -+ usage(); -+ } -+ return; -+} -+ -+/* -+ * options: "46a:b:c:d:himp:q:t:vx:"; -+ */ -+static const char *single_dash_opts = "46himv"; -+static isc_boolean_t -+dash_option(char *option, char *next, isc_boolean_t *open_type_class) { -+ char opt, *value; -+ isc_result_t result; -+ isc_boolean_t value_from_next; -+ isc_textregion_t tr; -+ dns_rdatatype_t rdtype; -+ dns_rdataclass_t rdclass; -+ char textname[MAXNAME]; -+ struct in_addr in4; -+ struct in6_addr in6; -+ isc_sockaddr_t a4, a6; -+ in_port_t srcport; -+ isc_uint32_t num; -+ char *hash; -+ -+ while (strpbrk(option, single_dash_opts) == &option[0]) { -+ /* -+ * Since the -[46himv] options do not take an argument, -+ * account for them (in any number and/or combination) -+ * if they appear as the first character(s) of a q-opt. -+ */ -+ opt = option[0]; -+ switch (opt) { -+ case '4': -+ if (isc_net_probeipv4() != ISC_R_SUCCESS) -+ fatal("IPv4 networking not available"); -+ if (use_ipv6) { -+ isc_net_disableipv6(); -+ use_ipv6 = ISC_FALSE; -+ } -+ break; -+ case '6': -+ if (isc_net_probeipv6() != ISC_R_SUCCESS) -+ fatal("IPv6 networking not available"); -+ if (use_ipv4) { -+ isc_net_disableipv4(); -+ use_ipv4 = ISC_FALSE; -+ } -+ break; -+ case 'h': -+ usage(); -+ exit(0); -+ /* NOTREACHED */ -+ case 'i': -+ no_sigs = ISC_TRUE; -+ dlv_validation = ISC_FALSE; -+ root_validation = ISC_FALSE; -+ break; -+ case 'm': -+ /* handled in preparse_args() */ -+ break; -+ case 'v': -+ fputs("delve " VERSION "\n", stderr); -+ exit(0); -+ /* NOTREACHED */ -+ default: -+ INSIST(0); -+ } -+ if (strlen(option) > 1U) -+ option = &option[1]; -+ else -+ return (ISC_FALSE); -+ } -+ opt = option[0]; -+ if (strlen(option) > 1U) { -+ value_from_next = ISC_FALSE; -+ value = &option[1]; -+ } else { -+ value_from_next = ISC_TRUE; -+ value = next; -+ } -+ if (value == NULL) -+ goto invalid_option; -+ switch (opt) { -+ case 'a': -+ anchorfile = isc_mem_strdup(mctx, value); -+ return (value_from_next); -+ case 'b': -+ hash = strchr(value, '#'); -+ if (hash != NULL) { -+ result = parse_uint(&num, hash + 1, 0xffff, "port"); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't parse port number"); -+ srcport = num; -+ *hash = '\0'; -+ } else -+ srcport = 0; -+ -+ if (inet_pton(AF_INET, value, &in4) == 1) { -+ if (srcaddr4 != NULL) -+ fatal("Only one local address per family " -+ "can be specified\n"); -+ isc_sockaddr_fromin(&a4, &in4, srcport); -+ srcaddr4 = &a4; -+ } else if (inet_pton(AF_INET6, value, &in6) == 1) { -+ if (srcaddr6 != NULL) -+ fatal("Only one local address per family " -+ "can be specified\n"); -+ isc_sockaddr_fromin6(&a6, &in6, srcport); -+ srcaddr6 = &a6; -+ } else { -+ if (hash != NULL) -+ *hash = '#'; -+ fatal("Invalid address %s", value); -+ } -+ if (hash != NULL) -+ *hash = '#'; -+ return (value_from_next); -+ case 'c': -+ if (classset) -+ warn("extra query class"); -+ -+ *open_type_class = ISC_FALSE; -+ tr.base = value; -+ tr.length = strlen(value); -+ result = dns_rdataclass_fromtext(&rdclass, -+ (isc_textregion_t *)&tr); -+ if (result == ISC_R_SUCCESS) -+ classset = ISC_TRUE; -+ else if (rdclass != dns_rdataclass_in) -+ warn("ignoring non-IN query class"); -+ else -+ warn("ignoring invalid class"); -+ return (value_from_next); -+ case 'd': -+ result = parse_uint(&num, value, 99, "debug level"); -+ if (result != ISC_R_SUCCESS) -+ fatal("Couldn't parse debug level"); -+ loglevel = num; -+ return (value_from_next); -+ case 'p': -+ port = value; -+ return (value_from_next); -+ case 'q': -+ if (qname != NULL) { -+ warn("extra query name"); -+ isc_mem_free(mctx, qname); -+ } -+ curqname = value; -+ return (value_from_next); -+ case 't': -+ *open_type_class = ISC_FALSE; -+ tr.base = value; -+ tr.length = strlen(value); -+ result = dns_rdatatype_fromtext(&rdtype, -+ (isc_textregion_t *)&tr); -+ if (result == ISC_R_SUCCESS) { -+ if (typeset) -+ warn("extra query type"); -+ if (rdtype == dns_rdatatype_ixfr || -+ rdtype == dns_rdatatype_axfr) -+ fatal("Transfer not supported"); -+ qtype = rdtype; -+ typeset = ISC_TRUE; -+ } else -+ warn("ignoring invalid type"); -+ return (value_from_next); -+ case 'x': -+ result = get_reverse(textname, sizeof(textname), value, -+ ISC_FALSE); -+ if (result == ISC_R_SUCCESS) { -+ if (curqname != NULL) -+ warn("extra query name"); -+ curqname = isc_mem_strdup(mctx, textname); -+ if (typeset) -+ warn("extra query type"); -+ qtype = dns_rdatatype_ptr; -+ typeset = ISC_TRUE; -+ } else { -+ fprintf(stderr, "Invalid IP address %s\n", value); -+ exit(1); -+ } -+ return (value_from_next); -+ invalid_option: -+ default: -+ fprintf(stderr, "Invalid option: -%s\n", option); -+ usage(); -+ } -+ /* NOTREACHED */ -+ return (ISC_FALSE); -+} -+ -+/* -+ * Check for -m first to determine whether to enable -+ * memory debugging when setting up the memory context. -+ */ -+static void -+preparse_args(int argc, char **argv) { -+ char *option; -+ -+ for (argc--, argv++; argc > 0; argc--, argv++) { -+ if (argv[0][0] != '-') -+ continue; -+ option = &argv[0][1]; -+ while (strpbrk(option, single_dash_opts) == &option[0]) { -+ if (option[0] == 'm') { -+ isc_mem_debugging = ISC_MEM_DEBUGTRACE | -+ ISC_MEM_DEBUGRECORD; -+ return; -+ } -+ option = &option[1]; -+ } -+ } -+} -+ -+/* -+ * Argument parsing is based on dig, but simplified: only one -+ * QNAME/QCLASS/QTYPE tuple can be specified, and options have -+ * been removed that aren't applicable to delve. The interface -+ * should be familiar to dig users, however. -+ */ -+static void -+parse_args(int argc, char **argv) { -+ isc_result_t result; -+ isc_textregion_t tr; -+ dns_rdatatype_t rdtype; -+ dns_rdataclass_t rdclass; -+ isc_boolean_t open_type_class = ISC_TRUE; -+ -+ for (; argc > 0; argc--, argv++) { -+ if (argv[0][0] == '@') { -+ server = &argv[0][1]; -+ } else if (argv[0][0] == '+') { -+ plus_option(&argv[0][1]); -+ } else if (argv[0][0] == '-') { -+ if (argc <= 1) { -+ if (dash_option(&argv[0][1], NULL, -+ &open_type_class)) -+ { -+ argc--; -+ argv++; -+ } -+ } else { -+ if (dash_option(&argv[0][1], argv[1], -+ &open_type_class)) -+ { -+ argc--; -+ argv++; -+ } -+ } -+ } else { -+ /* -+ * Anything which isn't an option -+ */ -+ if (open_type_class) { -+ tr.base = argv[0]; -+ tr.length = strlen(argv[0]); -+ result = dns_rdatatype_fromtext(&rdtype, -+ (isc_textregion_t *)&tr); -+ if (result == ISC_R_SUCCESS) { -+ if (typeset) -+ warn("extra query type"); -+ if (rdtype == dns_rdatatype_ixfr || -+ rdtype == dns_rdatatype_axfr) -+ fatal("Transfer not supported"); -+ qtype = rdtype; -+ typeset = ISC_TRUE; -+ continue; -+ } -+ result = dns_rdataclass_fromtext(&rdclass, -+ (isc_textregion_t *)&tr); -+ if (result == ISC_R_SUCCESS) { -+ if (classset) -+ warn("extra query class"); -+ else if (rdclass != dns_rdataclass_in) -+ warn("ignoring non-IN " -+ "query class"); -+ continue; -+ } -+ } -+ -+ if (curqname == NULL) -+ curqname = argv[0]; -+ } -+ } -+ -+ /* -+ * If no qname or qtype specified, search for root/NS -+ * If no qtype specified, use A -+ */ -+ if (!typeset) -+ qtype = dns_rdatatype_a; -+ -+ if (curqname == NULL) { -+ qname = isc_mem_strdup(mctx, "."); -+ if (!typeset) -+ qtype = dns_rdatatype_ns; -+ } else -+ qname = isc_mem_strdup(mctx, curqname); -+} -+ -+static isc_result_t -+append_str(const char *text, int len, char **p, char *end) { -+ if (len > end - *p) -+ return (ISC_R_NOSPACE); -+ memmove(*p, text, len); -+ *p += len; -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+reverse_octets(const char *in, char **p, char *end) { -+ char *dot = strchr(in, '.'); -+ int len; -+ if (dot != NULL) { -+ isc_result_t result; -+ result = reverse_octets(dot + 1, p, end); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ result = append_str(".", 1, p, end); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ len = (int)(dot - in); -+ } else -+ len = strlen(in); -+ return (append_str(in, len, p, end)); -+} -+ -+static isc_result_t -+get_reverse(char *reverse, size_t len, char *value, isc_boolean_t strict) { -+ int r; -+ isc_result_t result; -+ isc_netaddr_t addr; -+ -+ addr.family = AF_INET6; -+ r = inet_pton(AF_INET6, value, &addr.type.in6); -+ if (r > 0) { -+ /* This is a valid IPv6 address. */ -+ dns_fixedname_t fname; -+ dns_name_t *name; -+ unsigned int options = 0; -+ -+ dns_fixedname_init(&fname); -+ name = dns_fixedname_name(&fname); -+ result = dns_byaddr_createptrname2(&addr, options, name); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ dns_name_format(name, reverse, (unsigned int)len); -+ return (ISC_R_SUCCESS); -+ } else { -+ /* -+ * Not a valid IPv6 address. Assume IPv4. -+ * If 'strict' is not set, construct the -+ * in-addr.arpa name by blindly reversing -+ * octets whether or not they look like integers, -+ * so that this can be used for RFC2317 names -+ * and such. -+ */ -+ char *p = reverse; -+ char *end = reverse + len; -+ if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) -+ return (DNS_R_BADDOTTEDQUAD); -+ result = reverse_octets(value, &p, end); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ result = append_str(".in-addr.arpa.", 15, &p, end); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ return (ISC_R_SUCCESS); -+ } -+} -+ -+int -+main(int argc, char *argv[]) { -+ dns_client_t *client = NULL; -+ isc_result_t result; -+ dns_fixedname_t qfn; -+ dns_name_t *query_name, *response_name; -+ dns_rdataset_t *rdataset; -+ dns_namelist_t namelist; -+ unsigned int resopt; -+ isc_appctx_t *actx = NULL; -+ isc_taskmgr_t *taskmgr = NULL; -+ isc_socketmgr_t *socketmgr = NULL; -+ isc_timermgr_t *timermgr = NULL; -+ dns_master_style_t *style = NULL; -+ struct sigaction sa; -+ -+ preparse_args(argc, argv); -+ progname = argv[0]; -+ -+ argc -= optind; -+ argv += optind; -+ -+ isc_lib_register(); -+ result = dns_lib_init(); -+ if (result != ISC_R_SUCCESS) -+ fatal("dns_lib_init failed: %d", result); -+ -+ result = isc_mem_create(0, 0, &mctx); -+ if (result != ISC_R_SUCCESS) -+ fatal("failed to create mctx"); -+ -+ CHECK(isc_appctx_create(mctx, &actx)); -+ CHECK(isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr)); -+ CHECK(isc_socketmgr_createinctx(mctx, actx, &socketmgr)); -+ CHECK(isc_timermgr_createinctx(mctx, actx, &timermgr)); -+ -+ parse_args(argc, argv); -+ -+ CHECK(setup_style(&style)); -+ -+ setup_logging(stderr); -+ -+ CHECK(isc_app_ctxstart(actx)); -+ -+ /* Unblock SIGINT if it's been blocked by isc_app_ctxstart() */ -+ memset(&sa, 0, sizeof(sa)); -+ sa.sa_handler = SIG_DFL; -+ if (sigfillset(&sa.sa_mask) != 0 || sigaction(SIGINT, &sa, NULL) < 0) -+ fatal("Couldn't set up signal handler"); -+ -+ /* Create client */ -+ result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr, -+ 0, &client); -+ if (result != ISC_R_SUCCESS) { -+ delve_log(ISC_LOG_ERROR, "dns_client_create: %s", -+ isc_result_totext(result)); -+ goto cleanup; -+ } -+ -+ /* Set the nameserver */ -+ if (server != NULL) -+ addserver(client); -+ else -+ findserver(client); -+ -+ CHECK(setup_dnsseckeys(client)); -+ -+ /* Construct QNAME */ -+ convert_name(&qfn, &query_name, qname); -+ -+ /* Set up resolution options */ -+ resopt = DNS_CLIENTRESOPT_ALLOWRUN | DNS_CLIENTRESOPT_NOCDFLAG; -+ if (no_sigs) -+ resopt |= DNS_CLIENTRESOPT_NODNSSEC; -+ if (!root_validation && !dlv_validation) -+ resopt |= DNS_CLIENTRESOPT_NOVALIDATE; -+ if (cdflag) -+ resopt &= ~DNS_CLIENTRESOPT_NOCDFLAG; -+ -+ /* Perform resolution */ -+ ISC_LIST_INIT(namelist); -+ result = dns_client_resolve(client, query_name, dns_rdataclass_in, -+ qtype, resopt, &namelist); -+ if (result != ISC_R_SUCCESS) -+ delve_log(ISC_LOG_ERROR, "resolution failed: %s", -+ isc_result_totext(result)); -+ -+ for (response_name = ISC_LIST_HEAD(namelist); -+ response_name != NULL; -+ response_name = ISC_LIST_NEXT(response_name, link)) { -+ for (rdataset = ISC_LIST_HEAD(response_name->list); -+ rdataset != NULL; -+ rdataset = ISC_LIST_NEXT(rdataset, link)) { -+ result = printdata(rdataset, response_name, style); -+ if (result != ISC_R_SUCCESS) -+ delve_log(ISC_LOG_ERROR, "print data failed"); -+ } -+ } -+ -+ dns_client_freeresanswer(client, &namelist); -+ -+cleanup: -+ if (dlv_anchor != NULL) -+ isc_mem_free(mctx, dlv_anchor); -+ if (trust_anchor != NULL) -+ isc_mem_free(mctx, trust_anchor); -+ if (anchorfile != NULL) -+ isc_mem_free(mctx, anchorfile); -+ if (qname != NULL) -+ isc_mem_free(mctx, qname); -+ if (style != NULL) -+ dns_master_styledestroy(&style, mctx); -+ if (client != NULL) -+ dns_client_destroy(&client); -+ if (taskmgr != NULL) -+ isc_taskmgr_destroy(&taskmgr); -+ if (timermgr != NULL) -+ isc_timermgr_destroy(&timermgr); -+ if (socketmgr != NULL) -+ isc_socketmgr_destroy(&socketmgr); -+ if (actx != NULL) -+ isc_appctx_destroy(&actx); -+ if (lctx != NULL) -+ isc_log_destroy(&lctx); -+ isc_mem_detach(&mctx); -+ -+ dns_lib_shutdown(); -+ -+ exit(0); -+} -diff --git a/bin/delve/delve.docbook b/bin/delve/delve.docbook -new file mode 100644 -index 0000000000..12ff996ba4 ---- /dev/null -+++ b/bin/delve/delve.docbook -@@ -0,0 +1,639 @@ -+]> -+ -+ -+ -+ -+ -+ February 12, 2014 -+ -+ -+ -+ delve -+ 1 -+ BIND9 -+ -+ -+ -+ delve -+ DNS lookup and validation utility -+ -+ -+ -+ -+ 2014 -+ Internet Systems Consortium, Inc. ("ISC") -+ -+ -+ -+ -+ -+ delve -+ @server -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ name -+ type -+ class -+ queryopt -+ -+ -+ -+ delve -+ -+ -+ -+ -+ delve -+ queryopt -+ query -+ -+ -+ -+ -+ DESCRIPTION -+ delve -+ (Domain Entity Lookup & Validation Engine) is a tool for sending -+ DNS queries and validating the results, using the the same internal -+ resolver and validator logic as named. -+ -+ -+ delve will send to a specified name server all -+ queries needed to fetch and validate the requested data; this -+ includes the original requested query, subsequent queries to follow -+ CNAME or DNAME chains, and queries for DNSKEY, DS and DLV records -+ to establish a chain of trust for DNSSEC validation. -+ It does not perform iterative resolution, but simulates the -+ behavior of a name server configured for DNSSEC validating and -+ forwarding. -+ -+ -+ By default, responses are validated using built-in DNSSEC trust -+ anchors for the root zone (".") and for the ISC DNSSEC lookaside -+ validation zone ("dlv.isc.org"). Records returned by -+ delve are either fully validated or -+ were not signed. If validation fails, an explanation of -+ the failure is included in the output; the validation process -+ can be traced in detail. Because delve does -+ not rely on an external server to carry out validation, it can -+ be used to check the validity of DNS responses in environments -+ where local name servers may not be trustworthy. -+ -+ -+ Unless it is told to query a specific name server, -+ delve will try each of the servers listed in -+ /etc/resolv.conf. If no usable server -+ addresses are found, delve will send -+ queries to the localhost addresses (127.0.0.1 for IPv4, ::1 -+ for IPv6). -+ -+ -+ When no command line arguments or options are given, -+ delve will perform an NS query for "." -+ (the root zone). -+ -+ -+ -+ -+ SIMPLE USAGE -+ -+ -+ A typical invocation of delve looks like: -+ delve @server name type -+ where: -+ -+ -+ -+ server -+ -+ -+ is the name or IP address of the name server to query. This -+ can be an IPv4 address in dotted-decimal notation or an IPv6 -+ address in colon-delimited notation. When the supplied -+ server argument is a hostname, -+ delve resolves that name before -+ querying that name server (note, however, that this -+ initial lookup is not validated -+ by DNSSEC). -+ -+ -+ If no server argument is -+ provided, delve consults -+ /etc/resolv.conf; if an -+ address is found there, it queries the name server at -+ that address. If either of the or -+ options are in use, then -+ only addresses for the corresponding transport -+ will be tried. If no usable addresses are found, -+ delve will send queries to -+ the localhost addresses (127.0.0.1 for IPv4, -+ ::1 for IPv6). -+ -+ -+ -+ -+ -+ name -+ -+ -+ is the domain name to be looked up. -+ -+ -+ -+ -+ -+ type -+ -+ -+ indicates what type of query is required — -+ ANY, A, MX, etc. -+ type can be any valid query -+ type. If no -+ type argument is supplied, -+ delve will perform a lookup for an -+ A record. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ OPTIONS -+ -+ -+ -a -+ -+ -+ Specifies a file from which to read DNSSEC trust anchors. -+ The default is /etc/bind.keys, which -+ is included with BIND 9 and contains -+ trust anchors for the root zone (".") and for the ISC -+ DNSSEC lookaside validation zone ("dlv.isc.org"). -+ -+ -+ Keys that do not match the root or DLV trust-anchor -+ names are ignored; these key names can be overridden -+ using the or -+ options. -+ -+ -+ Note: When reading the trust anchor file, -+ delve treats -+ statements and statements -+ identically. That is, for a managed key, it is the -+ initial key that is trusted; RFC 5011 -+ key management is not supported. delve -+ will not consult the managed-keys database maintained by -+ named. This means that if either of the -+ keys in /etc/bind.keys is revoked -+ and rolled over, it will be necessary to update -+ /etc/bind.keys to use DNSSEC -+ validation in delve. -+ -+ -+ -+ -+ -+ -b -+ -+ -+ Sets the source IP address of the query to -+ address. This must be a valid address -+ on one of the host's network interfaces or "0.0.0.0" or "::". -+ An optional source port may be specified by appending -+ "#<port>" -+ -+ -+ -+ -+ -+ -c -+ -+ -+ Sets the query class for the requested data. Currently, -+ only class "IN" is supported in delve -+ and any other value is ignored. -+ -+ -+ -+ -+ -+ -i -+ -+ -+ Insecure mode. This disables internal DNSSEC validation. -+ (Note, however, this does not set the CD bit on upstream -+ queries. If the server being queried is performing DNSSEC -+ validation, then it will not return invalid data; this -+ can cause delve to time out. When it -+ is necessary to examine invalid data to debug a DNSSEC -+ problem, use dig +cd.) -+ -+ -+ -+ -+ -+ -m -+ -+ -+ Enables memory usage debugging. -+ -+ -+ -+ -+ -+ -p -+ -+ -+ Specifies a destination port to use for queries instead of -+ the standard DNS port number 53. This option would be used -+ with a name server that has been configured to listen -+ for queries on a non-standard port number. -+ -+ -+ -+ -+ -+ -4 -+ -+ -+ Forces delve to only use IPv4. -+ -+ -+ -+ -+ -+ -6 -+ -+ -+ Forces delve to only use IPv6. -+ -+ -+ -+ -+ -+ -q -+ -+ -+ Sets the query name to name. -+ While the query name can be specified without using the -+ , it is sometimes necessary to disambiguate -+ names from types or classes (for example, when looking up the -+ name "ns", which could be misinterpreted as the type NS, -+ or "ch", which could be misinterpreted as class CH). -+ -+ -+ -+ -+ -+ -t -+ -+ -+ Sets the query type to type, which -+ can be any valid query type supported in BIND 9 except -+ for zone transfer types AXFR and IXFR. As with -+ , this is useful to distinguish -+ query name type or class when they are ambiguous. -+ it is sometimes necessary to disambiguate names from types. -+ -+ -+ The default query type is "A", unless the -+ option is supplied to indicate a reverse lookup, in which case -+ it is "PTR". -+ -+ -+ -+ -+ -+ -x -+ -+ -+ Performs a reverse lookup, mapping an addresses to -+ a name. addr is an IPv4 address in -+ dotted-decimal notation, or a colon-delimited IPv6 address. -+ When is used, there is no need to provide -+ the name or type -+ arguments. delve automatically performs a -+ lookup for a name like 11.12.13.10.in-addr.arpa -+ and sets the query type to PTR. IPv6 addresses are looked up -+ using nibble format under the IP6.ARPA domain. -+ -+ -+ -+ -+ -+ -+ -+ QUERY OPTIONS -+ -+ delve -+ provides a number of query options which affect the way results are -+ displayed, and in some cases the way lookups are performed. -+ -+ -+ -+ Each query option is identified by a keyword preceded by a plus sign -+ (+). Some keywords set or reset an -+ option. These may be preceded by the string -+ no to negate the meaning of that keyword. -+ Other keywords assign values to options like the timeout interval. -+ They have the form . -+ The query options are: -+ -+ -+ -+ -+ -+ -+ Controls whether to set the CD (checking disabled) bit in -+ queries sent by delve. This may be useful -+ when troubleshooting DNSSEC problems from behind a validating -+ resolver. A validating resolver will block invalid responses, -+ making it difficult to retrieve them for analysis. Setting -+ the CD flag on queries will cause the resolver to return -+ invalid responses, which delve can then -+ validate internally and report the errors in detail. -+ -+ -+ -+ -+ -+ -+ -+ -+ Controls whether to display the CLASS when printing -+ a record. The default is to display the CLASS. -+ -+ -+ -+ -+ -+ -+ -+ -+ Controls whether to display the TTL when printing -+ a record. The default is to display the TTL. -+ -+ -+ -+ -+ -+ -+ -+ -+ Toggle resolver fetch logging. This reports the -+ name and type of each query sent by delve -+ in the process of carrying out the resolution and validation -+ process: this includes including the original query and -+ all subsequent queries to follow CNAMEs and to establish a -+ chain of trust for DNSSEC validation. -+ -+ -+ This is equivalent to setting the debug level to 1 in -+ the "resolver" logging category. Setting the systemwide -+ debug level to 1 using the option will -+ product the same output (but will affect other logging -+ categories as well). -+ -+ -+ -+ -+ -+ -+ -+ -+ Toggle message logging. This produces a detailed dump of -+ the responses received by delve in the -+ process of carrying out the resolution and validation process. -+ -+ -+ This is equivalent to setting the debug level to 10 -+ for the the "packets" module of the "resolver" logging -+ category. Setting the systemwide debug level to 10 using -+ the option will produce the same output -+ (but will affect other logging categories as well). -+ -+ -+ -+ -+ -+ -+ -+ -+ Toggle validation logging. This shows the internal -+ process of the validator as it determines whether an -+ answer is validly signed, unsigned, or invalid. -+ -+ -+ This is equivalent to setting the debug level to 3 -+ for the the "validator" module of the "dnssec" logging -+ category. Setting the systemwide debug level to 3 using -+ the option will produce the same output -+ (but will affect other logging categories as well). -+ -+ -+ -+ -+ -+ -+ -+ -+ Provide a terse answer. The default is to print the answer in a -+ verbose form. -+ -+ -+ -+ -+ -+ -+ -+ -+ Toggle the display of comment lines in the output. The default -+ is to print comments. -+ -+ -+ -+ -+ -+ -+ -+ -+ Toggle the display of per-record comments in the output (for -+ example, human-readable key information about DNSKEY records). -+ The default is to print per-record comments. -+ -+ -+ -+ -+ -+ -+ -+ -+ Toggle the display of cryptographic fields in DNSSEC records. -+ The contents of these field are unnecessary to debug most DNSSEC -+ validation failures and removing them makes it easier to see -+ the common failures. The default is to display the fields. -+ When omitted they are replaced by the string "[omitted]" or -+ in the DNSKEY case the key id is displayed as the replacement, -+ e.g. "[ key id = value ]". -+ -+ -+ -+ -+ -+ -+ -+ -+ Controls whether to display the trust level when printing -+ a record. The default is to display the trust level. -+ -+ -+ -+ -+ -+ -+ -+ -+ Split long hex- or base64-formatted fields in resource -+ records into chunks of W characters -+ (where W is rounded up to the nearest -+ multiple of 4). -+ +nosplit or -+ +split=0 causes fields not to be -+ split at all. The default is 56 characters, or 44 characters -+ when multiline mode is active. -+ -+ -+ -+ -+ -+ -+ -+ -+ Set or clear the display options -+ , -+ , and -+ as a group. -+ -+ -+ -+ -+ -+ -+ -+ -+ Print long records (such as RRSIG, DNSKEY, and SOA records) -+ in a verbose multi-line format with human-readable comments. -+ The default is to print each record on a single line, to -+ facilitate machine parsing of the delve -+ output. -+ -+ -+ -+ -+ -+ -+ -+ -+ Indicates whether to display RRSIG records in the -+ delve output. The default is to -+ do so. Note that (unlike in dig) -+ this does not control whether to -+ request DNSSEC records or whether to validate them. -+ DNSSEC records are always requested, and validation -+ will always occur unless suppressed by the use of -+ or and -+ . -+ -+ -+ -+ -+ -+ -+ -+ -+ Indicates whether to perform conventional (non- -+ lookaside) DNSSEC validation, and if so, specifies the -+ name of a trust anchor. The default is to validate using -+ a trust anchor of "." (the root zone), for which there is -+ a built-in key. If specifying a different trust anchor, -+ then must be used to specify a file -+ containing the key. -+ -+ -+ -+ -+ -+ -+ -+ -+ Indicates whether to perform DNSSEC lookaside validation, -+ and if so, specifies the name of the DLV trust anchor. -+ The default is to perform lookaside validation using -+ a trust anchor of "dlv.isc.org", for which there is a -+ built-in key. If specifying a different name, then -+ must be used to specify a file -+ containing the DLV key. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ FILES -+ /etc/bind.keys -+ /etc/resolv.conf -+ -+ -+ -+ SEE ALSO -+ -+ dig1 -+ , -+ -+ named8 -+ , -+ RFC4034, -+ RFC4035, -+ RFC4431, -+ RFC5074, -+ RFC5155. -+ -+ -+ -diff --git a/bin/delve/delve.html b/bin/delve/delve.html -new file mode 100644 -index 0000000000..34c30d2cdd ---- /dev/null -+++ b/bin/delve/delve.html -@@ -0,0 +1,445 @@ -+ -+ -+ -+ -+ -+delve -+ -+ -+
-+
-+
-+

Name

-+

delve — DNS lookup and validation utility

-+
-+
-+

Synopsis

-+

delve [@server] [-4] [-6] [-a anchor-file] [-b address] [-c class] [-d level] [-i] [-m] [-p port#] [-q name] [-t type] [-x addr] [name] [type] [class] [queryopt...]

-+

delve [-h]

-+

delve [queryopt...] [query...]

-+
-+
-+

DESCRIPTION

-+

delve -+ (Domain Entity Lookup & Validation Engine) is a tool for sending -+ DNS queries and validating the results, using the the same internal -+ resolver and validator logic as named. -+

-+

-+ delve will send to a specified name server all -+ queries needed to fetch and validate the requested data; this -+ includes the original requested query, subsequent queries to follow -+ CNAME or DNAME chains, and queries for DNSKEY, DS and DLV records -+ to establish a chain of trust for DNSSEC validation. -+ It does not perform iterative resolution, but simulates the -+ behavior of a name server configured for DNSSEC validating and -+ forwarding. -+

-+

-+ By default, responses are validated using built-in DNSSEC trust -+ anchors for the root zone (".") and for the ISC DNSSEC lookaside -+ validation zone ("dlv.isc.org"). Records returned by -+ delve are either fully validated or -+ were not signed. If validation fails, an explanation of -+ the failure is included in the output; the validation process -+ can be traced in detail. Because delve does -+ not rely on an external server to carry out validation, it can -+ be used to check the validity of DNS responses in environments -+ where local name servers may not be trustworthy. -+

-+

-+ Unless it is told to query a specific name server, -+ delve will try each of the servers listed in -+ /etc/resolv.conf. If no usable server -+ addresses are found, delve will send -+ queries to the localhost addresses (127.0.0.1 for IPv4, ::1 -+ for IPv6). -+

-+

-+ When no command line arguments or options are given, -+ delve will perform an NS query for "." -+ (the root zone). -+

-+
-+
-+

SIMPLE USAGE

-+

-+ A typical invocation of delve looks like: -+

-+
 delve @server name type 
-+

-+ where: -+ -+

-+
-+
server
-+
-+

-+ is the name or IP address of the name server to query. This -+ can be an IPv4 address in dotted-decimal notation or an IPv6 -+ address in colon-delimited notation. When the supplied -+ server argument is a hostname, -+ delve resolves that name before -+ querying that name server (note, however, that this -+ initial lookup is not validated -+ by DNSSEC). -+

-+

-+ If no server argument is -+ provided, delve consults -+ /etc/resolv.conf; if an -+ address is found there, it queries the name server at -+ that address. If either of the -4 or -+ -6 options are in use, then -+ only addresses for the corresponding transport -+ will be tried. If no usable addresses are found, -+ delve will send queries to -+ the localhost addresses (127.0.0.1 for IPv4, -+ ::1 for IPv6). -+

-+
-+
name
-+

-+ is the domain name to be looked up. -+

-+
type
-+

-+ indicates what type of query is required — -+ ANY, A, MX, etc. -+ type can be any valid query -+ type. If no -+ type argument is supplied, -+ delve will perform a lookup for an -+ A record. -+

-+
-+

-+

-+
-+
-+

OPTIONS

-+
-+
-a
-+
-+

-+ Specifies a file from which to read DNSSEC trust anchors. -+ The default is /etc/bind.keys, which -+ is included with BIND 9 and contains -+ trust anchors for the root zone (".") and for the ISC -+ DNSSEC lookaside validation zone ("dlv.isc.org"). -+

-+

-+ Keys that do not match the root or DLV trust-anchor -+ names are ignored; these key names can be overridden -+ using the +dlv=NAME or -+ +root=NAME options. -+

-+

-+ Note: When reading the trust anchor file, -+ delve treats managed-keys -+ statements and trusted-keys statements -+ identically. That is, for a managed key, it is the -+ initial key that is trusted; RFC 5011 -+ key management is not supported. delve -+ will not consult the managed-keys database maintained by -+ named. This means that if either of the -+ keys in /etc/bind.keys is revoked -+ and rolled over, it will be necessary to update -+ /etc/bind.keys to use DNSSEC -+ validation in delve. -+

-+
-+
-b
-+

-+ Sets the source IP address of the query to -+ address. This must be a valid address -+ on one of the host's network interfaces or "0.0.0.0" or "::". -+ An optional source port may be specified by appending -+ "#<port>" -+

-+
-c
-+

-+ Sets the query class for the requested data. Currently, -+ only class "IN" is supported in delve -+ and any other value is ignored. -+

-+
-i
-+

-+ Insecure mode. This disables internal DNSSEC validation. -+ (Note, however, this does not set the CD bit on upstream -+ queries. If the server being queried is performing DNSSEC -+ validation, then it will not return invalid data; this -+ can cause delve to time out. When it -+ is necessary to examine invalid data to debug a DNSSEC -+ problem, use dig +cd.) -+

-+
-m
-+

-+ Enables memory usage debugging. -+

-+
-p
-+

-+ Specifies a destination port to use for queries instead of -+ the standard DNS port number 53. This option would be used -+ with a name server that has been configured to listen -+ for queries on a non-standard port number. -+

-+
-4
-+

-+ Forces delve to only use IPv4. -+

-+
-6
-+

-+ Forces delve to only use IPv6. -+

-+
-q
-+

-+ Sets the query name to name. -+ While the query name can be specified without using the -+ -q, it is sometimes necessary to disambiguate -+ names from types or classes (for example, when looking up the -+ name "ns", which could be misinterpreted as the type NS, -+ or "ch", which could be misinterpreted as class CH). -+

-+
-t
-+
-+

-+ Sets the query type to type, which -+ can be any valid query type supported in BIND 9 except -+ for zone transfer types AXFR and IXFR. As with -+ -q, this is useful to distinguish -+ query name type or class when they are ambiguous. -+ it is sometimes necessary to disambiguate names from types. -+

-+

-+ The default query type is "A", unless the -x -+ option is supplied to indicate a reverse lookup, in which case -+ it is "PTR". -+

-+
-+
-x
-+

-+ Performs a reverse lookup, mapping an addresses to -+ a name. addr is an IPv4 address in -+ dotted-decimal notation, or a colon-delimited IPv6 address. -+ When -x is used, there is no need to provide -+ the name or type -+ arguments. delve automatically performs a -+ lookup for a name like 11.12.13.10.in-addr.arpa -+ and sets the query type to PTR. IPv6 addresses are looked up -+ using nibble format under the IP6.ARPA domain. -+

-+
-+
-+
-+

QUERY OPTIONS

-+

delve -+ provides a number of query options which affect the way results are -+ displayed, and in some cases the way lookups are performed. -+

-+

-+ Each query option is identified by a keyword preceded by a plus sign -+ (+). Some keywords set or reset an -+ option. These may be preceded by the string -+ no to negate the meaning of that keyword. -+ Other keywords assign values to options like the timeout interval. -+ They have the form +keyword=value. -+ The query options are: -+ -+

-+
-+
+[no]cdflag
-+

-+ Controls whether to set the CD (checking disabled) bit in -+ queries sent by delve. This may be useful -+ when troubleshooting DNSSEC problems from behind a validating -+ resolver. A validating resolver will block invalid responses, -+ making it difficult to retrieve them for analysis. Setting -+ the CD flag on queries will cause the resolver to return -+ invalid responses, which delve can then -+ validate internally and report the errors in detail. -+

-+
+[no]class
-+

-+ Controls whether to display the CLASS when printing -+ a record. The default is to display the CLASS. -+

-+
+[no]ttl
-+

-+ Controls whether to display the TTL when printing -+ a record. The default is to display the TTL. -+

-+
+[no]rtrace
-+
-+

-+ Toggle resolver fetch logging. This reports the -+ name and type of each query sent by delve -+ in the process of carrying out the resolution and validation -+ process: this includes including the original query and -+ all subsequent queries to follow CNAMEs and to establish a -+ chain of trust for DNSSEC validation. -+

-+

-+ This is equivalent to setting the debug level to 1 in -+ the "resolver" logging category. Setting the systemwide -+ debug level to 1 using the -d option will -+ product the same output (but will affect other logging -+ categories as well). -+

-+
-+
+[no]mtrace
-+
-+

-+ Toggle message logging. This produces a detailed dump of -+ the responses received by delve in the -+ process of carrying out the resolution and validation process. -+

-+

-+ This is equivalent to setting the debug level to 10 -+ for the the "packets" module of the "resolver" logging -+ category. Setting the systemwide debug level to 10 using -+ the -d option will produce the same output -+ (but will affect other logging categories as well). -+

-+
-+
+[no]vtrace
-+
-+

-+ Toggle validation logging. This shows the internal -+ process of the validator as it determines whether an -+ answer is validly signed, unsigned, or invalid. -+

-+

-+ This is equivalent to setting the debug level to 3 -+ for the the "validator" module of the "dnssec" logging -+ category. Setting the systemwide debug level to 3 using -+ the -d option will produce the same output -+ (but will affect other logging categories as well). -+

-+
-+
+[no]short
-+

-+ Provide a terse answer. The default is to print the answer in a -+ verbose form. -+

-+
+[no]comments
-+

-+ Toggle the display of comment lines in the output. The default -+ is to print comments. -+

-+
+[no]rrcomments
-+

-+ Toggle the display of per-record comments in the output (for -+ example, human-readable key information about DNSKEY records). -+ The default is to print per-record comments. -+

-+
+[no]crypto
-+

-+ Toggle the display of cryptographic fields in DNSSEC records. -+ The contents of these field are unnecessary to debug most DNSSEC -+ validation failures and removing them makes it easier to see -+ the common failures. The default is to display the fields. -+ When omitted they are replaced by the string "[omitted]" or -+ in the DNSKEY case the key id is displayed as the replacement, -+ e.g. "[ key id = value ]". -+

-+
+[no]trust
-+

-+ Controls whether to display the trust level when printing -+ a record. The default is to display the trust level. -+

-+
+[no]split[=W]
-+

-+ Split long hex- or base64-formatted fields in resource -+ records into chunks of W characters -+ (where W is rounded up to the nearest -+ multiple of 4). -+ +nosplit or -+ +split=0 causes fields not to be -+ split at all. The default is 56 characters, or 44 characters -+ when multiline mode is active. -+

-+
+[no]all
-+

-+ Set or clear the display options -+ +[no]comments, -+ +[no]rrcomments, and -+ +[no]trust as a group. -+

-+
+[no]multiline
-+

-+ Print long records (such as RRSIG, DNSKEY, and SOA records) -+ in a verbose multi-line format with human-readable comments. -+ The default is to print each record on a single line, to -+ facilitate machine parsing of the delve -+ output. -+

-+
+[no]dnssec
-+

-+ Indicates whether to display RRSIG records in the -+ delve output. The default is to -+ do so. Note that (unlike in dig) -+ this does not control whether to -+ request DNSSEC records or whether to validate them. -+ DNSSEC records are always requested, and validation -+ will always occur unless suppressed by the use of -+ -i or +noroot and -+ +nodlv. -+

-+
+[no]root[=ROOT]
-+

-+ Indicates whether to perform conventional (non- -+ lookaside) DNSSEC validation, and if so, specifies the -+ name of a trust anchor. The default is to validate using -+ a trust anchor of "." (the root zone), for which there is -+ a built-in key. If specifying a different trust anchor, -+ then -a must be used to specify a file -+ containing the key. -+

-+
+[no]dlv[=DLV]
-+

-+ Indicates whether to perform DNSSEC lookaside validation, -+ and if so, specifies the name of the DLV trust anchor. -+ The default is to perform lookaside validation using -+ a trust anchor of "dlv.isc.org", for which there is a -+ built-in key. If specifying a different name, then -+ -a must be used to specify a file -+ containing the DLV key. -+

-+
-+

-+ -+

-+
-+
-+

FILES

-+

/etc/bind.keys

-+

/etc/resolv.conf

-+
-+
-+

SEE ALSO

-+

dig(1), -+ named(8), -+ RFC4034, -+ RFC4035, -+ RFC4431, -+ RFC5074, -+ RFC5155. -+

-+
-+
-+ -diff --git a/bin/named/config.c b/bin/named/config.c -index b43c0fcb0e..818ed3797a 100644 ---- a/bin/named/config.c -+++ b/bin/named/config.c -@@ -78,6 +78,8 @@ options {\n\ - memstatistics-file \"named.memstats\";\n\ - multiple-cnames no;\n\ - # named-xfer ;\n\ -+ nta-lifetime 3600;\n\ -+ nta-recheck 300;\n\ - # pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\ - bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\ - port 53;\n\ -diff --git a/bin/named/control.c b/bin/named/control.c -index 86fa691bd2..7a8e71f19b 100644 ---- a/bin/named/control.c -+++ b/bin/named/control.c -@@ -210,6 +210,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { - result = ns_server_del_zone(ns_g_server, command); - } else if (command_compare(command, NS_COMMAND_SIGNING)) { - result = ns_server_signing(ns_g_server, command, text); -+ } else if (command_compare(command, NS_COMMAND_NTA)) { -+ result = ns_server_nta(ns_g_server, command, text); - } else { - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, -diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h -index 52ed583a5a..1c8275477f 100644 ---- a/bin/named/include/named/control.h -+++ b/bin/named/include/named/control.h -@@ -66,6 +66,7 @@ - #define NS_COMMAND_DELZONE "delzone" - #define NS_COMMAND_SYNC "sync" - #define NS_COMMAND_SIGNING "signing" -+#define NS_COMMAND_NTA "nta" - - isc_result_t - ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp); -diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h -index 83622f406a..0107b51e08 100644 ---- a/bin/named/include/named/server.h -+++ b/bin/named/include/named/server.h -@@ -251,6 +251,18 @@ ns_server_togglequerylog(ns_server_t *server, char *args); - * but can also be used as a toggle for backward comptibility.) - */ - -+/*% -+ * Save the current NTAs for all views to files. -+ */ -+isc_result_t -+ns_server_saventa(ns_server_t *server); -+ -+/*% -+ * Load NTAs for all views from files. -+ */ -+isc_result_t -+ns_server_loadnta(ns_server_t *server); -+ - /*% - * Dump the current statistics to the statistics file. - */ -@@ -365,4 +377,11 @@ ns_server_del_zone(ns_server_t *server, char *args); - */ - isc_result_t - ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text); -+ -+/*% -+ * Adds a Negative Trust Anchor (NTA) for a specified name and -+ * duration, in a particular view if specified, or in all views. -+ */ -+isc_result_t -+ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text); - #endif /* NAMED_SERVER_H */ -diff --git a/bin/named/server.c b/bin/named/server.c -index a00cf1596a..0c297049ed 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -73,6 +73,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -89,6 +90,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -812,6 +814,14 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, - return (ISC_R_UNEXPECTED); - } - -+ result = dns_view_initntatable(view, ns_g_taskmgr, ns_g_timermgr); -+ if (result != ISC_R_SUCCESS) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR, -+ "couldn't create NTA table"); -+ return (ISC_R_UNEXPECTED); -+ } -+ - if (auto_dlv && view->rdclass == dns_rdataclass_in) { - const cfg_obj_t *builtin_keys = NULL; - const cfg_obj_t *builtin_managed_keys = NULL; -@@ -3263,6 +3273,16 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - if (result == ISC_R_SUCCESS) - CHECK(mustbesecure(obj, view->resolver)); - -+ obj = NULL; -+ result = ns_config_get(maps, "nta-recheck", &obj); -+ INSIST(result == ISC_R_SUCCESS); -+ view->nta_recheck = cfg_obj_asuint32(obj); -+ -+ obj = NULL; -+ result = ns_config_get(maps, "nta-lifetime", &obj); -+ INSIST(result == ISC_R_SUCCESS); -+ view->nta_lifetime = cfg_obj_asuint32(obj); -+ - obj = NULL; - result = ns_config_get(maps, "preferred-glue", &obj); - if (result == ISC_R_SUCCESS) { -@@ -3348,6 +3368,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - } else { - empty_zones_enable = ISC_FALSE; - } -+ - if (empty_zones_enable && !lwresd_g_useresolvconf) { - const char *empty; - int empty_zone = 0; -@@ -5069,9 +5090,10 @@ load_configuration(const char *filename, ns_server_t *server, - maps[i] = NULL; - - /* -- * If bind.keys exists, load it. If "dnssec-lookaside auto" -- * is turned on, the keys found there will be used as default -- * trust anchors. -+ * If bind.keys exists, load it. If "dnssec-validation auto" -+ * is turned on, the root key found there will be used as a -+ * default trust anchor, and if "dnssec-lookaside auto" is -+ * turned on, then the DLV key found there will too. - */ - obj = NULL; - result = ns_config_get(maps, "bindkeys-file", &obj); -@@ -5852,6 +5874,8 @@ load_configuration(const char *filename, ns_server_t *server, - server->flushonshutdown = ISC_FALSE; - } - -+ (void) ns_server_loadnta(server); -+ - result = ISC_R_SUCCESS; - - cleanup: -@@ -6147,6 +6171,8 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { - cfg_obj_destroy(ns_g_parser, &ns_g_config); - cfg_parser_destroy(&ns_g_parser); - -+ (void) ns_server_saventa(server); -+ - for (view = ISC_LIST_HEAD(server->viewlist); - view != NULL; - view = view_next) { -@@ -7297,6 +7323,7 @@ isc_result_t - ns_server_dumpsecroots(ns_server_t *server, char *args) { - dns_view_t *view; - dns_keytable_t *secroots = NULL; -+ dns_ntatable_t *ntatable = NULL; - isc_result_t result; - char *ptr; - FILE *fp = NULL; -@@ -7330,11 +7357,25 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) { - result = ISC_R_SUCCESS; - continue; - } -- fprintf(fp, "\n Start view %s\n\n", view->name); -+ fprintf(fp, "\n Start view %s\n", view->name); -+ fprintf(fp, " Secure roots:\n\n"); - result = dns_keytable_dump(secroots, fp); - if (result != ISC_R_SUCCESS) - fprintf(fp, " dumpsecroots failed: %s\n", - isc_result_totext(result)); -+ -+ if (ntatable != NULL) -+ dns_ntatable_detach(&ntatable); -+ result = dns_view_getntatable(view, &ntatable); -+ if (result == ISC_R_NOTFOUND) { -+ result = ISC_R_SUCCESS; -+ continue; -+ } -+ fprintf(fp, "\n Negative trust anchors:\n\n"); -+ result = dns_ntatable_dump(ntatable, fp); -+ if (result != ISC_R_SUCCESS) -+ fprintf(fp, " dumpntatable failed: %s\n", -+ isc_result_totext(result)); - } - if (ptr != NULL) - ptr = next_token(&args, " \t"); -@@ -7343,6 +7384,8 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) { - cleanup: - if (secroots != NULL) - dns_keytable_detach(&secroots); -+ if (ntatable != NULL) -+ dns_ntatable_detach(&ntatable); - if (fp != NULL) - (void)isc_stdio_close(fp); - if (result == ISC_R_SUCCESS) -@@ -8800,3 +8843,295 @@ ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text) { - - return (result); - } -+ -+static isc_result_t -+putstr(isc_buffer_t *b, const char *str) { -+ unsigned int l = strlen(str); -+ -+ /* -+ * Use >= to leave space for NUL termination. -+ */ -+ if (l >= isc_buffer_availablelength(b)) -+ return (ISC_R_NOSPACE); -+ -+ isc_buffer_putmem(b, (const unsigned char *)str, l); -+ return (ISC_R_SUCCESS); -+} -+ -+static inline isc_boolean_t -+argcheck(char *cmd, const char *full) { -+ size_t l; -+ -+ if (cmd == NULL || cmd[0] != '-') -+ return (ISC_FALSE); -+ -+ cmd++; -+ l = strlen(cmd); -+ if (l > strlen(full) || strncasecmp(cmd, full, l) != 0) -+ return (ISC_FALSE); -+ -+ return (ISC_TRUE); -+} -+ -+isc_result_t -+ns_server_nta(ns_server_t *server, char *args, isc_buffer_t *text) { -+ dns_view_t *view; -+ dns_ntatable_t *ntatable = NULL; -+ isc_result_t result; -+ char *ptr, *nametext = NULL, *viewname; -+ isc_stdtime_t now, when; -+ isc_time_t t; -+ char tbuf[64]; -+ const char *msg = NULL; -+ isc_boolean_t dump = ISC_FALSE, force = ISC_FALSE; -+ dns_fixedname_t fn; -+ dns_name_t *ntaname; -+ dns_ttl_t ntattl; -+ isc_boolean_t ttlset = ISC_FALSE, excl = ISC_FALSE; -+ -+ UNUSED(force); -+ -+ dns_fixedname_init(&fn); -+ ntaname = dns_fixedname_name(&fn); -+ -+ /* Skip the command name. */ -+ ptr = next_token(&args, " \t"); -+ if (ptr == NULL) -+ return (ISC_R_UNEXPECTEDEND); -+ -+ for (;;) { -+ /* Check for options */ -+ ptr = next_token(&args, " \t"); -+ if (ptr == NULL) -+ return (ISC_R_UNEXPECTEDEND); -+ -+ if (argcheck(ptr, "dump")) -+ dump = ISC_TRUE; -+ else if (argcheck(ptr, "remove")) { -+ ntattl = 0; -+ ttlset = ISC_TRUE; -+ } else if (argcheck(ptr, "force")) { -+ force = ISC_TRUE; -+ continue; -+ } else if (argcheck(ptr, "lifetime")) { -+ isc_textregion_t tr; -+ -+ ptr = next_token(&args, " \t"); -+ if (ptr == NULL) { -+ msg = "No lifetime specified"; -+ CHECK(ISC_R_UNEXPECTEDEND); -+ } -+ -+ tr.base = ptr; -+ tr.length = strlen(ptr); -+ result = dns_ttl_fromtext(&tr, &ntattl); -+ if (result != ISC_R_SUCCESS) { -+ msg = "could not parse NTA lifetime"; -+ CHECK(result); -+ } -+ -+ if (ntattl > 604800) { -+ msg = "NTA lifetime cannot exceed one week"; -+ CHECK(ISC_R_RANGE); -+ } -+ -+ ttlset = ISC_TRUE; -+ continue; -+ } else -+ nametext = ptr; -+ -+ break; -+ } -+ -+ /* -+ * If -dump was specified, list NTA's and return -+ */ -+ if (dump) { -+ for (view = ISC_LIST_HEAD(server->viewlist); -+ view != NULL; -+ view = ISC_LIST_NEXT(view, link)) -+ { -+ if (ntatable != NULL) -+ dns_ntatable_detach(&ntatable); -+ result = dns_view_getntatable(view, &ntatable); -+ if (result == ISC_R_NOTFOUND) { -+ result = ISC_R_SUCCESS; -+ continue; -+ } -+ CHECK(dns_ntatable_totext(ntatable, text)); -+ } -+ -+ goto cleanup; -+ } -+ -+ /* Get the NTA name. */ -+ if (nametext == NULL) -+ nametext = next_token(&args, " \t"); -+ if (nametext == NULL) -+ return (ISC_R_UNEXPECTEDEND); -+ -+ if (strcmp(nametext, ".") == 0) -+ ntaname = dns_rootname; -+ else { -+ isc_buffer_t b; -+ isc_buffer_init(&b, nametext, strlen(nametext)); -+ isc_buffer_add(&b, strlen(nametext)); -+ CHECK(dns_name_fromtext(ntaname, &b, dns_rootname, 0, NULL)); -+ } -+ -+ /* Look for the view name. */ -+ viewname = next_token(&args, " \t"); -+ -+ isc_stdtime_get(&now); -+ -+ result = isc_task_beginexclusive(server->task); -+ RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ excl = ISC_TRUE; -+ for (view = ISC_LIST_HEAD(server->viewlist); -+ view != NULL; -+ view = ISC_LIST_NEXT(view, link)) -+ { -+ if (viewname != NULL && -+ strcmp(view->name, viewname) != 0) -+ continue; -+ -+ if (view->nta_lifetime == 0) -+ continue; -+ -+ if (!ttlset) -+ ntattl = view->nta_lifetime; -+ -+ if (ntatable != NULL) -+ dns_ntatable_detach(&ntatable); -+ -+ result = dns_view_getntatable(view, &ntatable); -+ if (result == ISC_R_NOTFOUND) { -+ result = ISC_R_SUCCESS; -+ continue; -+ } -+ -+ result = dns_view_flushnode(view, ntaname, ISC_TRUE); -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_INFO, -+ "flush tree '%s' in cache view '%s': %s", -+ nametext, view->name, -+ isc_result_totext(result)); -+ -+ if (ntattl != 0) { -+ CHECK(dns_ntatable_add(ntatable, ntaname, -+ force, now, ntattl)); -+ -+ when = now + ntattl; -+ isc_time_set(&t, when, 0); -+ isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); -+ -+ CHECK(putstr(text, "Negative trust anchor added: ")); -+ CHECK(putstr(text, nametext)); -+ CHECK(putstr(text, "/")); -+ CHECK(putstr(text, view->name)); -+ CHECK(putstr(text, ", expires ")); -+ CHECK(putstr(text, tbuf)); -+ -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_INFO, -+ "added NTA '%s' (%d sec) in view '%s'", -+ nametext, ntattl, view->name); -+ } else { -+ CHECK(dns_ntatable_delete(ntatable, ntaname)); -+ -+ CHECK(putstr(text, "Negative trust anchor removed: ")); -+ CHECK(putstr(text, nametext)); -+ CHECK(putstr(text, "/")); -+ CHECK(putstr(text, view->name)); -+ -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_INFO, -+ "removed NTA '%s' in view %s", -+ nametext, view->name); -+ } -+ -+ if (isc_buffer_availablelength(text) == 0) -+ return (ISC_R_NOSPACE); -+ result = dns_view_saventa(view); -+ if (result != ISC_R_SUCCESS) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR, -+ "error writing NTA file " -+ "for view '%s': %s", -+ view->name, isc_result_totext(result)); -+ } -+ -+ -+ -+ isc_buffer_putuint8(text, 0); -+ } -+ cleanup: -+ if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) -+ isc_buffer_putstr(text, msg); -+ if (excl) -+ isc_task_endexclusive(server->task); -+ -+ if (ntatable != NULL) -+ dns_ntatable_detach(&ntatable); -+ return (result); -+} -+ -+isc_result_t -+ns_server_saventa(ns_server_t *server) { -+ dns_view_t *view; -+ -+ for (view = ISC_LIST_HEAD(server->viewlist); -+ view != NULL; -+ view = ISC_LIST_NEXT(view, link)) -+ { -+ isc_result_t result = dns_view_saventa(view); -+ -+ if (result != ISC_R_SUCCESS) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR, -+ "error writing NTA file '%s' " -+ "for view '%s': %s", -+ view->nta_file, view->name, -+ isc_result_totext(result)); -+ } else { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), -+ "written NTA file '%s' for view '%s'", -+ view->nta_file, view->name); -+ } -+ -+ } -+ -+ return (ISC_R_SUCCESS); -+} -+ -+isc_result_t -+ns_server_loadnta(ns_server_t *server) { -+ dns_view_t *view; -+ -+ for (view = ISC_LIST_HEAD(server->viewlist); -+ view != NULL; -+ view = ISC_LIST_NEXT(view, link)) -+ { -+ isc_result_t result = dns_view_loadnta(view); -+ -+ if ((result != ISC_R_SUCCESS) && -+ (result != ISC_R_FILENOTFOUND) && -+ (result != ISC_R_NOTFOUND)) -+ { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR, -+ "error loading NTA file '%s' " -+ "for view '%s': %s", -+ view->nta_file, view->name, -+ isc_result_totext(result)); -+ } else if (result == ISC_R_SUCCESS) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), -+ "loaded NTA file '%s' for view '%s'", -+ view->nta_file, view->name); -+ } -+ } -+ -+ return (ISC_R_SUCCESS); -+} -diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c -index c67223bbbb..81e629f15c 100644 ---- a/bin/rndc/rndc.c -+++ b/bin/rndc/rndc.c -@@ -157,6 +157,18 @@ command is one of the following:\n\ - Delete a TKEY-negotiated TSIG key.\n\ - validation newstate [view]\n\ - Enable / disable DNSSEC validation.\n\ -+ nta [-lifetime duration] [-force] domain [view]\n\ -+ Set a negative trust anchor, disabling DNSSEC validation\n\ -+ for the given domain.\n\ -+ Using -lifetime specifies the duration of the NTA, up\n\ -+ to one day.\n\ -+ Using -force prevents the NTA from expiring before its\n\ -+ full lifetime, even if the domain can validate sooner.\n\ -+ nta -remove domain [view]\n\ -+ Remove a negative trust anchor, re-enabling validation\n\ -+ for the given domain.\n\ -+ nta -dump\n\ -+ List all negative trust anchors.\n\ - addzone [\"file\"] zone [class [view]] { zone-options }\n\ - Add zone to given view. Requires new-zone-file option.\n\ - delzone [\"file\"] zone [class [view]]\n\ -diff --git a/bin/rndc/rndc.docbook b/bin/rndc/rndc.docbook -index ac2e54d98d..3c2061e26f 100644 ---- a/bin/rndc/rndc.docbook -+++ b/bin/rndc/rndc.docbook -@@ -427,10 +427,9 @@ - secroots view ... - - -- Dump the server's security roots to the secroots -- file for the specified views. If no view is -- specified, security roots for all -- views are dumped. -+ Dump the server's security roots and negative trust anchors -+ to the secroots file for the specified views. If no view is -+ specified, all views are dumped. - - -
-@@ -561,6 +560,81 @@ -
-
- -+ -+ nta -+ ( -d | -f | -r | -l duration) -+ domain -+ view -+ -+ -+ -+ Sets a DNSSEC negative trust anchor (NTA) -+ for , with a lifetime of -+ . The default lifetime is -+ configured in named.conf via the -+ , and defaults to -+ one hour. The lifetime cannot exceed one week. -+ -+ -+ A negative trust anchor selectively disables -+ DNSSEC validation for zones that known to be -+ failing because of misconfiguration rather than -+ an attack. When data to be validated is -+ at or below an active NTA (and above any other -+ configured trust anchors), named will -+ abort the DNSSEC validation process and treat the data as -+ insecure rather than bogus. This continues until the -+ NTA's lifetime is elapsed. -+ -+ -+ NTAs persist across restarts of the named server. -+ The NTAs for a view are saved in a file called -+ name.nta, -+ where name is the -+ name of the view, or if it contains characters -+ that are incompatible with use as a file name, a -+ cryptographic hash generated from the name -+ of the view. -+ -+ -+ An existing NTA can be removed by using the -+ option. -+ -+ -+ An NTA's lifetime can be specified with the -+ option. TTL-style -+ suffixes can be used to specify the lifetime in -+ seconds, minutes, or hours. If the specified NTA -+ already exists, its lifetime will be updated to the -+ new value. Setting to zero -+ is equivalent to . -+ -+ -+ If is used, any other arguments -+ are ignored, and a list of existing NTAs is printed -+ (note that this may include NTAs that are expired but -+ have not yet been cleaned up). -+ -+ -+ Normally, named will periodically -+ test to see whether data below an NTA can now be -+ validated (see the option -+ in the Administrator Reference Manual for details). -+ If data can be validated, then the NTA is regarded as -+ no longer necessary, and will be allowed to expire -+ early. The overrides this -+ behavior and forces an NTA to persist for its entire -+ lifetime, regardless of whether data could be -+ validated if the NTA were not present. -+ -+ -+ All of these options can be shortened, i.e., to -+ , , , -+ and . -+ -+ -+ -+ - - tsig-list - -diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf -index a6310cd1e2..cf7c745722 100644 ---- a/bin/tests/system/checkconf/good.conf -+++ b/bin/tests/system/checkconf/good.conf -@@ -67,6 +67,8 @@ options { - serial-query-rate 100; - server-id none; - max-cache-size 20000000000000; -+ nta-recheck 604800; -+ nta-lifetime 604800; - zone-statistics none; - }; - view "first" { -diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh -index 64563154df..7ddd9c789f 100644 ---- a/bin/tests/system/checkconf/tests.sh -+++ b/bin/tests/system/checkconf/tests.sh -@@ -12,8 +12,6 @@ - # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - # PERFORMANCE OF THIS SOFTWARE. - --# $Id$ -- - SYSTEMTESTTOP=.. - . $SYSTEMTESTTOP/conf.sh - -diff --git a/bin/tests/system/dlvauto/tests.sh b/bin/tests/system/dlvauto/tests.sh -index 25bb8e30d8..138a72b850 100644 ---- a/bin/tests/system/dlvauto/tests.sh -+++ b/bin/tests/system/dlvauto/tests.sh -@@ -51,7 +51,7 @@ linecount=`grep "\./RSAMD5/.* ; managed" ns2/named.secroots | wc -l` - linecount=`grep "dlv.isc.org/RSAMD5/.* ; managed" ns2/named.secroots | wc -l` - [ "$linecount" -eq 2 ] || ret=1 - linecount=`cat ns2/named.secroots | wc -l` --[ "$linecount" -eq 13 ] || ret=1 -+[ "$linecount" -eq 28 ] || ret=1 - n=`expr $n + 1` - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` -diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh -index 0f333409b3..3b91a96818 100644 ---- a/bin/tests/system/dnssec/clean.sh -+++ b/bin/tests/system/dnssec/clean.sh -@@ -69,3 +69,4 @@ rm -f ns6/optout-tld.db - rm -f nosign.before - rm -f signing.out* - rm -f canonical?.* -+rm -f ns*/*.nta -diff --git a/bin/tests/system/dnssec/ns2/example.db.in b/bin/tests/system/dnssec/ns2/example.db.in -index 7be1044204..e22999f445 100644 ---- a/bin/tests/system/dnssec/ns2/example.db.in -+++ b/bin/tests/system/dnssec/ns2/example.db.in -@@ -65,6 +65,10 @@ ns.insecure A 10.53.0.3 - bogus NS ns.bogus - ns.bogus A 10.53.0.3 - -+; A subdomain with a corrupt DS -+badds NS ns.badds -+ns.badds A 10.53.0.3 -+ - ; A dynamic secure subdomain - dynamic NS dynamic - dynamic A 10.53.0.3 -diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh -index 5b5d337a5d..118b8a6d6b 100644 ---- a/bin/tests/system/dnssec/ns2/sign.sh -+++ b/bin/tests/system/dnssec/ns2/sign.sh -@@ -30,11 +30,10 @@ zonefile=example.db - - ( cd ../ns3 && sh sign.sh ) - --for subdomain in secure bogus dynamic keyless nsec3 optout nsec3-unknown \ -- optout-unknown multiple rsasha256 rsasha512 kskonly update-nsec3 \ -- auto-nsec auto-nsec3 secure.below-cname ttlpatch split-dnssec \ -- split-smart expired expiring upper lower -- -+for subdomain in secure badds bogus dynamic keyless nsec3 optout \ -+ nsec3-unknown optout-unknown multiple rsasha256 rsasha512 \ -+ kskonly update-nsec3 auto-nsec auto-nsec3 secure.below-cname \ -+ ttlpatch split-dnssec split-smart expired expiring upper lower - do - cp ../ns3/dsset-$subdomain.example. . - done -diff --git a/bin/tests/system/dnssec/ns3/bogus.example.db.in b/bin/tests/system/dnssec/ns3/bogus.example.db.in -index e83d07bea0..80fb5e3992 100644 ---- a/bin/tests/system/dnssec/ns3/bogus.example.db.in -+++ b/bin/tests/system/dnssec/ns3/bogus.example.db.in -@@ -28,5 +28,6 @@ ns A 10.53.0.3 - - a A 10.0.0.1 - b A 10.0.0.2 -+c A 10.0.0.3 - d A 10.0.0.4 - z A 10.0.0.26 -diff --git a/bin/tests/system/dnssec/ns3/named.conf b/bin/tests/system/dnssec/ns3/named.conf -index e745a7525f..6ef21b39c6 100644 ---- a/bin/tests/system/dnssec/ns3/named.conf -+++ b/bin/tests/system/dnssec/ns3/named.conf -@@ -68,6 +68,12 @@ zone "bogus.example" { - allow-update { any; }; - }; - -+zone "badds.example" { -+ type master; -+ file "badds.example.db.signed"; -+ allow-update { any; }; -+}; -+ - zone "dynamic.example" { - type master; - file "dynamic.example.db.signed"; -diff --git a/bin/tests/system/dnssec/ns3/secure.example.db.in b/bin/tests/system/dnssec/ns3/secure.example.db.in -index c9de3e5b6d..816f766fcb 100644 ---- a/bin/tests/system/dnssec/ns3/secure.example.db.in -+++ b/bin/tests/system/dnssec/ns3/secure.example.db.in -@@ -28,7 +28,11 @@ ns A 10.53.0.3 - - a A 10.0.0.1 - b A 10.0.0.2 -+c A 10.0.0.3 - d A 10.0.0.4 -+e A 10.0.0.5 -+f A 10.0.0.6 -+g A 10.0.0.7 - z A 10.0.0.26 - a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27 - x CNAME a -diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh -index 24b0fed7dd..4f010168cf 100644 ---- a/bin/tests/system/dnssec/ns3/sign.sh -+++ b/bin/tests/system/dnssec/ns3/sign.sh -@@ -451,3 +451,19 @@ kskname=`$KEYGEN -I $now+90s -q -r $RANDFILE -f KSK $zone` - zskname=`$KEYGEN -q -r $RANDFILE $zone` - cp $infile $zonefile - $SIGNER -S -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1 -+ -+ -+# -+# A zone with a bad DS in the parent -+# (sourced from bogus.example.db.in) -+# -+zone=badds.example. -+infile=bogus.example.db.in -+zonefile=badds.example.db -+ -+keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone` -+ -+cat $infile $keyname.key >$zonefile -+ -+$SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1 -+sed -e 's/bogus/badds/g' < dsset-bogus.example. > dsset-badds.example. -\ No newline at end of file -diff --git a/bin/tests/system/dnssec/ns4/named1.conf b/bin/tests/system/dnssec/ns4/named1.conf -index a129c5e51a..542266f2f6 100644 ---- a/bin/tests/system/dnssec/ns4/named1.conf -+++ b/bin/tests/system/dnssec/ns4/named1.conf -@@ -34,6 +34,9 @@ options { - dnssec-validation yes; - dnssec-must-be-secure mustbesecure.example yes; - -+ nta-lifetime 10s; -+ nta-recheck 7s; -+ - # Note: We only reference the bind.keys file here to confirm that it - # is *not* being used. It contains the real root key, and we're - # using a local toy root zone for the tests, so it wouldn't work. -diff --git a/bin/tests/system/dnssec/ntadiff.pl b/bin/tests/system/dnssec/ntadiff.pl -new file mode 100755 -index 0000000000..d3f5554230 ---- /dev/null -+++ b/bin/tests/system/dnssec/ntadiff.pl -@@ -0,0 +1,13 @@ -+#!/usr/bin/perl -w -+ -+use strict; -+use Time::Piece; -+use Time::Seconds; -+ -+exit 1 if (scalar(@ARGV) != 2); -+ -+my $actual = Time::Piece->strptime($ARGV[0], '%d-%b-%Y %H:%M:%S.000 %z'); -+my $expected = Time::Piece->strptime($ARGV[1], '%s') + ONE_WEEK; -+my $diff = abs($actual - $expected); -+ -+print($diff . "\n"); -diff --git a/bin/tests/system/dnssec/setup.sh b/bin/tests/system/dnssec/setup.sh -index 424792966a..7b2a6bc825 100644 ---- a/bin/tests/system/dnssec/setup.sh -+++ b/bin/tests/system/dnssec/setup.sh -@@ -24,6 +24,8 @@ sh clean.sh - cd ns1 && sh sign.sh - - echo "a.bogus.example. A 10.0.0.22" >>../ns3/bogus.example.db.signed -+echo "b.bogus.example. A 10.0.0.23" >>../ns3/bogus.example.db.signed -+echo "c.bogus.example. A 10.0.0.23" >>../ns3/bogus.example.db.signed - - cd ../ns4 && cp -f named1.conf named.conf - cd ../ns5 && cp -f trusted.conf.bad trusted.conf -diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh -index bb7452f82b..9397b75bb4 100644 ---- a/bin/tests/system/dnssec/tests.sh -+++ b/bin/tests/system/dnssec/tests.sh -@@ -21,6 +21,7 @@ SYSTEMTESTTOP=.. - . $SYSTEMTESTTOP/conf.sh - - RANDFILE=random.data -+DEFAULT_NTA=3bf305731dd26307.nta - - status=0 - n=1 -@@ -811,7 +812,7 @@ if [ -x ${SAMPLE} ] ; then - ret=0 - echo "I:checking failed validation using dns_client ($n)" - $SAMPLE $SAMPLEKEY -p 5300 -t a 10.53.0.4 a.bogus.example > /dev/null 2> sample.out$n || ret=1 -- grep "resolution failed: no valid RRSIG" sample.out$n > /dev/null || ret=1 -+ grep "resolution failed: RRSIG failed to verify" sample.out$n > /dev/null || ret=1 - n=`expr $n + 1` - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` -@@ -1505,7 +1506,7 @@ keyid=`cat ns1/managed.key.id` - linecount=`grep "./RSAMD5/$keyid ; trusted" ns4/named.secroots | wc -l` - [ "$linecount" -eq 1 ] || ret=1 - linecount=`cat ns4/named.secroots | wc -l` --[ "$linecount" -eq 5 ] || ret=1 -+[ "$linecount" -eq 10 ] || ret=1 - n=`expr $n + 1` - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` -@@ -1585,9 +1586,398 @@ ret=0 - $DIG $DIGOPTS ns algroll. @10.53.0.4 > dig.out.ns4.test$n || ret=1 - grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 - grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n > /dev/null || ret=1 -+n=`expr $n + 1` -+if [ $ret != 0 ]; then echo "I:failed"; fi -+status=`expr $status + $ret` -+ -+echo "I:checking positive and negative validation with negative trust anchors ($n)" -+ret=0 -+# -+# check correct initial behavior -+# -+$DIG $DIGOPTS a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.1 > /dev/null || ret=1 -+$DIG $DIGOPTS badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1 -+$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1 -+ -+# -+# add negative trust anchors -+# -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -f -l 15s bogus.example 2>&1 | sed 's/^/I:ns4 /' -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta badds.example 2>&1 | sed 's/^/I:ns4 /' -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 reconfig # reconfig should maintain NTAs -+lines=`$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d | wc -l` -+[ "$lines" -eq 2 ] || ret=1 -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta secure.example 2>&1 | sed 's/^/I:ns4 /' -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta fakenode.secure.example 2>&1 | sed 's/^/I:ns4 /' -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 reload # reload should maintain NTAs -+lines=`$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d | wc -l` -+[ "$lines" -eq 4 ] || ret=1 -+ -+# -+# check behavior with NTA's in place -+# -+$DIG $DIGOPTS a.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1 -+$DIG $DIGOPTS badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.5 > /dev/null && ret=1 -+$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.6 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.6 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 > /dev/null && ret=1 -+$DIG $DIGOPTS a.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.7 || ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 > /dev/null && ret=1 -+echo "I: dumping secroots" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 secroots | sed 's/^/I:ns4 /' -+grep "bogus.example: expiry" ns4/named.secroots > /dev/null || ret=1 -+grep "badds.example: expiry" ns4/named.secroots > /dev/null || ret=1 -+grep "secure.example: expiry" ns4/named.secroots > /dev/null || ret=1 -+grep "fakenode.secure.example: expiry" ns4/named.secroots > /dev/null || ret=1 -+echo "I: waiting for NTA rechecks/expirations" -+ -+# -+# secure.example and badds.example used default nta-duration -+# (configured as 10s in ns4/named1.conf), but nta recheck interval -+# is configured to 7s, so at t=8 the NTAs for secure.example and -+# fakenode.secure.example should both be lifted, but badds.example -+# should still be going. -+# -+sleep 8 -+$DIG $DIGOPTS b.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.8 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.8 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.8 > /dev/null || ret=1 -+$DIG $DIGOPTS b.fakenode.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.9 || ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.9 > /dev/null || ret=1 -+grep "status: NXDOMAIN" dig.out.ns4.test$n.9 > /dev/null || ret=1 -+$DIG $DIGOPTS badds.example. soa @10.53.0.4 > dig.out.ns4.test$n.10 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.10 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.10 > /dev/null && ret=1 -+ -+# -+# bogus.example was set to expire in 15s, so at t=11 -+# it should still be NTA'd, but badds.example used the default -+# lifetime of 10s, so it should revert to SERVFAIL now. -+# -+sleep 3 -+# check nta table -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n._11 -+lines=`wc -l < rndc.out.ns4.test$n._11` -+[ "$lines" -le 2 ] || ret=1 -+grep "bogus.example: expiry" rndc.out.ns4.test$n._11 > /dev/null || ret=1 -+grep "badds.example: expiry" rndc.out.ns4.test$n._11 > /dev/null && ret=1 -+$DIG $DIGOPTS b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.11 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.11 > /dev/null && ret=1 -+$DIG $DIGOPTS a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.12 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.12 > /dev/null || ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.12 > /dev/null && ret=1 -+$DIG $DIGOPTS c.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.13 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.13 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.13 > /dev/null || ret=1 -+ -+# -+# at t=16, all the NTAs should have expired. -+# -+sleep 5 -+# check correct behavior after bogus.example expiry -+$DIG $DIGOPTS d.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.14 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.14 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.14 > /dev/null || ret=1 -+$DIG $DIGOPTS c.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.15 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.15 > /dev/null || ret=1 -+# check nta table has been cleaned up now -+lines=`$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d | wc -l` -+[ "$lines" -eq 0 ] || ret=1 -+n=`expr $n + 1` -+if [ $ret != 0 ]; then echo "I:failed - checking that all nta's have been lifted"; fi -+status=`expr $status + $ret` -+ret=0 -+ -+echo "I: testing NTA removals ($n)" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta badds.example 2>&1 | sed 's/^/I:ns4 /' -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n.1 -+grep "badds.example: expiry" rndc.out.ns4.test$n.1 > /dev/null || ret=1 -+$DIG $DIGOPTS a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.1 || ret=1 -+grep "^a.badds.example." dig.out.ns4.test$n.1 > /dev/null || ret=1 -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -remove badds.example > rndc.out.ns4.test$n.2 -+grep "Negative trust anchor removed: badds.example/_default" rndc.out.ns4.test$n.2 > /dev/null || ret=1 -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n.3 -+grep "badds.example: expiry" rndc.out.ns4.test$n.3 > /dev/null && ret=1 -+$DIG $DIGOPTS a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null || ret=1 -+echo "I: remove non-existent NTA three times" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -r foo > rndc.out.ns4.test$n.4 2>&1 -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -remove foo > rndc.out.ns4.test$n.5 2>&1 -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -r foo > rndc.out.ns4.test$n.6 2>&1 -+grep "'nta' failed: not found" rndc.out.ns4.test$n.6 > /dev/null || ret=1 -+if [ $ret != 0 ]; then echo "I:failed"; fi -+status=`expr $status + $ret` -+ret=0 -+ -+n=`expr $n + 1` -+echo "I: testing NTA with bogus lifetimes ($n)" -+echo "I:check with no nta lifetime specified" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -l "" foo > rndc.out.ns4.test$n.1 2>&1 -+grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.1 > /dev/null || ret=1 -+echo "I:check with bad nta lifetime" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -l garbage foo > rndc.out.ns4.test$n.2 2>&1 -+grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.2 > /dev/null || ret=1 -+echo "I:check with too long nta lifetime" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -l 7d1h foo > rndc.out.ns4.test$n.3 2>&1 -+grep "'nta' failed: out of range" rndc.out.ns4.test$n.3 > /dev/null || ret=1 - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` -+ret=0 -+ -+# -+# check NTA persistence across restarts -+# -+n=`expr $n + 1` -+echo "I: testing NTA persistence across restarts ($n)" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n.1 -+lines=`wc -l < rndc.out.ns4.test$n.1` -+[ "$lines" -eq 0 ] || ret=1 -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -f -l 30s bogus.example 2>&1 | sed 's/^/I:ns4 /' -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -f -l 10s badds.example 2>&1 | sed 's/^/I:ns4 /' -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n.2 -+lines=`wc -l < rndc.out.ns4.test$n.2` -+[ "$lines" -eq 2 ] || ret=1 -+start=`$PERL -e 'print time()."\n";'` -+ -+if [ $ret != 0 ]; then echo "I:failed - NTA persistence: adding NTA's failed"; fi -+status=`expr $status + $ret` -+ret=0 -+ -+echo "I:killing ns4 with SIGTERM" -+cd ns4 -+kill -TERM `cat named.pid` -+rm named.pid -+cd .. -+ -+# -+# ns4 has now shutdown. wait until t=14 when badds.example's NTA -+# (lifetime=10s) would have expired, and then restart ns4. -+# -+echo "I:waiting till 14s have passed since NTAs were added before restarting ns4" -+$PERL -e 'my $delay = '$start' + 14 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' -+ -+if -+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns4 -+then -+ echo "I:restarted server ns4" -+else -+ echo "I:could not restart server ns4" -+ exit 1 -+fi -+ -+echo "I:sleeping for an additional 4 seconds for ns4 to fully startup" -+sleep 4 -+ -+# -+# ns4 should be back up now. The NTA for bogus.example should still be -+# valid, whereas badds.example should not have been added during named -+# startup (as it had already expired). -+# -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n.3 -+lines=`wc -l < rndc.out.ns4.test$n.3` -+[ "$lines" -eq 1 ] || ret=1 -+grep "bogus.example: expiry" rndc.out.ns4.test$n.3 > /dev/null || ret=1 -+$DIG $DIGOPTS b.bogus.example. a @10.53.0.4 > dig.out.ns4.test$n.4 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.4 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 > /dev/null && ret=1 -+$DIG $DIGOPTS a.badds.example. a @10.53.0.4 > dig.out.ns4.test$n.5 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.5 > /dev/null || ret=1 -+ -+# cleanup -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -remove bogus.example > rndc.out.ns4.test$n.6 -+ -+if [ $ret != 0 ]; then echo "I:failed - NTA persistence: restoring NTA failed"; fi -+status=`expr $status + $ret` -+ret=0 -+ -+# -+# check "regular" attribute in NTA file works as expected at named -+# startup. -+# -+n=`expr $n + 1` -+echo "I: testing loading regular attribute from NTA file ($n)" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n.1 2>/dev/null -+lines=`wc -l < rndc.out.ns4.test$n.1` -+[ "$lines" -eq 0 ] || ret=1 -+# initially, secure.example. validates with AD=1 -+$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1 -+ -+echo "I:killing ns4 with SIGTERM" -+cd ns4 -+kill -TERM `cat named.pid` -+rm named.pid -+cd .. -+ -+echo "I:sleeping for an additional 4 seconds for ns4 to fully shutdown" -+sleep 4 -+ -+# -+# ns4 has now shutdown. add NTA for secure.example. directly into the -+# ${DEFAULT_NTA} file with the regular attribute and some future timestamp. -+# -+year=`date +%Y` -+future="`expr 20 + ${year}`0101010000" -+echo "secure.example. regular $future" > ns4/${DEFAULT_NTA} -+start=`$PERL -e 'print time()."\n";'` -+ -+if -+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns4 -+then -+ echo "I:restarted server ns4" -+else -+ echo "I:could not restart server ns4" -+ exit 1 -+fi -+ -+# nta-recheck is configured as 7s, so at t=10 the NTAs for -+# secure.example. should be lifted as it is not a forced NTA. -+echo "I:waiting till 10s have passed after ns4 was restarted" -+$PERL -e 'my $delay = '$start' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' -+ -+# secure.example. should now return an AD=1 answer (still validates) as -+# the NTA has been lifted. -+$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null || ret=1 -+ -+# cleanup -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -remove secure.example > rndc.out.ns4.test$n.4 2>/dev/null -+ -+if [ $ret != 0 ]; then echo "I:failed - NTA persistence: loading regular NTAs failed"; fi -+status=`expr $status + $ret` -+ret=0 -+ -+# -+# check "forced" attribute in NTA file works as expected at named -+# startup. -+# -+n=`expr $n + 1` -+echo "I: testing loading forced attribute from NTA file ($n)" -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n.1 2>/dev/null -+lines=`wc -l < rndc.out.ns4.test$n.1` -+[ "$lines" -eq 0 ] || ret=1 -+# initially, secure.example. validates with AD=1 -+$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.2 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.2 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 > /dev/null || ret=1 -+ -+echo "I:killing ns4 with SIGTERM" -+cd ns4 -+kill -TERM `cat named.pid` -+rm named.pid -+cd .. -+ -+echo "I:sleeping for an additional 4 seconds for ns4 to fully shutdown" -+sleep 4 -+ -+# -+# ns4 has now shutdown. add NTA for secure.example. directly into the -+# ${DEFAULT_NTA} file with the forced attribute and some future timestamp. -+# -+echo "secure.example. forced $future" > ns4/${DEFAULT_NTA} -+start=`$PERL -e 'print time()."\n";'` -+ -+if -+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns4 -+then -+ echo "I:restarted server ns4" -+else -+ echo "I:could not restart server ns4" -+ exit 1 -+fi -+ -+# nta-recheck is configured as 7s, but even at t=10 the NTAs for -+# secure.example. should not be lifted as it is a forced NTA. -+echo "I:waiting till 10s have passed after ns4 was restarted" -+$PERL -e 'my $delay = '$start' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' -+ -+# secure.example. should now return an AD=0 answer (non-authenticated) -+# as the NTA is still there. -+$DIG $DIGOPTS a.secure.example. a @10.53.0.4 > dig.out.ns4.test$n.3 || ret=1 -+grep "status: SERVFAIL" dig.out.ns4.test$n.3 > /dev/null && ret=1 -+grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 > /dev/null && ret=1 -+ -+# cleanup -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -remove secure.example > rndc.out.ns4.test$n.4 2>/dev/null -+ -+if [ $ret != 0 ]; then echo "I:failed - NTA persistence: loading forced NTAs failed"; fi -+status=`expr $status + $ret` -+ret=0 -+ -+# -+# check that NTA lifetime read from file is clamped to 1 week. -+# -+n=`expr $n + 1` -+echo "I: testing loading out of bounds lifetime from NTA file ($n)" -+ -+echo "I:killing ns4 with SIGTERM" -+cd ns4 -+kill -TERM `cat named.pid` -+rm named.pid -+cd .. -+ -+echo "I:sleeping for an additional 4 seconds for ns4 to fully shutdown" -+sleep 4 -+ -+# -+# ns4 has now shutdown. add NTA for secure.example. directly into the -+# ${DEFAULT_NTA} file with a lifetime well into the future. -+# -+echo "secure.example. forced $future" > ns4/${DEFAULT_NTA} -+added=`$PERL -e 'print time()."\n";'` -+ -+if -+ $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns4 -+then -+ echo "I:restarted server ns4" -+else -+ echo "I:could not restart server ns4" -+ exit 1 -+fi -+ -+echo "I:sleeping for an additional 4 seconds for ns4 to fully startup" -+sleep 4 -+ -+# dump the NTA to a file -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -d > rndc.out.ns4.test$n.1 2>rndc.out.ns4.test$n.1err -+lines=`wc -l < rndc.out.ns4.test$n.1` -+[ "$lines" -eq 1 ] || ret=1 -+ts=`awk '{print $3" "$4}' < rndc.out.ns4.test$n.1` -+# rndc nta outputs localtime, so append the timezone -+ts_with_zone="$ts `date +%z`" -+echo "ts=$ts" > rndc.out.ns4.test$n.2 -+echo "ts_with_zone=$ts_with_zone" >> rndc.out.ns4.test$n.2 -+echo "added=$added" >> rndc.out.ns4.test$n.2 -+if $PERL -e 'use Time::Piece; use Time::Seconds;' 2>/dev/null -+then -+ # ntadiff.pl computes $ts_with_zone - ($added + 1week) -+ d=`$PERL ./ntadiff.pl "$ts_with_zone" "$added"` -+ echo "d=$d" >> rndc.out.ns4.test$n.2 -+ # diff from $added(now) + 1week to the clamped NTA lifetime should be -+ # less than a few seconds. -+ [ $d -lt 3610 ] || ret=1 -+else -+ echo "I: skipped ntadiff test; install PERL module Time::Piece" -+fi -+ -+# cleanup -+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 nta -remove secure.example > rndc.out.ns4.test$n.3 2>/dev/null -+ -+if [ $ret != 0 ]; then echo "I:failed - NTA lifetime clamping failed"; fi -+status=`expr $status + $ret` -+ret=0 - -+echo "I:completed NTA tests" - # Run a minimal update test if possible. This is really just - # a regression test for RT #2399; more tests should be added. - -@@ -1689,7 +2079,7 @@ ret=0 - $DIG $DIGOPTS +noauth expired.example. +dnssec @10.53.0.4 soa > dig.out.ns4.test$n || ret=1 - grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1 - grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1 --grep "expired.example .*: RRSIG has expired" ns4/named.run > /dev/null || ret=1 -+grep "expired.example[ /].*: RRSIG has expired" ns4/named.run > /dev/null || ret=1 - n=`expr $n + 1` - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` -diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh -index 947987bce8..01dbc811ae 100644 ---- a/bin/tests/system/rndc/tests.sh -+++ b/bin/tests/system/rndc/tests.sh -@@ -305,5 +305,11 @@ done - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` - -+echo "I:testing rndc nta time limits" -+ret=0 -+$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf nta -l 2h nta1.example 2>&1 | grep "Negative trust anchor added" > /dev/null || ret=1 -+$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf nta -l 1d nta2.example 2>&1 | grep "Negative trust anchor added" > /dev/null || ret=1 -+$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf nta -l 1w nta3.example 2>&1 | grep "Negative trust anchor added" > /dev/null || ret=1 -+$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf nta -l 8d nta4.example 2>&1 | grep "NTA lifetime cannot exceed one week" > /dev/null || ret=1 - echo "I:exit status: $status" - exit $status -diff --git a/configure.in b/configure.in -index fb2e53e8e1..ee38901937 100644 ---- a/configure.in -+++ b/configure.in -@@ -3710,6 +3710,7 @@ AC_SUBST(BIND9_ISCCFG_BUILDINCLUDE) - AC_SUBST(BIND9_DNS_BUILDINCLUDE) - AC_SUBST(BIND9_LWRES_BUILDINCLUDE) - AC_SUBST(BIND9_BIND9_BUILDINCLUDE) -+AC_SUBST(BIND9_IRS_BUILDINCLUDE) - if test "X$srcdir" != "X"; then - BIND9_ISC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isc/include" - BIND9_ISCCC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccc/include" -@@ -3717,6 +3718,7 @@ if test "X$srcdir" != "X"; then - BIND9_DNS_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/dns/include" - BIND9_LWRES_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/lwres/include" - BIND9_BIND9_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/bind9/include" -+ BIND9_IRS_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/irs/include" - else - BIND9_ISC_BUILDINCLUDE="" - BIND9_ISCCC_BUILDINCLUDE="" -@@ -3724,6 +3726,7 @@ else - BIND9_DNS_BUILDINCLUDE="" - BIND9_LWRES_BUILDINCLUDE="" - BIND9_BIND9_BUILDINCLUDE="" -+ BIND9_IRS_BUILDINCLUDE="" - fi - - AC_SUBST_FILE(BIND9_MAKE_INCLUDES) -diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml -index 7a9d60db02..af194d9cfd 100644 ---- a/doc/arm/Bv9ARM-book.xml -+++ b/doc/arm/Bv9ARM-book.xml -@@ -4902,6 +4902,8 @@ badresp:1,adberr:0,findfail:0,valfail:0] - max-refresh-time number ; - min-retry-time number ; - max-retry-time number ; -+ nta-lifetime duration ; -+ nta-recheck duration ; - port ip_port; - additional-from-auth yes_or_no ; - additional-from-cache yes_or_no ; -@@ -5684,11 +5686,76 @@ options { - named. (A planned third option, - external, will disable all automatic - signing and allow DNSSEC data to be submitted into a zone -- via dyanmic update; this is not yet implemented.) -+ via dynamic update; this is not yet implemented.) - - - - -+ -+ nta-lifetime -+ -+ -+ Species the default lifetime, in seconds, -+ that will be used for negative trust anchors added -+ via rndc nta. -+ -+ -+ A negative trust anchor selectively disables -+ DNSSEC validation for zones that known to be -+ failing because of misconfiguration rather than -+ an attack. When data to be validated is -+ at or below an active NTA (and above any other -+ configured trust anchors), named will -+ abort the DNSSEC validation process and treat the data as -+ insecure rather than bogus. This continues until the -+ NTA's lifetime is elapsed. NTAs persist -+ across named restarts. -+ -+ -+ For convienience, TTL-style time unit suffixes can be -+ used to specify the NTA lifetime in seconds, minutes -+ or hours. defaults to -+ one hour. It cannot exceed one week. -+ -+ -+ -+ -+ -+ nta-recheck -+ -+ -+ Species how often to check whether negative -+ trust anchors added via rndc nta -+ are still necessary. -+ -+ -+ A negative trust anchor is normally used when a -+ domain has stopped validating due to operator error; -+ it temporarily disables DNSSEC validation for that -+ domain. In the interest of ensuring that DNSSEC -+ validation is turned back on as soon as possible, -+ named will periodically send a -+ query to the domain, ignoring negative trust anchors, -+ to find out whether it can now be validated. If so, -+ the negative trust anchor is allowed to expire early. -+ -+ -+ Validity checks can be disabled for an indivdiual -+ NTA by using rndc nta -f, or -+ for all NTA's by setting -+ to zero. -+ -+ -+ For convienience, TTL-style time unit suffixes can be -+ used to specify the NTA recheck interval in seconds, -+ minutes or hours. The default is five minutes. It -+ cannot be longer than -+ (which cannot be longer than a week). -+ -+ -+ -+ -+ - - zone-statistics - -@@ -10179,6 +10246,10 @@ ns.domain.com.rpz-nsdname CNAME . - level are inherited by all views, but keys defined in a view - are only used within that view. - -+ -+ Validation below specified names can be temporarily disabled -+ by using rndc nta. -+ - - - -@@ -17037,6 +17108,7 @@ zone "example.com" { - Manual pages - - -+ - - - -diff --git a/lib/bind9/check.c b/lib/bind9/check.c -index 61574e8144..5131b521f4 100644 ---- a/lib/bind9/check.c -+++ b/lib/bind9/check.c -@@ -689,6 +689,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx, - const char *str; - dns_name_t *name; - isc_buffer_t b; -+ isc_uint32_t lifetime = 0; - - static intervaltable intervals[] = { - { "cleaning-interval", 60, 28 * 24 * 60 }, /* 28 days */ -@@ -1038,6 +1039,38 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx, - result = ISC_R_FAILURE; - } - -+ -+ obj = NULL; -+ (void)cfg_map_get(options, "nta-lifetime", &obj); -+ if (obj != NULL) { -+ lifetime = cfg_obj_asuint32(obj); -+ if (lifetime > 604800) { /* 7 days */ -+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR, -+ "'nta-lifetime' cannot exceed one week"); -+ result = ISC_R_RANGE; -+ } else if (lifetime == 0) { -+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR, -+ "'nta-lifetime' may not be zero"); -+ result = ISC_R_RANGE; -+ } -+ } -+ -+ obj = NULL; -+ (void)cfg_map_get(options, "nta-recheck", &obj); -+ if (obj != NULL) { -+ isc_uint32_t recheck = cfg_obj_asuint32(obj); -+ if (recheck > 604800) { /* 7 days */ -+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR, -+ "'nta-recheck' cannot exceed one week"); -+ result = ISC_R_RANGE; -+ } -+ -+ if (recheck > lifetime) -+ cfg_obj_log(obj, logctx, ISC_LOG_WARNING, -+ "'nta-recheck' (%d seconds) is " -+ "greater than 'nta-lifetime' " -+ "(%d seconds)", recheck, lifetime); -+ } - return (result); - } - -diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in -index ae316c59e2..4478a6c8e6 100644 ---- a/lib/dns/Makefile.in -+++ b/lib/dns/Makefile.in -@@ -66,8 +66,8 @@ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ - iptable.@O@ journal.@O@ keydata.@O@ keytable.@O@ \ - lib.@O@ log.@O@ lookup.@O@ \ - master.@O@ masterdump.@O@ message.@O@ \ -- name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ \ -- portlist.@O@ private.@O@ \ -+ name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ nta.@O@ \ -+ order.@O@ peer.@O@ portlist.@O@ private.@O@ \ - rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rcode.@O@ rdata.@O@ \ - rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \ - request.@O@ resolver.@O@ result.@O@ rootns.@O@ \ -@@ -100,7 +100,8 @@ DNSSRCS = acache.c acl.c adb.c byaddr.c \ - dlz.c dns64.c dnssec.c ds.c dyndb.c forward.c iptable.c \ - journal.c keydata.c keytable.c lib.c log.c lookup.c \ - master.c masterdump.c message.c \ -- name.c ncache.c nsec.c nsec3.c order.c peer.c portlist.c \ -+ name.c ncache.c nsec.c nsec3.c nta.c \ -+ order.c peer.c portlist.c \ - rbt.c rbtdb.c rbtdb64.c rcode.c rdata.c rdatalist.c \ - rdataset.c rdatasetiter.c rdataslab.c request.c \ - resolver.c result.c rootns.c rpz.c rriterator.c \ -diff --git a/lib/dns/adb.c b/lib/dns/adb.c -index ac89e66172..c38df5bb87 100644 ---- a/lib/dns/adb.c -+++ b/lib/dns/adb.c -@@ -2465,9 +2465,9 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, - - result = isc_taskmgr_excltask(adb->taskmgr, &adb->excl); - if (result != ISC_R_SUCCESS) { -- DP(ISC_LOG_INFO, "adb: task-exclusive mode unavailable, " -- "intializing table sizes to %u\n", -- nbuckets[11]); -+ DP(DEF_LEVEL, "adb: task-exclusive mode unavailable, " -+ "intializing table sizes to %u\n", -+ nbuckets[11]); - adb->nentries = nbuckets[11]; - adb->nnames = nbuckets[11]; - -diff --git a/lib/dns/client.c b/lib/dns/client.c -index d3b371b0e4..9835b37bf0 100644 ---- a/lib/dns/client.c -+++ b/lib/dns/client.c -@@ -21,6 +21,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -129,6 +130,8 @@ typedef struct resctx { - isc_mutex_t lock; - dns_client_t *client; - isc_boolean_t want_dnssec; -+ isc_boolean_t want_validation; -+ isc_boolean_t want_cdflag; - - /* Locked */ - ISC_LINK(struct resctx) link; -@@ -302,12 +305,12 @@ getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, - } - - static isc_result_t --dns_client_createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, -- unsigned int options, isc_taskmgr_t *taskmgr, -- unsigned int ntasks, isc_socketmgr_t *socketmgr, -- isc_timermgr_t *timermgr, dns_dispatchmgr_t *dispatchmgr, -- dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, -- dns_view_t **viewp) -+createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, -+ unsigned int options, isc_taskmgr_t *taskmgr, -+ unsigned int ntasks, isc_socketmgr_t *socketmgr, -+ isc_timermgr_t *timermgr, dns_dispatchmgr_t *dispatchmgr, -+ dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, -+ dns_view_t **viewp) - { - isc_result_t result; - dns_view_t *view = NULL; -@@ -324,9 +327,9 @@ dns_client_createview(isc_mem_t *mctx, dns_rdataclass_t rdclass, - return (result); - } - -- result = dns_view_createresolver(view, taskmgr, ntasks, 1, socketmgr, -- timermgr, 0, dispatchmgr, -- dispatchv4, dispatchv6); -+ result = dns_view_createresolver(view, taskmgr, ntasks, 1, -+ socketmgr, timermgr, 0, -+ dispatchmgr, dispatchv4, dispatchv6); - if (result != ISC_R_SUCCESS) { - dns_view_detach(&view); - return (result); -@@ -485,10 +488,9 @@ dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, - } - - /* Create the default view for class IN */ -- result = dns_client_createview(mctx, dns_rdataclass_in, options, -- taskmgr, RESOLVER_NTASKS, socketmgr, timermgr, -- dispatchmgr, dispatchv4, dispatchv6, -- &view); -+ result = createview(mctx, dns_rdataclass_in, options, taskmgr, -+ RESOLVER_NTASKS, socketmgr, timermgr, dispatchmgr, -+ dispatchv4, dispatchv6, &view); - if (result != ISC_R_SUCCESS) - goto cleanup; - ISC_LIST_INIT(client->viewlist); -@@ -653,6 +655,46 @@ dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass, - return (result); - } - -+isc_result_t -+dns_client_setdlv(dns_client_t *client, dns_rdataclass_t rdclass, -+ const char *dlvname) -+{ -+ isc_result_t result; -+ isc_buffer_t b; -+ dns_view_t *view = NULL; -+ -+ REQUIRE(DNS_CLIENT_VALID(client)); -+ -+ LOCK(&client->lock); -+ result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME, -+ rdclass, &view); -+ UNLOCK(&client->lock); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup; -+ -+ if (dlvname == NULL) -+ view->dlv = NULL; -+ else { -+ dns_name_t *newdlv; -+ -+ isc_buffer_constinit(&b, dlvname, strlen(dlvname)); -+ isc_buffer_add(&b, strlen(dlvname)); -+ newdlv = dns_fixedname_name(&view->dlv_fixed); -+ result = dns_name_fromtext(newdlv, &b, dns_rootname, -+ DNS_NAME_DOWNCASE, NULL); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup; -+ -+ view->dlv = dns_fixedname_name(&view->dlv_fixed); -+ } -+ -+ cleanup: -+ if (view != NULL) -+ dns_view_detach(&view); -+ -+ return (result); -+} -+ - static isc_result_t - getrdataset(isc_mem_t *mctx, dns_rdataset_t **rdatasetp) { - dns_rdataset_t *rdataset; -@@ -703,6 +745,7 @@ fetch_done(isc_task_t *task, isc_event_t *event) { - static inline isc_result_t - start_fetch(resctx_t *rctx) { - isc_result_t result; -+ int fopts = 0; - - /* - * The caller must be holding the rctx's lock. -@@ -710,10 +753,15 @@ start_fetch(resctx_t *rctx) { - - REQUIRE(rctx->fetch == NULL); - -+ if (!rctx->want_cdflag) -+ fopts |= DNS_FETCHOPT_NOCDFLAG; -+ if (!rctx->want_validation) -+ fopts |= DNS_FETCHOPT_NOVALIDATE; -+ - result = dns_resolver_createfetch(rctx->view->resolver, - dns_fixedname_name(&rctx->name), - rctx->type, -- NULL, NULL, NULL, 0, -+ NULL, NULL, NULL, fopts, - rctx->task, fetch_done, rctx, - rctx->rdataset, - rctx->sigrdataset, -@@ -1256,7 +1304,7 @@ dns_client_startresolve(dns_client_t *client, dns_name_t *name, - isc_mem_t *mctx; - isc_result_t result; - dns_rdataset_t *rdataset, *sigrdataset; -- isc_boolean_t want_dnssec; -+ isc_boolean_t want_dnssec, want_validation, want_cdflag; - - REQUIRE(DNS_CLIENT_VALID(client)); - REQUIRE(transp != NULL && *transp == NULL); -@@ -1272,6 +1320,8 @@ dns_client_startresolve(dns_client_t *client, dns_name_t *name, - rdataset = NULL; - sigrdataset = NULL; - want_dnssec = ISC_TF((options & DNS_CLIENTRESOPT_NODNSSEC) == 0); -+ want_validation = ISC_TF((options & DNS_CLIENTRESOPT_NOVALIDATE) == 0); -+ want_cdflag = ISC_TF((options & DNS_CLIENTRESOPT_NOCDFLAG) == 0); - - /* - * Prepare some intermediate resources -@@ -1327,6 +1377,8 @@ dns_client_startresolve(dns_client_t *client, dns_name_t *name, - rctx->restarts = 0; - rctx->fetch = NULL; - rctx->want_dnssec = want_dnssec; -+ rctx->want_validation = want_validation; -+ rctx->want_cdflag = want_cdflag; - ISC_LIST_INIT(rctx->namelist); - rctx->event = event; - -diff --git a/lib/dns/include/dns/client.h b/lib/dns/include/dns/client.h -index d21dff788d..289dc18918 100644 ---- a/lib/dns/include/dns/client.h -+++ b/lib/dns/include/dns/client.h -@@ -77,10 +77,14 @@ ISC_LANG_BEGINDECLS - /*% - * Optional flags for dns_client_(start)resolve. - */ --/*%< Disable DNSSEC validation. */ -+/*%< Do not return DNSSEC data (e.g. RRSIGS) with response. */ - #define DNS_CLIENTRESOPT_NODNSSEC 0x01 - /*%< Allow running external context. */ - #define DNS_CLIENTRESOPT_ALLOWRUN 0x02 -+/*%< Don't validate responses. */ -+#define DNS_CLIENTRESOPT_NOVALIDATE 0x04 -+/*%< Don't set the CD flag on upstream queries. */ -+#define DNS_CLIENTRESOPT_NOCDFLAG 0x08 - - /*% - * Optional flags for dns_client_(start)request. -@@ -248,6 +252,26 @@ dns_client_clearservers(dns_client_t *client, dns_rdataclass_t rdclass, - *\li Anything else Failure. - */ - -+isc_result_t -+dns_client_setdlv(dns_client_t *client, dns_rdataclass_t rdclass, -+ const char *dlvname); -+/*%< -+ * Specify a name to use for DNSSEC lookaside validation (e.g., -+ * "dlv.isc.org"). If a trusted key has been added for that name, -+ * then DLV will be used during validation. If 'dlvname' is NULL, -+ * then DLV will no longer be used for this client. -+ * -+ * Requires: -+ * -+ *\li 'client' is a valid client. -+ * -+ * Returns: -+ * -+ *\li #ISC_R_SUCCESS On success. -+ * -+ *\li Anything else Failure. -+ */ -+ - isc_result_t - dns_client_resolve(dns_client_t *client, dns_name_t *name, - dns_rdataclass_t rdclass, dns_rdatatype_t type, -diff --git a/lib/dns/include/dns/keytable.h b/lib/dns/include/dns/keytable.h -index 3f4adaf6e3..c44fca8a40 100644 ---- a/lib/dns/include/dns/keytable.h -+++ b/lib/dns/include/dns/keytable.h -@@ -386,7 +386,7 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, - - isc_result_t - dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name, -- isc_boolean_t *wantdnssecp); -+ dns_name_t *foundname, isc_boolean_t *wantdnssecp); - /*%< - * Is 'name' at or beneath a trusted key? - * -@@ -396,12 +396,16 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name, - * - *\li 'name' is a valid absolute name. - * -- *\li '*wantsdnssecp' is a valid isc_boolean_t. -+ *\li 'foundanme' is NULL or is a pointer to an initialized dns_name_t - * -+ *\li '*wantsdnssecp' is a valid isc_boolean_t. -+ - * Ensures: - * - *\li On success, *wantsdnssecp will be ISC_TRUE if and only if 'name' -- * is at or beneath a trusted key. -+ * is at or beneath a trusted key. If 'foundname' is not NULL, then -+ * it will be updated to contain the name of the closest enclosing -+ * trust anchor. - * - * Returns: - * -diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h -index a3b7e5a71e..d7185678ff 100644 ---- a/lib/dns/include/dns/log.h -+++ b/lib/dns/include/dns/log.h -@@ -78,6 +78,8 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[]; - #define DNS_LOGMODULE_DNSSEC (&dns_modules[27]) - #define DNS_LOGMODULE_CRYPTO (&dns_modules[28]) - #define DNS_LOGMODULE_DYNDB (&dns_modules[29]) -+#define DNS_LOGMODULE_PACKETS (&dns_modules[30]) -+#define DNS_LOGMODULE_NTA (&dns_modules[31]) - - ISC_LANG_BEGINDECLS - -diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h -index 8631248cc2..5164fd5084 100644 ---- a/lib/dns/include/dns/masterdump.h -+++ b/lib/dns/include/dns/masterdump.h -@@ -100,6 +100,10 @@ typedef struct dns_master_style dns_master_style_t; - /*% Report re-signing time. */ - #define DNS_STYLEFLAG_RESIGN 0x04000000U - -+/*% Comment out data by prepending with ";" */ -+#define DNS_STYLEFLAG_COMMENTDATA 0x10000000U -+ -+ - ISC_LANG_BEGINDECLS - - /*** -@@ -148,6 +152,11 @@ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_simple; - */ - LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_debug; - -+/*% -+ * Similar to dns_master_style_debug but data is prepended with ";" -+ */ -+LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_comment; -+ - /*** - *** Functions - ***/ -diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h -index d999e75a4d..11f3d41318 100644 ---- a/lib/dns/include/dns/message.h -+++ b/lib/dns/include/dns/message.h -@@ -138,6 +138,7 @@ typedef int dns_messagetextflag_t; - #define DNS_MESSAGETEXTFLAG_NOHEADERS 0x0002 - #define DNS_MESSAGETEXTFLAG_ONESOA 0x0004 - #define DNS_MESSAGETEXTFLAG_OMITSOA 0x0008 -+#define DNS_MESSAGETEXTFLAG_COMMENTDATA 0x0010 - - /* - * Dynamic update names for these sections. -@@ -1358,6 +1359,17 @@ dns_message_gettimeadjust(dns_message_t *msg); - *\li msg be a valid message. - */ - -+void -+dns_message_logpacket(dns_message_t *message, const char *description, -+ isc_logcategory_t *category, isc_logmodule_t *module, -+ int level, isc_mem_t *mctx); -+ -+void -+dns_message_logfmtpacket(dns_message_t *message, const char *description, -+ isc_logcategory_t *category, isc_logmodule_t *module, -+ const dns_master_style_t *style, int level, -+ isc_mem_t *mctx); -+ - isc_result_t - dns_message_buildopt(dns_message_t *msg, dns_rdataset_t **opt, - unsigned int version, isc_uint16_t udpsize, -diff --git a/lib/dns/include/dns/nta.h b/lib/dns/include/dns/nta.h -new file mode 100644 -index 0000000000..20bb86d5c7 ---- /dev/null -+++ b/lib/dns/include/dns/nta.h -@@ -0,0 +1,220 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef DNS_NTA_H -+#define DNS_NTA_H 1 -+ -+/***** -+ ***** Module Info -+ *****/ -+ -+/*! \file -+ * \brief -+ * The NTA module provides services for storing and retrieving negative -+ * trust anchors, and determine whether a given domain is subject to -+ * DNSSEC validation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+ISC_LANG_BEGINDECLS -+ -+struct dns_ntatable { -+ /* Unlocked. */ -+ unsigned int magic; -+ dns_view_t *view; -+ isc_rwlock_t rwlock; -+ isc_uint32_t recheck; -+ isc_taskmgr_t *taskmgr; -+ isc_timermgr_t *timermgr; -+ isc_task_t *task; -+ /* Locked by rwlock. */ -+ isc_uint32_t references; -+ dns_rbt_t *table; -+}; -+ -+#define NTATABLE_MAGIC ISC_MAGIC('N', 'T', 'A', 't') -+#define VALID_NTATABLE(nt) ISC_MAGIC_VALID(nt, NTATABLE_MAGIC) -+ -+isc_result_t -+dns_ntatable_create(dns_view_t *view, -+ isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, -+ dns_ntatable_t **ntatablep); -+/*%< -+ * Create an NTA table in view 'view'. -+ * -+ * Requires: -+ * -+ *\li 'view' is a valid view. -+ * -+ *\li 'tmgr' is a valid timer manager. -+ * -+ *\li ntatablep != NULL && *ntatablep == NULL -+ * -+ * Ensures: -+ * -+ *\li On success, *ntatablep is a valid, empty NTA table. -+ * -+ * Returns: -+ * -+ *\li ISC_R_SUCCESS -+ *\li Any other result indicates failure. -+ */ -+ -+void -+dns_ntatable_attach(dns_ntatable_t *source, dns_ntatable_t **targetp); -+/*%< -+ * Attach *targetp to source. -+ * -+ * Requires: -+ * -+ *\li 'source' is a valid ntatable. -+ * -+ *\li 'targetp' points to a NULL dns_ntatable_t *. -+ * -+ * Ensures: -+ * -+ *\li *targetp is attached to source. -+ */ -+ -+void -+dns_ntatable_detach(dns_ntatable_t **ntatablep); -+/*%< -+ * Detach *ntatablep from its ntatable. -+ * -+ * Requires: -+ * -+ *\li 'ntatablep' points to a valid ntatable. -+ * -+ * Ensures: -+ * -+ *\li *ntatablep is NULL. -+ * -+ *\li If '*ntatablep' is the last reference to the ntatable, -+ * all resources used by the ntatable will be freed -+ */ -+ -+isc_result_t -+dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name, -+ isc_boolean_t force, isc_stdtime_t now, -+ isc_uint32_t lifetime); -+/*%< -+ * Add a negative trust anchor to 'ntatable' for name 'name', -+ * which will expire at time 'now' + 'lifetime'. If 'force' is ISC_FALSE, -+ * then the name will be checked periodically to see if it's bogus; -+ * if not, then the NTA will be allowed to expire early. -+ * -+ * Notes: -+ * -+ *\li If an NTA already exists in the table, its expiry time -+ * is updated. -+ * -+ * Requires: -+ * -+ *\li 'ntatable' points to a valid ntatable. -+ * -+ *\li 'name' points to a valid name. -+ * -+ * Returns: -+ * -+ *\li ISC_R_SUCCESS -+ * -+ *\li Any other result indicates failure. -+ */ -+ -+isc_result_t -+dns_ntatable_delete(dns_ntatable_t *ntatable, dns_name_t *keyname); -+/*%< -+ * Delete node(s) from 'ntatable' matching name 'keyname' -+ * -+ * Requires: -+ * -+ *\li 'ntatable' points to a valid ntatable. -+ * -+ *\li 'name' is not NULL -+ * -+ * Returns: -+ * -+ *\li ISC_R_SUCCESS -+ * -+ *\li Any other result indicates failure. -+ */ -+ -+isc_result_t -+dns_ntatable_deletenta(dns_ntatable_t *ntatable, dns_name_t *name); -+/*%< -+ * Delete node from 'ntatable' matching the name 'name' -+ * -+ * Requires: -+ * -+ *\li 'ntatable' points to a valid ntatable. -+ *\li 'name' is a valid name. -+ * -+ * Returns: -+ * -+ *\li ISC_R_SUCCESS -+ * -+ *\li Any other result indicates failure. -+ */ -+ -+isc_boolean_t -+dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now, -+ dns_name_t *name, dns_name_t *anchor); -+/*%< -+ * Return ISC_TRUE if 'name' is below a non-expired negative trust -+ * anchor which in turn is at or below 'anchor'. -+ * -+ * If 'ntatable' has not been initialized, return ISC_FALSE. -+ * -+ * Requires: -+ * -+ *\li 'ntatable' is NULL or is a valid ntatable. -+ * -+ *\li 'name' is a valid absolute name. -+ */ -+ -+isc_result_t -+dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t *buf); -+/*%< -+ * Dump the NTA table to buffer 'buf' -+ */ -+ -+isc_result_t -+dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp); -+/*%< -+ * Dump the NTA table to the file opened as 'fp'. -+ */ -+ -+isc_result_t -+dns_ntatable_save(dns_ntatable_t *ntatable, FILE *fp); -+/*%< -+ * Save the NTA table to the file opened as 'fp', for later loading. -+ */ -+ISC_LANG_ENDDECLS -+ -+#endif /* DNS_NTA_H */ -diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h -index e8a712a781..10642f2eab 100644 ---- a/lib/dns/include/dns/resolver.h -+++ b/lib/dns/include/dns/resolver.h -@@ -95,7 +95,10 @@ typedef struct dns_fetchevent { - #define DNS_FETCHOPT_NOVALIDATE 0x20 /*%< Disable validation. */ - #define DNS_FETCHOPT_EDNS512 0x40 /*%< Advertise a 512 byte - UDP buffer. */ --#define DNS_FETCHOPT_WANTNSID 0x80 /*%< Request NSID */ -+#define DNS_FETCHOPT_WANTNSID 0x080 /*%< Request NSID */ -+#define DNS_FETCHOPT_PREFETCH 0x100 /*%< Request NSID */ -+#define DNS_FETCHOPT_NONTA 0x400 /*%< Ignore NTA table. */ -+#define DNS_FETCHOPT_NOCDFLAG 0x200 /*%< Don't set CD flag. */ - - #define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000 - #define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000 -diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h -index 12aacf9ba7..137bfd8567 100644 ---- a/lib/dns/include/dns/result.h -+++ b/lib/dns/include/dns/result.h -@@ -153,8 +153,9 @@ - #define DNS_R_EXPIRED (ISC_RESULTCLASS_DNS + 107) - #define DNS_R_NOTDYNAMIC (ISC_RESULTCLASS_DNS + 108) - #define DNS_R_BADEUI (ISC_RESULTCLASS_DNS + 109) -+#define DNS_R_NTACOVERED (ISC_RESULTCLASS_DNS + 110) - --#define DNS_R_NRESULTS 110 /*%< Number of results */ -+#define DNS_R_NRESULTS 111 /*%< Number of results */ - - /* - * DNS wire format rcodes. -diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h -index 5dc03deac1..d397b063b7 100644 ---- a/lib/dns/include/dns/types.h -+++ b/lib/dns/include/dns/types.h -@@ -95,6 +95,8 @@ typedef isc_region_t dns_label_t; - typedef struct dns_lookup dns_lookup_t; - typedef struct dns_name dns_name_t; - typedef ISC_LIST(dns_name_t) dns_namelist_t; -+typedef struct dns_nta dns_nta_t; -+typedef struct dns_ntatable dns_ntatable_t; - typedef isc_uint16_t dns_opcode_t; - typedef unsigned char dns_offsets_t[128]; - typedef struct dns_order dns_order_t; -diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h -index b3cfe9992f..88c7b8288d 100644 ---- a/lib/dns/include/dns/validator.h -+++ b/lib/dns/include/dns/validator.h -@@ -165,13 +165,16 @@ struct dns_validator { - unsigned int depth; - unsigned int authcount; - unsigned int authfail; -+ isc_stdtime_t start; - }; - - /*% - * dns_validator_create() options. - */ --#define DNS_VALIDATOR_DLV 1U --#define DNS_VALIDATOR_DEFER 2U -+#define DNS_VALIDATOR_DLV 0x0001U -+#define DNS_VALIDATOR_DEFER 0x0002U -+#define DNS_VALIDATOR_NOCDFLAG 0x0004U -+#define DNS_VALIDATOR_NONTA 0x0008U /*% Ignore NTA table */ - - ISC_LANG_BEGINDECLS - -diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h -index 704e5fe3e9..9d8b3373fd 100644 ---- a/lib/dns/include/dns/view.h -+++ b/lib/dns/include/dns/view.h -@@ -190,6 +190,11 @@ struct dns_view { - dns_zone_t * managed_keys; - dns_zone_t * redirect; - -+ dns_ntatable_t * ntatable_priv; /* internal use only */ -+ isc_uint32_t nta_lifetime; -+ isc_uint32_t nta_recheck; -+ char *nta_file; -+ - #ifdef BIND9 - /* File in which to store configuration for newly added zones */ - char * new_zone_file; -@@ -1023,17 +1028,50 @@ dns_view_iscacheshared(dns_view_t *view); - *\li #ISC_FALSE otherwise. - */ - -+isc_result_t -+dns_view_initntatable(dns_view_t *view, -+ isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr); -+/*%< -+ * Initialize the negative trust anchor table for the view. -+ * -+ * Requires: -+ * \li 'view' is valid. -+ * -+ * Returns: -+ *\li ISC_R_SUCCESS -+ *\li Any other result indicates failure -+ */ -+ -+isc_result_t -+dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp); -+/*%< -+ * Get the negative trust anchor table for this view. Returns -+ * ISC_R_NOTFOUND if the table not been initialized for the view. -+ * -+ * '*ntp' is attached on success; the caller is responsible for -+ * detaching it with dns_ntatable_detach(). -+ * -+ * Requires: -+ * \li 'view' is valid. -+ * \li 'nta' is not NULL and '*nta' is NULL. -+ * -+ * Returns: -+ *\li ISC_R_SUCCESS -+ *\li ISC_R_NOTFOUND -+ */ -+ - isc_result_t - dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx); - /*%< -- * Initialize security roots for the view. (Note that secroots is -+ * Initialize security roots for the view, detaching any previously -+ * existing security roots first. (Note that secroots_priv is - * NULL until this function is called, so any function using -- * secroots must check its validity first. One way to do this is -- * use dns_view_getsecroots() and check its return value.) -+ * security roots must check that they have been initialized first. -+ * One way to do this is use dns_view_getsecroots() and check its -+ * return value.) - * - * Requires: - * \li 'view' is valid. -- * \li 'view->secroots' is NULL. - * - * Returns: - *\li ISC_R_SUCCESS -@@ -1060,10 +1098,14 @@ dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp); - - isc_result_t - dns_view_issecuredomain(dns_view_t *view, dns_name_t *name, -- isc_boolean_t *secure_domain); -+ isc_stdtime_t now, isc_boolean_t checknta, -+ isc_boolean_t *secure_domain); - /*%< -- * Is 'name' at or beneath a trusted key? Put answer in -- * '*secure_domain'. -+ * Is 'name' at or beneath a trusted key, and not covered by a valid -+ * negative trust anchor? Put answer in '*secure_domain'. -+ * -+ * If 'checknta' is ISC_FALSE, ignore the NTA table in determining -+ * whether this is a secure domain. - * - * Requires: - * \li 'view' is valid. -@@ -1073,6 +1115,20 @@ dns_view_issecuredomain(dns_view_t *view, dns_name_t *name, - *\li Any other value indicates failure - */ - -+isc_boolean_t -+dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now, -+ dns_name_t *name, dns_name_t *anchor); -+/*%< -+ * Is there a current negative trust anchor above 'name' and below 'anchor'? -+ * -+ * Requires: -+ * \li 'view' is valid. -+ * -+ * Returns: -+ *\li ISC_R_TRUE -+ *\li ISC_R_FALSE -+ */ -+ - void - dns_view_untrust(dns_view_t *view, dns_name_t *keyname, - dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx); -@@ -1111,6 +1167,24 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx, - void - dns_view_restorekeyring(dns_view_t *view); - -+isc_result_t -+dns_view_saventa(dns_view_t *view); -+/*%< -+ * Save NTA for names in this view to a file. -+ * -+ * Requires: -+ *\li 'view' to be valid. -+ */ -+ -+isc_result_t -+dns_view_loadnta(dns_view_t *view); -+/*%< -+ * Loads NTA for names in this view from a file. -+ * -+ * Requires: -+ *\li 'view' to be valid. -+ */ -+ - ISC_LANG_ENDDECLS - - #endif /* DNS_VIEW_H */ -diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c -index c49847f326..c2025b0203 100644 ---- a/lib/dns/keytable.c -+++ b/lib/dns/keytable.c -@@ -174,6 +174,7 @@ insert(dns_keytable_t *keytable, isc_boolean_t managed, - for (k = node->data; k != NULL; k = k->next) { - if (k->key == NULL) { - k->key = *keyp; -+ *keyp = NULL; /* transfer ownership */ - break; - } - if (dst_key_compare(k->key, *keyp) == ISC_TRUE) -@@ -182,7 +183,7 @@ insert(dns_keytable_t *keytable, isc_boolean_t managed, - - if (k == NULL) - result = ISC_R_SUCCESS; -- else -+ else if (*keyp != NULL) - dst_key_free(keyp); - } - -@@ -523,10 +524,10 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep) - - isc_result_t - dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name, -- isc_boolean_t *wantdnssecp) -+ dns_name_t *foundname, isc_boolean_t *wantdnssecp) - { - isc_result_t result; -- void *data; -+ dns_rbtnode_t *node = NULL; - - /* - * Is 'name' at or beneath a trusted key? -@@ -538,11 +539,10 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name, - - RWLOCK(&keytable->rwlock, isc_rwlocktype_read); - -- data = NULL; -- result = dns_rbt_findname(keytable->table, name, 0, NULL, &data); -- -+ result = dns_rbt_findnode(keytable->table, name, foundname, &node, -+ NULL, DNS_RBTFIND_NOOPTIONS, NULL, NULL); - if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { -- INSIST(data != NULL); -+ INSIST(node->data != NULL); - *wantdnssecp = ISC_TRUE; - result = ISC_R_SUCCESS; - } else if (result == ISC_R_NOTFOUND) { -@@ -575,6 +575,8 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) - - dns_rbtnodechain_current(&chain, NULL, NULL, &node); - for (knode = node->data; knode != NULL; knode = knode->next) { -+ if (knode->key == NULL) -+ continue; - dst_key_format(knode->key, pbuf, sizeof(pbuf)); - fprintf(fp, "%s ; %s\n", pbuf, - knode->managed ? "managed" : "trusted"); -diff --git a/lib/dns/log.c b/lib/dns/log.c -index ff9ca6573c..c223e3b603 100644 ---- a/lib/dns/log.c -+++ b/lib/dns/log.c -@@ -84,6 +84,8 @@ LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = { - { "dns/dnssec", 0 }, - { "dns/crypto", 0 }, - { "dns/dyndb", 0 }, -+ { "dns/packets", 0 }, -+ { "dns/nta", 0 }, - { NULL, 0 } - }; - -diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c -index 2717658e69..80fcd4c12d 100644 ---- a/lib/dns/masterdump.c -+++ b/lib/dns/masterdump.c -@@ -158,6 +158,18 @@ dns_master_style_debug = { - 24, 32, 40, 48, 80, 8, UINT_MAX - }; - -+/*% -+ * Similar, but with each line commented out. -+ */ -+LIBDNS_EXTERNAL_DATA const dns_master_style_t -+dns_master_style_comment = { -+ DNS_STYLEFLAG_REL_OWNER | -+ DNS_STYLEFLAG_MULTILINE | -+ DNS_STYLEFLAG_RRCOMMENT | -+ DNS_STYLEFLAG_COMMENTDATA, -+ 24, 32, 40, 48, 80, 8, UINT_MAX -+}; -+ - - #define N_SPACES 10 - static char spaces[N_SPACES+1] = " "; -@@ -291,6 +303,14 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) { - r.base[0] = '\n'; - isc_buffer_add(&buf, 1); - -+ if ((ctx->style.flags & DNS_STYLEFLAG_COMMENTDATA) != 0) { -+ isc_buffer_availableregion(&buf, &r); -+ if (r.length < 1) -+ return (DNS_R_TEXTTOOLONG); -+ r.base[0] = ';'; -+ isc_buffer_add(&buf, 1); -+ } -+ - result = indent(&col, ctx->style.rdata_column, - ctx->style.tab_width, &buf); - /* -@@ -427,6 +447,12 @@ rdataset_totext(dns_rdataset_t *rdataset, - while (result == ISC_R_SUCCESS) { - column = 0; - -+ /* -+ * Comment? -+ */ -+ if ((ctx->style.flags & DNS_STYLEFLAG_COMMENTDATA) != 0) -+ isc_buffer_putstr(target, ";"); -+ - /* - * Owner name. - */ -diff --git a/lib/dns/message.c b/lib/dns/message.c -index 06211751e5..2dba3bc8e7 100644 ---- a/lib/dns/message.c -+++ b/lib/dns/message.c -@@ -3579,6 +3579,54 @@ dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) { - return (ISC_R_SUCCESS); - } - -+void -+dns_message_logpacket(dns_message_t *message, const char *description, -+ isc_logcategory_t *category, isc_logmodule_t *module, -+ int level, isc_mem_t *mctx) -+{ -+ dns_message_logfmtpacket(message, description, category, module, -+ &dns_master_style_debug, level, mctx); -+} -+ -+void -+dns_message_logfmtpacket(dns_message_t *message, const char *description, -+ isc_logcategory_t *category, isc_logmodule_t *module, -+ const dns_master_style_t *style, int level, -+ isc_mem_t *mctx) -+{ -+ isc_buffer_t buffer; -+ char *buf = NULL; -+ int len = 1024; -+ isc_result_t result; -+ -+ if (! isc_log_wouldlog(dns_lctx, level)) -+ return; -+ -+ /* -+ * Note that these are multiline debug messages. We want a newline -+ * to appear in the log after each message. -+ */ -+ -+ do { -+ buf = isc_mem_get(mctx, len); -+ if (buf == NULL) -+ break; -+ isc_buffer_init(&buffer, buf, len); -+ result = dns_message_totext(message, style, 0, &buffer); -+ if (result == ISC_R_NOSPACE) { -+ isc_mem_put(mctx, buf, len); -+ len += 1024; -+ } else if (result == ISC_R_SUCCESS) -+ isc_log_write(dns_lctx, category, module, level, -+ "%s%.*s", description, -+ (int)isc_buffer_usedlength(&buffer), -+ buf); -+ } while (result == ISC_R_NOSPACE); -+ -+ if (buf != NULL) -+ isc_mem_put(mctx, buf, len); -+} -+ - isc_result_t - dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp, - unsigned int version, isc_uint16_t udpsize, -diff --git a/lib/dns/nta.c b/lib/dns/nta.c -new file mode 100644 -index 0000000000..7188c4da30 ---- /dev/null -+++ b/lib/dns/nta.c -@@ -0,0 +1,683 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct dns_nta { -+ unsigned int magic; -+ isc_refcount_t refcount; -+ dns_ntatable_t *ntatable; -+ isc_boolean_t forced; -+ isc_timer_t *timer; -+ dns_fetch_t *fetch; -+ dns_rdataset_t rdataset; -+ dns_rdataset_t sigrdataset; -+ dns_fixedname_t fn; -+ dns_name_t *name; -+ isc_stdtime_t expiry; -+}; -+ -+#define NTA_MAGIC ISC_MAGIC('N', 'T', 'A', 'n') -+#define VALID_NTA(nn) ISC_MAGIC_VALID(nn, NTA_MAGIC) -+ -+/* -+ * Obtain a reference to the nta object. Released by -+ * nta_detach. -+ */ -+static void -+nta_ref(dns_nta_t *nta) { -+ isc_refcount_increment(&nta->refcount, NULL); -+} -+ -+static void -+nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) { -+ unsigned int refs; -+ dns_nta_t *nta = *ntap; -+ -+ REQUIRE(VALID_NTA(nta)); -+ -+ *ntap = NULL; -+ isc_refcount_decrement(&nta->refcount, &refs); -+ if (refs == 0) { -+ nta->magic = 0; -+ if (nta->timer != NULL) { -+ (void) isc_timer_reset(nta->timer, -+ isc_timertype_inactive, -+ NULL, NULL, ISC_TRUE); -+ isc_timer_detach(&nta->timer); -+ } -+ isc_refcount_destroy(&nta->refcount); -+ if (dns_rdataset_isassociated(&nta->rdataset)) -+ dns_rdataset_disassociate(&nta->rdataset); -+ if (dns_rdataset_isassociated(&nta->sigrdataset)) -+ dns_rdataset_disassociate(&nta->sigrdataset); -+ if (nta->fetch != NULL) { -+ dns_resolver_cancelfetch(nta->fetch); -+ dns_resolver_destroyfetch(&nta->fetch); -+ } -+ isc_mem_put(mctx, nta, sizeof(dns_nta_t)); -+ } -+} -+ -+static void -+free_nta(void *data, void *arg) { -+ dns_nta_t *nta = (dns_nta_t *) data; -+ isc_mem_t *mctx = (isc_mem_t *) arg; -+ -+ nta_detach(mctx, &nta); -+} -+ -+isc_result_t -+dns_ntatable_create(dns_view_t *view, -+ isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, -+ dns_ntatable_t **ntatablep) -+{ -+ dns_ntatable_t *ntatable; -+ isc_result_t result; -+ -+ REQUIRE(ntatablep != NULL && *ntatablep == NULL); -+ -+ ntatable = isc_mem_get(view->mctx, sizeof(*ntatable)); -+ if (ntatable == NULL) -+ return (ISC_R_NOMEMORY); -+ -+ ntatable->task = NULL; -+ result = isc_task_create(taskmgr, 0, &ntatable->task); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup_ntatable; -+ isc_task_setname(ntatable->task, "ntatable", ntatable); -+ -+ ntatable->table = NULL; -+ result = dns_rbt_create(view->mctx, free_nta, view->mctx, -+ &ntatable->table); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup_task; -+ -+ result = isc_rwlock_init(&ntatable->rwlock, 0, 0); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup_rbt; -+ -+ ntatable->timermgr = timermgr; -+ ntatable->taskmgr = taskmgr; -+ -+ ntatable->view = view; -+ ntatable->references = 1; -+ -+ ntatable->magic = NTATABLE_MAGIC; -+ *ntatablep = ntatable; -+ -+ return (ISC_R_SUCCESS); -+ -+ cleanup_rbt: -+ dns_rbt_destroy(&ntatable->table); -+ -+ cleanup_task: -+ isc_task_detach(&ntatable->task); -+ -+ cleanup_ntatable: -+ isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable)); -+ -+ return (result); -+} -+ -+void -+dns_ntatable_attach(dns_ntatable_t *source, dns_ntatable_t **targetp) { -+ REQUIRE(VALID_NTATABLE(source)); -+ REQUIRE(targetp != NULL && *targetp == NULL); -+ -+ RWLOCK(&source->rwlock, isc_rwlocktype_write); -+ -+ INSIST(source->references > 0); -+ source->references++; -+ INSIST(source->references != 0); -+ -+ RWUNLOCK(&source->rwlock, isc_rwlocktype_write); -+ -+ *targetp = source; -+} -+ -+void -+dns_ntatable_detach(dns_ntatable_t **ntatablep) { -+ isc_boolean_t destroy = ISC_FALSE; -+ dns_ntatable_t *ntatable; -+ -+ REQUIRE(ntatablep != NULL && VALID_NTATABLE(*ntatablep)); -+ -+ ntatable = *ntatablep; -+ *ntatablep = NULL; -+ -+ RWLOCK(&ntatable->rwlock, isc_rwlocktype_write); -+ INSIST(ntatable->references > 0); -+ ntatable->references--; -+ if (ntatable->references == 0) -+ destroy = ISC_TRUE; -+ RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write); -+ -+ if (destroy) { -+ dns_rbt_destroy(&ntatable->table); -+ isc_rwlock_destroy(&ntatable->rwlock); -+ if (ntatable->task != NULL) -+ isc_task_detach(&ntatable->task); -+ ntatable->timermgr = NULL; -+ ntatable->taskmgr = NULL; -+ ntatable->magic = 0; -+ isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable)); -+ } -+} -+ -+static void -+fetch_done(isc_task_t *task, isc_event_t *event) { -+ dns_fetchevent_t *devent = (dns_fetchevent_t *)event; -+ dns_nta_t *nta = devent->ev_arg; -+ isc_result_t eresult = devent->result; -+ dns_ntatable_t *ntatable = nta->ntatable; -+ dns_view_t *view = ntatable->view; -+ isc_stdtime_t now = 0; -+ -+ UNUSED(task); -+ -+ if (dns_rdataset_isassociated(&nta->rdataset)) -+ dns_rdataset_disassociate(&nta->rdataset); -+ if (dns_rdataset_isassociated(&nta->sigrdataset)) -+ dns_rdataset_disassociate(&nta->sigrdataset); -+ if (nta->fetch == devent->fetch) -+ nta->fetch = NULL; -+ dns_resolver_destroyfetch(&devent->fetch); -+ -+ if (devent->node != NULL) -+ dns_db_detachnode(devent->db, &devent->node); -+ if (devent->db != NULL) -+ dns_db_detach(&devent->db); -+ -+ isc_event_free(&event); -+ -+ switch (eresult) { -+ case ISC_R_SUCCESS: -+ case DNS_R_NCACHENXDOMAIN: -+ case DNS_R_NXDOMAIN: -+ case DNS_R_NCACHENXRRSET: -+ case DNS_R_NXRRSET: -+ isc_stdtime_get(&now); -+ nta->expiry = now; -+ break; -+ default: -+ break; -+ } -+ -+ /* -+ * If we're expiring before the next recheck, we might -+ * as well stop the timer now. -+ */ -+ if (nta->timer != NULL && nta->expiry - now < ntatable->recheck) -+ (void) isc_timer_reset(nta->timer, isc_timertype_inactive, -+ NULL, NULL, ISC_TRUE); -+ nta_detach(view->mctx, &nta); -+} -+ -+static void -+checkbogus(isc_task_t *task, isc_event_t *event) { -+ dns_nta_t *nta = event->ev_arg; -+ dns_ntatable_t *ntatable = nta->ntatable; -+ dns_view_t *view = ntatable->view; -+ isc_result_t result; -+ -+ if (nta->fetch != NULL) { -+ dns_resolver_cancelfetch(nta->fetch); -+ nta->fetch = NULL; -+ } -+ if (dns_rdataset_isassociated(&nta->rdataset)) -+ dns_rdataset_disassociate(&nta->rdataset); -+ if (dns_rdataset_isassociated(&nta->sigrdataset)) -+ dns_rdataset_disassociate(&nta->sigrdataset); -+ -+ isc_event_free(&event); -+ -+ nta_ref(nta); -+ result = dns_resolver_createfetch(view->resolver, nta->name, -+ dns_rdatatype_nsec, -+ NULL, NULL, NULL, -+ DNS_FETCHOPT_NONTA, -+ task, fetch_done, nta, -+ &nta->rdataset, -+ &nta->sigrdataset, -+ &nta->fetch); -+ if (result != ISC_R_SUCCESS) -+ nta_detach(view->mctx, &nta); -+} -+ -+static isc_result_t -+settimer(dns_ntatable_t *ntatable, dns_nta_t *nta, isc_uint32_t lifetime) { -+ isc_result_t result; -+ isc_interval_t interval; -+ dns_view_t *view; -+ -+ REQUIRE(VALID_NTATABLE(ntatable)); -+ REQUIRE(VALID_NTA(nta)); -+ -+ if (ntatable->timermgr == NULL) -+ return (ISC_R_SUCCESS); -+ -+ view = ntatable->view; -+ if (view->nta_recheck == 0 || lifetime <= view->nta_recheck) -+ return (ISC_R_SUCCESS); -+ -+ isc_interval_set(&interval, view->nta_recheck, 0); -+ result = isc_timer_create(ntatable->timermgr, isc_timertype_ticker, -+ NULL, &interval, ntatable->task, -+ checkbogus, nta, &nta->timer); -+ return (result); -+} -+ -+static isc_result_t -+nta_create(dns_ntatable_t *ntatable, dns_name_t *name, dns_nta_t **target) { -+ isc_result_t result; -+ dns_nta_t *nta = NULL; -+ dns_view_t *view; -+ -+ REQUIRE(VALID_NTATABLE(ntatable)); -+ REQUIRE(target != NULL && *target == NULL); -+ -+ view = ntatable->view; -+ -+ nta = isc_mem_get(view->mctx, sizeof(dns_nta_t)); -+ if (nta == NULL) -+ return (ISC_R_NOMEMORY); -+ -+ nta->ntatable = ntatable; -+ nta->expiry = 0; -+ nta->timer = NULL; -+ nta->fetch = NULL; -+ dns_rdataset_init(&nta->rdataset); -+ dns_rdataset_init(&nta->sigrdataset); -+ -+ result = isc_refcount_init(&nta->refcount, 1); -+ if (result != ISC_R_SUCCESS) { -+ isc_mem_put(view->mctx, nta, sizeof(dns_nta_t)); -+ return (result); -+ } -+ -+ dns_fixedname_init(&nta->fn); -+ nta->name = dns_fixedname_name(&nta->fn); -+ dns_name_copy(name, nta->name, NULL); -+ -+ nta->magic = NTA_MAGIC; -+ -+ *target = nta; -+ return (ISC_R_SUCCESS); -+} -+ -+isc_result_t -+dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name, -+ isc_boolean_t force, isc_stdtime_t now, -+ isc_uint32_t lifetime) -+{ -+ isc_result_t result; -+ dns_nta_t *nta = NULL; -+ dns_rbtnode_t *node; -+ dns_view_t *view; -+ -+ REQUIRE(VALID_NTATABLE(ntatable)); -+ -+ view = ntatable->view; -+ -+ result = nta_create(ntatable, name, &nta); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ -+ nta->expiry = now + lifetime; -+ nta->forced = force; -+ -+ RWLOCK(&ntatable->rwlock, isc_rwlocktype_write); -+ -+ node = NULL; -+ result = dns_rbt_addnode(ntatable->table, name, &node); -+ if (result == ISC_R_SUCCESS) { -+ if (!force) -+ (void)settimer(ntatable, nta, lifetime); -+ node->data = nta; -+ nta = NULL; -+ } else if (result == ISC_R_EXISTS) { -+ dns_nta_t *n = node->data; -+ if (n == NULL) { -+ if (!force) -+ (void)settimer(ntatable, nta, lifetime); -+ node->data = nta; -+ nta = NULL; -+ } else { -+ n->expiry = nta->expiry; -+ nta_detach(view->mctx, &nta); -+ } -+ result = ISC_R_SUCCESS; -+ } -+ -+ RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write); -+ -+ if (nta != NULL) -+ nta_detach(view->mctx, &nta); -+ -+ return (result); -+} -+ -+/* -+ * Caller must hold a write lock on rwlock. -+ */ -+static isc_result_t -+delete(dns_ntatable_t *ntatable, dns_name_t *name) { -+ isc_result_t result; -+ dns_rbtnode_t *node = NULL; -+ -+ REQUIRE(VALID_NTATABLE(ntatable)); -+ REQUIRE(name != NULL); -+ -+ result = dns_rbt_findnode(ntatable->table, name, NULL, &node, NULL, -+ DNS_RBTFIND_NOOPTIONS, NULL, NULL); -+ if (result == ISC_R_SUCCESS) { -+ if (node->data != NULL) -+ result = dns_rbt_deletenode(ntatable->table, -+ node, ISC_FALSE); -+ else -+ result = ISC_R_NOTFOUND; -+ } else if (result == DNS_R_PARTIALMATCH) -+ result = ISC_R_NOTFOUND; -+ -+ return (result); -+} -+ -+isc_result_t -+dns_ntatable_delete(dns_ntatable_t *ntatable, dns_name_t *name) { -+ isc_result_t result; -+ -+ RWLOCK(&ntatable->rwlock, isc_rwlocktype_write); -+ result = delete(ntatable, name); -+ RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write); -+ -+ return (result); -+} -+ -+isc_boolean_t -+dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now, -+ dns_name_t *name, dns_name_t *anchor) -+{ -+ isc_result_t result; -+ dns_fixedname_t fn; -+ dns_rbtnode_t *node; -+ dns_name_t *foundname; -+ dns_nta_t *nta = NULL; -+ isc_boolean_t answer = ISC_FALSE; -+ isc_rwlocktype_t locktype = isc_rwlocktype_read; -+ -+ REQUIRE(ntatable == NULL || VALID_NTATABLE(ntatable)); -+ REQUIRE(dns_name_isabsolute(name)); -+ -+ if (ntatable == NULL) -+ return (ISC_FALSE); -+ -+ dns_fixedname_init(&fn); -+ foundname = dns_fixedname_name(&fn); -+ -+ relock: -+ RWLOCK(&ntatable->rwlock, locktype); -+ again: -+ node = NULL; -+ result = dns_rbt_findnode(ntatable->table, name, foundname, &node, NULL, -+ DNS_RBTFIND_NOOPTIONS, NULL, NULL); -+ if (result == DNS_R_PARTIALMATCH) { -+ if (dns_name_issubdomain(foundname, anchor)) -+ result = ISC_R_SUCCESS; -+ } -+ if (result == ISC_R_SUCCESS) { -+ nta = (dns_nta_t *) node->data; -+ answer = ISC_TF(nta->expiry >= now); -+ } -+ -+ /* Deal with expired NTA */ -+ if (result == ISC_R_SUCCESS && !answer) { -+ char nb[DNS_NAME_FORMATSIZE]; -+ -+ if (locktype == isc_rwlocktype_read) { -+ RWUNLOCK(&ntatable->rwlock, locktype); -+ locktype = isc_rwlocktype_write; -+ goto relock; -+ } -+ -+ dns_name_format(foundname, nb, sizeof(nb)); -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, -+ DNS_LOGMODULE_NTA, ISC_LOG_INFO, -+ "deleting expired NTA at %s", nb); -+ -+ if (nta->timer != NULL) { -+ (void) isc_timer_reset(nta->timer, -+ isc_timertype_inactive, -+ NULL, NULL, ISC_TRUE); -+ isc_timer_detach(&nta->timer); -+ } -+ -+ result = delete(ntatable, foundname); -+ if (result != ISC_R_SUCCESS) { -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, -+ DNS_LOGMODULE_NTA, ISC_LOG_INFO, -+ "deleting NTA failed: %s", -+ isc_result_totext(result)); -+ } -+ goto again; -+ } -+ RWUNLOCK(&ntatable->rwlock, locktype); -+ -+ return (answer); -+} -+ -+isc_result_t -+dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t *buf) { -+ isc_result_t result; -+ dns_rbtnode_t *node; -+ dns_rbtnodechain_t chain; -+ isc_boolean_t first = ISC_TRUE; -+ isc_stdtime_t now; -+ -+ REQUIRE(VALID_NTATABLE(ntatable)); -+ -+ isc_stdtime_get(&now); -+ -+ RWLOCK(&ntatable->rwlock, isc_rwlocktype_read); -+ dns_rbtnodechain_init(&chain, ntatable->view->mctx); -+ result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL); -+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) -+ goto cleanup; -+ for (;;) { -+ dns_rbtnodechain_current(&chain, NULL, NULL, &node); -+ if (node->data != NULL) { -+ dns_nta_t *n = (dns_nta_t *) node->data; -+ char nbuf[DNS_NAME_FORMATSIZE], tbuf[80]; -+ char obuf[DNS_NAME_FORMATSIZE + 200]; -+ dns_fixedname_t fn; -+ dns_name_t *name; -+ isc_time_t t; -+ -+ dns_fixedname_init(&fn); -+ name = dns_fixedname_name(&fn); -+ dns_rbt_fullnamefromnode(node, name); -+ dns_name_format(name, nbuf, sizeof(nbuf)); -+ isc_time_set(&t, n->expiry, 0); -+ isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); -+ -+ snprintf(obuf, sizeof(obuf), "%s%s: %s %s", -+ first ? "" : "\n", nbuf, -+ n->expiry < now ? "expired" : "expiry", -+ tbuf); -+ first = ISC_FALSE; -+ if (1+strlen(obuf) >= isc_buffer_availablelength(buf)) { -+ result = ISC_R_NOSPACE; -+ goto cleanup; -+ } else -+ isc_buffer_putstr(buf, obuf); -+ } -+ result = dns_rbtnodechain_next(&chain, NULL, NULL); -+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { -+ if (result == ISC_R_NOMORE) -+ result = ISC_R_SUCCESS; -+ break; -+ } -+ } -+ -+ cleanup: -+ if (isc_buffer_availablelength(buf) != 0) -+ isc_buffer_putuint8(buf, 0); -+ -+ dns_rbtnodechain_invalidate(&chain); -+ RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read); -+ return (result); -+} -+ -+isc_result_t -+dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) { -+ isc_result_t result; -+ dns_rbtnode_t *node; -+ dns_rbtnodechain_t chain; -+ isc_stdtime_t now; -+ -+ REQUIRE(VALID_NTATABLE(ntatable)); -+ -+ isc_stdtime_get(&now); -+ -+ RWLOCK(&ntatable->rwlock, isc_rwlocktype_read); -+ dns_rbtnodechain_init(&chain, ntatable->view->mctx); -+ result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL); -+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) -+ goto cleanup; -+ for (;;) { -+ dns_rbtnodechain_current(&chain, NULL, NULL, &node); -+ if (node->data != NULL) { -+ dns_nta_t *n = (dns_nta_t *) node->data; -+ char nbuf[DNS_NAME_FORMATSIZE], tbuf[80]; -+ dns_fixedname_t fn; -+ dns_name_t *name; -+ isc_time_t t; -+ -+ dns_fixedname_init(&fn); -+ name = dns_fixedname_name(&fn); -+ dns_rbt_fullnamefromnode(node, name); -+ dns_name_format(name, nbuf, sizeof(nbuf)); -+ isc_time_set(&t, n->expiry, 0); -+ isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); -+ fprintf(fp, "%s: %s %s\n", nbuf, -+ n->expiry < now ? "expired" : "expiry", -+ tbuf); -+ } -+ result = dns_rbtnodechain_next(&chain, NULL, NULL); -+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { -+ if (result == ISC_R_NOMORE) -+ result = ISC_R_SUCCESS; -+ break; -+ } -+ } -+ -+ cleanup: -+ dns_rbtnodechain_invalidate(&chain); -+ RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read); -+ return (result); -+} -+ -+isc_result_t -+dns_ntatable_save(dns_ntatable_t *ntatable, FILE *fp) { -+ isc_result_t result; -+ dns_rbtnode_t *node; -+ dns_rbtnodechain_t chain; -+ isc_stdtime_t now; -+ isc_boolean_t written = ISC_FALSE; -+ -+ REQUIRE(VALID_NTATABLE(ntatable)); -+ -+ isc_stdtime_get(&now); -+ -+ RWLOCK(&ntatable->rwlock, isc_rwlocktype_read); -+ dns_rbtnodechain_init(&chain, ntatable->view->mctx); -+ result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL); -+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) -+ goto cleanup; -+ -+ for (;;) { -+ dns_rbtnodechain_current(&chain, NULL, NULL, &node); -+ if (node->data != NULL) { -+ dns_nta_t *n = (dns_nta_t *) node->data; -+ if (now <= n->expiry) { -+ isc_buffer_t b; -+ char nbuf[DNS_NAME_FORMATSIZE + 1], tbuf[80]; -+ dns_fixedname_t fn; -+ dns_name_t *name; -+ -+ dns_fixedname_init(&fn); -+ name = dns_fixedname_name(&fn); -+ dns_rbt_fullnamefromnode(node, name); -+ -+ isc_buffer_init(&b, nbuf, sizeof(nbuf) - 1); -+ result = dns_name_totext(name, ISC_FALSE, &b); -+ if (result != ISC_R_SUCCESS) -+ goto skip; -+ -+ /* Zero terminate. */ -+ isc_buffer_putuint8(&b, 0); -+ -+ isc_buffer_init(&b, tbuf, sizeof(tbuf)); -+ dns_time32_totext(n->expiry, &b); -+ -+ fprintf(fp, "%s %s %s\n", nbuf, -+ n->forced ? "forced" : "regular", -+ tbuf); -+ written = ISC_TRUE; -+ } -+ } -+ skip: -+ result = dns_rbtnodechain_next(&chain, NULL, NULL); -+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { -+ if (result == ISC_R_NOMORE) -+ result = ISC_R_SUCCESS; -+ break; -+ } -+ } -+ -+ cleanup: -+ dns_rbtnodechain_invalidate(&chain); -+ RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read); -+ -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ else -+ return (written ? ISC_R_SUCCESS : ISC_R_NOTFOUND); -+} -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 619646f1d5..79aea7b399 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -1679,6 +1679,30 @@ add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) { - ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link); - } - -+static isc_result_t -+issecuredomain(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, -+ isc_stdtime_t now, isc_boolean_t checknta, -+ isc_boolean_t *issecure) -+{ -+ dns_name_t suffix; -+ unsigned int labels; -+ -+ /* -+ * For DS variants we need to check fom the parent domain, -+ * since there may be a negative trust anchor for the name, -+ * while the enclosing domain where the DS record lives is -+ * under a secure entry point. -+ */ -+ labels = dns_name_countlabels(name); -+ if (dns_rdatatype_atparent(type) && labels > 1) { -+ dns_name_init(&suffix, NULL); -+ dns_name_getlabelsequence(name, 1, labels - 1, &suffix); -+ name = &suffix; -+ } -+ -+ return (dns_view_issecuredomain(view, name, now, checknta, issecure)); -+} -+ - static isc_result_t - resquery_send(resquery_t *query) { - fetchctx_t *fctx; -@@ -1768,14 +1792,23 @@ resquery_send(resquery_t *query) { - fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD; - - /* -- * Set CD if the client says don't validate or the question is -- * under a secure entry point. -+ * Set CD if the client says not to validate, or if the -+ * question is under a secure entry point and this is a -+ * recursive/forward query -- unless the client said not to. - */ -- if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) { -+ if ((query->options & DNS_FETCHOPT_NOCDFLAG) != 0) -+ /* Do nothing */ -+ ; -+ else if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) - fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD; -- } else if (res->view->enablevalidation) { -- result = dns_view_issecuredomain(res->view, &fctx->name, -- &secure_domain); -+ else if (res->view->enablevalidation && -+ ((fctx->qmessage->flags & DNS_MESSAGEFLAG_RD) != 0)) -+ { -+ isc_boolean_t checknta = -+ ISC_TF((query->options & DNS_FETCHOPT_NONTA) == 0); -+ result = issecuredomain(res->view, &fctx->name, -+ fctx->type, query->start.seconds, -+ checknta, &secure_domain); - if (result != ISC_R_SUCCESS) - secure_domain = ISC_FALSE; - if (res->view->dlv != NULL) -@@ -2402,8 +2435,8 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason, - isc_sockaddr_format(address, addrbuf, sizeof(addrbuf)); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS, - DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, -- "error (%s%s%s) resolving '%s/%s/%s': %s", -- dns_result_totext(reason), spc, code, -+ "%s%s%s resolving '%s/%s/%s': %s", -+ code, spc, dns_result_totext(reason), - namebuf, typebuf, classbuf, addrbuf); - } - -@@ -4612,6 +4645,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, - isc_task_t *task; - isc_boolean_t fail; - unsigned int valoptions = 0; -+ isc_boolean_t checknta = ISC_TRUE; - - /* - * The appropriate bucket lock must be held. -@@ -4628,18 +4662,26 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, - /* - * Is DNSSEC validation required for this name? - */ -+ if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) { -+ valoptions |= DNS_VALIDATOR_NONTA; -+ checknta = ISC_FALSE; -+ } -+ - if (res->view->enablevalidation) { -- result = dns_view_issecuredomain(res->view, name, -- &secure_domain); -+ result = issecuredomain(res->view, name, fctx->type, -+ now, checknta, &secure_domain); - if (result != ISC_R_SUCCESS) - return (result); - - if (!secure_domain && res->view->dlv != NULL) { -- valoptions = DNS_VALIDATOR_DLV; -+ valoptions |= DNS_VALIDATOR_DLV; - secure_domain = ISC_TRUE; - } - } - -+ if ((fctx->options & DNS_FETCHOPT_NOCDFLAG) != 0) -+ valoptions |= DNS_VALIDATOR_NOCDFLAG; -+ - if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0) - need_validation = ISC_FALSE; - else -@@ -5110,6 +5152,7 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, - dns_fetchevent_t *event; - isc_uint32_t ttl; - unsigned int valoptions = 0; -+ isc_boolean_t checknta = ISC_TRUE; - - FCTXTRACE("ncache_message"); - -@@ -5132,18 +5175,26 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, - /* - * Is DNSSEC validation required for this name? - */ -+ if ((fctx->options & DNS_FETCHOPT_NONTA) != 0) { -+ valoptions |= DNS_VALIDATOR_NONTA; -+ checknta = ISC_FALSE; -+ } -+ - if (fctx->res->view->enablevalidation) { -- result = dns_view_issecuredomain(res->view, name, -- &secure_domain); -+ result = issecuredomain(res->view, name, fctx->type, -+ now, checknta, &secure_domain); - if (result != ISC_R_SUCCESS) - return (result); - - if (!secure_domain && res->view->dlv != NULL) { -- valoptions = DNS_VALIDATOR_DLV; -+ valoptions |= DNS_VALIDATOR_DLV; - secure_domain = ISC_TRUE; - } - } - -+ if ((fctx->options & DNS_FETCHOPT_NOCDFLAG) != 0) -+ valoptions |= DNS_VALIDATOR_NOCDFLAG; -+ - if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0) - need_validation = ISC_FALSE; - else -@@ -6545,7 +6596,8 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) { - FCTXTRACE("continuing to look for parent's NS records"); - result = dns_resolver_createfetch(fctx->res, &fctx->nsname, - dns_rdatatype_ns, domain, -- nsrdataset, NULL, 0, task, -+ nsrdataset, NULL, -+ fctx->options, task, - resume_dslookup, fctx, - &fctx->nsrrset, NULL, - &fctx->nsfetch); -@@ -6654,43 +6706,6 @@ log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query, - return; - } - --static void --log_packet(dns_message_t *message, int level, isc_mem_t *mctx) { -- isc_buffer_t buffer; -- char *buf = NULL; -- int len = 1024; -- isc_result_t result; -- -- if (! isc_log_wouldlog(dns_lctx, level)) -- return; -- -- /* -- * Note that these are multiline debug messages. We want a newline -- * to appear in the log after each message. -- */ -- -- do { -- buf = isc_mem_get(mctx, len); -- if (buf == NULL) -- break; -- isc_buffer_init(&buffer, buf, len); -- result = dns_message_totext(message, &dns_master_style_debug, -- 0, &buffer); -- if (result == ISC_R_NOSPACE) { -- isc_mem_put(mctx, buf, len); -- len += 1024; -- } else if (result == ISC_R_SUCCESS) -- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, -- DNS_LOGMODULE_RESOLVER, level, -- "received packet:\n%.*s", -- (int)isc_buffer_usedlength(&buffer), -- buf); -- } while (result == ISC_R_NOSPACE); -- -- if (buf != NULL) -- isc_mem_put(mctx, buf, len); --} -- - static isc_boolean_t - iscname(fetchctx_t *fctx) { - isc_result_t result; -@@ -6746,7 +6761,7 @@ process_opt(resquery_t *query, dns_rdataset_t *opt) { - case DNS_OPT_NSID: - if (query->options & DNS_FETCHOPT_WANTNSID) - log_nsid(&optbuf, optlen, query, -- ISC_LOG_INFO, -+ ISC_LOG_DEBUG(3), - query->fctx->res->mctx); - isc_buffer_forward(&optbuf, optlen); - break; -@@ -6948,14 +6963,18 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - /* - * Log the incoming packet. - */ -- log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx); -+ dns_message_logfmtpacket(message, "received packet:\n", -+ DNS_LOGCATEGORY_RESOLVER, -+ DNS_LOGMODULE_PACKETS, -+ &dns_master_style_comment, -+ ISC_LOG_DEBUG(10), -+ fctx->res->mctx); - - if (message->rdclass != fctx->res->rdclass) { - resend = ISC_TRUE; - FCTXTRACE("bad class"); - goto done; - } -- - /* - * Process receive opt record. - */ -@@ -7480,7 +7499,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - - result = dns_resolver_createfetch(fctx->res, &fctx->nsname, - dns_rdatatype_ns, -- NULL, NULL, NULL, 0, task, -+ NULL, NULL, NULL, -+ fctx->options, task, - resume_dslookup, fctx, - &fctx->nsrrset, NULL, - &fctx->nsfetch); -@@ -7786,6 +7806,7 @@ dns_resolver_create(dns_view_t *view, - result = isc_task_create(taskmgr, 0, &task); - if (result != ISC_R_SUCCESS) - goto cleanup_primelock; -+ isc_task_setname(task, "resolver_task", NULL); - - result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL, - task, spillattimer_countdown, res, -@@ -8126,7 +8147,7 @@ log_fetch(dns_name_t *name, dns_rdatatype_t type) { - - isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, - DNS_LOGMODULE_RESOLVER, level, -- "createfetch: %s %s", namebuf, typebuf); -+ "fetch: %s/%s", namebuf, typebuf); - } - - isc_result_t -diff --git a/lib/dns/result.c b/lib/dns/result.c -index 39879532d4..4834cb227c 100644 ---- a/lib/dns/result.c -+++ b/lib/dns/result.c -@@ -162,7 +162,8 @@ static const char *text[DNS_R_NRESULTS] = { - "broken trust chain", /*%< 106 DNS_R_BROKENCHAIN */ - "expired", /*%< 107 DNS_R_EXPIRED */ - "not dynamic", /*%< 108 DNS_R_NOTDYNAMIC */ -- "bad EUI" /*%< 109 DNS_R_BADEUI */ -+ "bad EUI", /*%< 109 DNS_R_BADEUI */ -+ "covered by negative trust anchor", /*%< 110 DNS_R_NTACOVERED */ - }; - - static const char *rcode_text[DNS_R_NRCODERESULTS] = { -diff --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in -index 023e60cead..4bd189f5c7 100644 ---- a/lib/dns/tests/Makefile.in -+++ b/lib/dns/tests/Makefile.in -@@ -41,14 +41,15 @@ OBJS = dnstest.@O@ - SRCS = dnstest.c gost_test.c master_test.c dbiterator_test.c time_test.c \ - private_test.c tsig_test.c update_test.c zonemgr_test.c zt_test.c \ - dbdiff_test.c geoip_test.c dispatch_test.c nsec3_test.c \ -- rdataset_test.c rdata_test.c -+ rdataset_test.c rdata_test.c keytable_test.c - - SUBDIRS = - TARGETS = gost_test@EXEEXT@ master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \ - private_test@EXEEXT@ tsig_test@EXEEXT@ update_test@EXEEXT@ zonemgr_test@EXEEXT@ \ - zt_test@EXEEXT@ dbversion_test@EXEEXT@ dbdiff_test@EXEEXT@ geoip_test@EXEEXT@ \ - dispatch_test@EXEEXT@ nsec3_test@EXEEXT@ \ -- rdataset_test@EXEEXT@ rdata_test@EXEEXT@ -+ rdataset_test@EXEEXT@ rdata_test@EXEEXT@ \ -+ keytable_test@EXEEXT@ \ - - @BIND9_MAKE_RULES@ - -@@ -65,6 +66,11 @@ master_test@EXEEXT@: master_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - master_test.@O@ dnstest.@O@ ${DNSLIBS} \ - ${ISCLIBS} ${LIBS} - -+keytable_test@EXEEXT@: keytable_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ -+ keytable_test.@O@ dnstest.@O@ ${DNSLIBS} \ -+ ${ISCLIBS} ${LIBS} -+ - time_test@EXEEXT@: time_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ - time_test.@O@ dnstest.@O@ ${DNSLIBS} \ -diff --git a/lib/dns/tests/dnstest.c b/lib/dns/tests/dnstest.c -index f06f526eb3..4f96a9c6b7 100644 ---- a/lib/dns/tests/dnstest.c -+++ b/lib/dns/tests/dnstest.c -@@ -43,8 +43,6 @@ - #include - #include - --#include -- - #include "dnstest.h" - - isc_mem_t *mctx = NULL; -@@ -187,6 +185,26 @@ dns_test_end() { - isc_mem_destroy(&mctx); - } - -+/* -+ * Create a view. -+ */ -+isc_result_t -+dns_test_makeview(const char *name, dns_view_t **viewp) -+{ -+ isc_result_t result; -+ dns_view_t *view = NULL; -+ -+ CHECK(dns_view_create(mctx, dns_rdataclass_in, name, &view)); -+ *viewp = view; -+ -+ return (ISC_R_SUCCESS); -+ -+ cleanup: -+ if (view != NULL) -+ dns_view_detach(&view); -+ return (result); -+} -+ - /* - * Create a zone with origin 'name', return a pointer to the zone object in - * 'zonep'. If 'view' is set, add the zone to that view; otherwise, create -diff --git a/lib/dns/tests/dnstest.h b/lib/dns/tests/dnstest.h -index 863ffb6aa5..cd430477b3 100644 ---- a/lib/dns/tests/dnstest.h -+++ b/lib/dns/tests/dnstest.h -@@ -57,6 +57,9 @@ dns_test_begin(FILE *logfile, isc_boolean_t create_managers); - void - dns_test_end(void); - -+isc_result_t -+dns_test_makeview(const char *name, dns_view_t **viewp); -+ - isc_result_t - dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view, - isc_boolean_t keepview); -diff --git a/lib/dns/tests/keytable_test.c b/lib/dns/tests/keytable_test.c -new file mode 100644 -index 0000000000..c41e4081df ---- /dev/null -+++ b/lib/dns/tests/keytable_test.c -@@ -0,0 +1,611 @@ -+/* -+ * Copyright (c) 2014 Infoblox Inc. All Rights Reserved. -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "dnstest.h" -+ -+dns_keytable_t *keytable = NULL; -+dns_ntatable_t *ntatable = NULL; -+ -+static const char *keystr1 = "BQEAAAABok+vaUC9neRv8yeT/FEGgN7svR8s7VBUVSBd8NsAiV8AlaAg O5FHar3JQd95i/puZos6Vi6at9/JBbN8qVmO2AuiXxVqfxMKxIcy+LEB 0Vw4NaSJ3N3uaVREso6aTSs98H/25MjcwLOr7SFfXA7bGhZatLtYY/xu kp6Km5hMfkE="; -+static const dns_keytag_t keytag1 = 30591; -+ -+static const char *keystr2 = "BQEAAAABwuHz9Cem0BJ0JQTO7C/a3McR6hMaufljs1dfG/inaJpYv7vH XTrAOm/MeKp+/x6eT4QLru0KoZkvZJnqTI8JyaFTw2OM/ItBfh/hL2lm Cft2O7n3MfeqYtvjPnY7dWghYW4sVfH7VVEGm958o9nfi79532Qeklxh x8pXWdeAaRU="; -+ -+static dns_view_t *view = NULL; -+ -+/* -+ * Test utilities. In general, these assume input parameters are valid -+ * (checking with ATF_REQUIRE_EQ, thus aborting if not) and unlikely run time -+ * errors (such as memory allocation failure) won't happen. This helps keep -+ * the test code concise. -+ */ -+ -+/* -+ * Utility to convert C-string to dns_name_t. Return a pointer to -+ * static data, and so is not thread safe. -+ */ -+static dns_name_t * -+str2name(const char *namestr) { -+ static dns_fixedname_t fname; -+ static dns_name_t *name; -+ static isc_buffer_t namebuf; -+ void *deconst_namestr; -+ -+ dns_fixedname_init(&fname); -+ name = dns_fixedname_name(&fname); -+ DE_CONST(namestr, deconst_namestr); /* OK, since we don't modify it */ -+ isc_buffer_init(&namebuf, deconst_namestr, strlen(deconst_namestr)); -+ isc_buffer_add(&namebuf, strlen(namestr)); -+ ATF_REQUIRE_EQ(dns_name_fromtext(name, &namebuf, dns_rootname, 0, -+ NULL), ISC_R_SUCCESS); -+ -+ return (name); -+} -+ -+static void -+create_key(isc_uint16_t flags, isc_uint8_t proto, isc_uint8_t alg, -+ const char *keynamestr, const char *keystr, dst_key_t **target) -+{ -+ dns_rdata_dnskey_t keystruct; -+ unsigned char keydata[4096]; -+ isc_buffer_t keydatabuf; -+ unsigned char rrdata[4096]; -+ isc_buffer_t rrdatabuf; -+ isc_region_t r; -+ const dns_rdataclass_t rdclass = dns_rdataclass_in; /* for brevity */ -+ -+ keystruct.common.rdclass = rdclass; -+ keystruct.common.rdtype = dns_rdatatype_dnskey; -+ keystruct.mctx = NULL; -+ ISC_LINK_INIT(&keystruct.common, link); -+ keystruct.flags = flags; -+ keystruct.protocol = proto; -+ keystruct.algorithm = alg; -+ -+ isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); -+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); -+ ATF_REQUIRE_EQ(isc_base64_decodestring(keystr, &keydatabuf), -+ ISC_R_SUCCESS); -+ isc_buffer_usedregion(&keydatabuf, &r); -+ keystruct.datalen = r.length; -+ keystruct.data = r.base; -+ ATF_REQUIRE_EQ(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, -+ keystruct.common.rdtype, -+ &keystruct, &rrdatabuf), -+ ISC_R_SUCCESS); -+ -+ ATF_REQUIRE_EQ(dst_key_fromdns(str2name(keynamestr), rdclass, -+ &rrdatabuf, mctx, target), -+ ISC_R_SUCCESS); -+} -+ -+/* Common setup: create a keytable and ntatable to test with a few keys */ -+static void -+create_tables() { -+ isc_result_t result; -+ dst_key_t *key = NULL; -+ isc_stdtime_t now; -+ -+ result = dns_test_makeview("view", &view); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ ATF_REQUIRE_EQ(dns_keytable_create(mctx, &keytable), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_ntatable_create(view, taskmgr, timermgr, -+ &ntatable), ISC_R_SUCCESS); -+ -+ /* Add a normal key */ -+ create_key(257, 3, 5, "example.com", keystr1, &key); -+ ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key), -+ ISC_R_SUCCESS); -+ -+ /* Add a null key */ -+ ATF_REQUIRE_EQ(dns_keytable_marksecure(keytable, -+ str2name("null.example")), -+ ISC_R_SUCCESS); -+ -+ /* Add a negative trust anchor, duration 1 hour */ -+ isc_stdtime_get(&now); -+ ATF_REQUIRE_EQ(dns_ntatable_add(ntatable, -+ str2name("insecure.example"), -+ ISC_FALSE, now, 3600), -+ ISC_R_SUCCESS); -+} -+ -+static void -+destroy_tables() { -+ if (ntatable != NULL) -+ dns_ntatable_detach(&ntatable); -+ if (keytable != NULL) -+ dns_keytable_detach(&keytable); -+ -+ dns_view_detach(&view); -+} -+ -+/* -+ * Individual unit tests -+ */ -+ -+ATF_TC(add); -+ATF_TC_HEAD(add, tc) { -+ atf_tc_set_md_var(tc, "descr", "add keys to the keytable"); -+} -+ATF_TC_BODY(add, tc) { -+ dst_key_t *key = NULL; -+ dns_keynode_t *keynode = NULL; -+ dns_keynode_t *next_keynode = NULL; -+ dns_keynode_t *null_keynode = NULL; -+ -+ UNUSED(tc); -+ -+ ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS); -+ create_tables(); -+ -+ /* -+ * Get the keynode for the example.com key. There's no other key for -+ * the name, so nextkeynode() should return NOTFOUND. -+ */ -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"), -+ &keynode), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode, -+ &next_keynode), ISC_R_NOTFOUND); -+ -+ /* -+ * Try to add the same key. This should have no effect, so -+ * nextkeynode() should still return NOTFOUND. -+ */ -+ create_key(257, 3, 5, "example.com", keystr1, &key); -+ ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key), -+ ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode, -+ &next_keynode), ISC_R_NOTFOUND); -+ -+ /* Add another key (different keydata) */ -+ dns_keytable_detachkeynode(keytable, &keynode); -+ create_key(257, 3, 5, "example.com", keystr2, &key); -+ ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key), -+ ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"), -+ &keynode), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode, -+ &next_keynode), ISC_R_SUCCESS); -+ dns_keytable_detachkeynode(keytable, &next_keynode); -+ -+ /* -+ * Add a normal key to a name that has a null key. The null key node -+ * will be updated with the normal key. -+ */ -+ dns_keytable_detachkeynode(keytable, &keynode); -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"), -+ &null_keynode), ISC_R_SUCCESS); -+ create_key(257, 3, 5, "null.example", keystr2, &key); -+ ATF_REQUIRE_EQ(dns_keytable_add(keytable, ISC_FALSE, &key), -+ ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"), -+ &keynode), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(keynode, null_keynode); /* should be the same node */ -+ ATF_REQUIRE(dns_keynode_key(keynode) != NULL); /* now have a key */ -+ dns_keytable_detachkeynode(keytable, &null_keynode); -+ -+ /* -+ * Try to add a null key to a name that already has a key. It's -+ * effectively no-op, so the same key node is still there, with no -+ * no next node. -+ * (Note: this and above checks confirm that if a name has a null key -+ * that's the only key for the name). -+ */ -+ ATF_REQUIRE_EQ(dns_keytable_marksecure(keytable, -+ str2name("null.example")), -+ ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"), -+ &null_keynode), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(keynode, null_keynode); -+ ATF_REQUIRE(dns_keynode_key(keynode) != NULL); -+ ATF_REQUIRE_EQ(dns_keytable_nextkeynode(keytable, keynode, -+ &next_keynode), ISC_R_NOTFOUND); -+ dns_keytable_detachkeynode(keytable, &null_keynode); -+ -+ dns_keytable_detachkeynode(keytable, &keynode); -+ destroy_tables(); -+ dns_test_end(); -+} -+ -+ATF_TC(delete); -+ATF_TC_HEAD(delete, tc) { -+ atf_tc_set_md_var(tc, "descr", "delete keys from the keytable"); -+} -+ATF_TC_BODY(delete, tc) { -+ UNUSED(tc); -+ -+ ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS); -+ create_tables(); -+ -+ /* dns_keytable_delete requires exact match */ -+ ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.org")), -+ ISC_R_NOTFOUND); -+ ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("s.example.com")), -+ ISC_R_NOTFOUND); -+ ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.com")), -+ ISC_R_SUCCESS); -+ -+ /* works also for nodes with a null key */ -+ ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("null.example")), -+ ISC_R_SUCCESS); -+ -+ /* or a negative trust anchor */ -+ ATF_REQUIRE_EQ(dns_ntatable_delete(ntatable, -+ str2name("insecure.example")), -+ ISC_R_SUCCESS); -+ -+ destroy_tables(); -+ dns_test_end(); -+} -+ -+ATF_TC(deletekeynode); -+ATF_TC_HEAD(deletekeynode, tc) { -+ atf_tc_set_md_var(tc, "descr", "delete key nodes from the keytable"); -+} -+ATF_TC_BODY(deletekeynode, tc) { -+ dst_key_t *key = NULL; -+ -+ UNUSED(tc); -+ -+ ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS); -+ create_tables(); -+ -+ /* key name doesn't match */ -+ create_key(257, 3, 5, "example.org", keystr1, &key); -+ ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), -+ ISC_R_NOTFOUND); -+ dst_key_free(&key); -+ -+ /* subdomain match is the same as no match */ -+ create_key(257, 3, 5, "sub.example.com", keystr1, &key); -+ ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), -+ ISC_R_NOTFOUND); -+ dst_key_free(&key); -+ -+ /* name matches but key doesn't match (resulting in PARTIALMATCH) */ -+ create_key(257, 3, 5, "example.com", keystr2, &key); -+ ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), -+ DNS_R_PARTIALMATCH); -+ dst_key_free(&key); -+ -+ /* -+ * exact match. after deleting the node the internal rbt node will be -+ * empty, and any delete or deletekeynode attempt should result in -+ * NOTFOUND. -+ */ -+ create_key(257, 3, 5, "example.com", keystr1, &key); -+ ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), -+ ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), -+ ISC_R_NOTFOUND); -+ ATF_REQUIRE_EQ(dns_keytable_delete(keytable, str2name("example.com")), -+ ISC_R_NOTFOUND); -+ dst_key_free(&key); -+ -+ /* -+ * The only null key node for a name can be deleted as long as the -+ * passed key name matches. -+ */ -+ create_key(257, 3, 5, "null.example", keystr1, &key); -+ ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), -+ ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keytable_deletekeynode(keytable, key), -+ ISC_R_NOTFOUND); -+ dst_key_free(&key); -+ -+ destroy_tables(); -+ dns_test_end(); -+} -+ -+ATF_TC(find); -+ATF_TC_HEAD(find, tc) { -+ atf_tc_set_md_var(tc, "descr", "check find-variant operations"); -+} -+ATF_TC_BODY(find, tc) { -+ dns_keynode_t *keynode = NULL; -+ dns_fixedname_t fname; -+ dns_name_t *name; -+ -+ UNUSED(tc); -+ -+ ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS); -+ create_tables(); -+ -+ /* -+ * dns_keytable_find() requires exact name match. It matches node -+ * that has a null key, too. But it doesn't match a negative trust -+ * anchor. -+ */ -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.org"), -+ &keynode), ISC_R_NOTFOUND); -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("sub.example.com"), -+ &keynode), ISC_R_NOTFOUND); -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("example.com"), -+ &keynode), ISC_R_SUCCESS); -+ dns_keytable_detachkeynode(keytable, &keynode); -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("null.example"), -+ &keynode), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_keynode_key(keynode), NULL); -+ dns_keytable_detachkeynode(keytable, &keynode); -+ ATF_REQUIRE_EQ(dns_keytable_find(keytable, str2name("insecure.example"), -+ &keynode), ISC_R_NOTFOUND); -+ -+ /* -+ * dns_keytable_finddeepestmatch() allows partial match. Also match -+ * nodes with a null key or a negative trust anchor. -+ */ -+ dns_fixedname_init(&fname); -+ name = dns_fixedname_name(&fname); -+ ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable, -+ str2name("example.com"), -+ name), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_name_equal(name, str2name("example.com")), ISC_TRUE); -+ ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable, -+ str2name("s.example.com"), -+ name), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_name_equal(name, str2name("example.com")), ISC_TRUE); -+ ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable, -+ str2name("example.org"), -+ name), ISC_R_NOTFOUND); -+ ATF_REQUIRE_EQ(dns_keytable_finddeepestmatch(keytable, -+ str2name("null.example"), -+ name), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(dns_name_equal(name, str2name("null.example")), -+ ISC_TRUE); -+ -+ /* -+ * dns_keytable_findkeynode() requires exact name, algorithm, keytag -+ * match. If algorithm or keytag doesn't match, should result in -+ * PARTIALMATCH. Same for a node with a null key or a negative trust -+ * anchor. -+ */ -+ ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, -+ str2name("example.org"), -+ 5, keytag1, &keynode), -+ ISC_R_NOTFOUND); -+ ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, -+ str2name("sub.example.com"), -+ 5, keytag1, &keynode), -+ ISC_R_NOTFOUND); -+ ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, -+ str2name("example.com"), -+ 4, keytag1, &keynode), -+ DNS_R_PARTIALMATCH); /* different algorithm */ -+ ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, -+ str2name("example.com"), -+ 5, keytag1 + 1, &keynode), -+ DNS_R_PARTIALMATCH); /* different keytag */ -+ ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, -+ str2name("null.example"), -+ 5, 0, &keynode), -+ DNS_R_PARTIALMATCH); /* null key */ -+ ATF_REQUIRE_EQ(dns_keytable_findkeynode(keytable, -+ str2name("example.com"), -+ 5, keytag1, &keynode), -+ ISC_R_SUCCESS); /* complete match */ -+ dns_keytable_detachkeynode(keytable, &keynode); -+ -+ destroy_tables(); -+ dns_test_end(); -+} -+ -+ATF_TC(issecuredomain); -+ATF_TC_HEAD(issecuredomain, tc) { -+ atf_tc_set_md_var(tc, "descr", "check issecuredomain()"); -+} -+ATF_TC_BODY(issecuredomain, tc) { -+ isc_boolean_t issecure; -+ const char **n; -+ const char *names[] = {"example.com", "sub.example.com", -+ "null.example", "sub.null.example", NULL}; -+ -+ UNUSED(tc); -+ ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS); -+ create_tables(); -+ -+ /* -+ * Domains that are an exact or partial match of a key name are -+ * considered secure. It's the case even if the key is null -+ * (validation will then fail, but that's actually the intended effect -+ * of installing a null key). -+ */ -+ for (n = names; *n != NULL; n++) { -+ ATF_REQUIRE_EQ(dns_keytable_issecuredomain(keytable, -+ str2name(*n), -+ NULL, -+ &issecure), -+ ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(issecure, ISC_TRUE); -+ } -+ -+ /* -+ * Domains that are an exact or partial match of a negative trust -+ * anchor are considered insecure. -+ */ -+ ATF_REQUIRE_EQ(dns_keytable_issecuredomain(keytable, -+ str2name("insecure.example"), -+ NULL, -+ &issecure), -+ ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(issecure, ISC_FALSE); -+ ATF_REQUIRE_EQ(dns_keytable_issecuredomain( -+ keytable, str2name("sub.insecure.example"), -+ NULL, &issecure), ISC_R_SUCCESS); -+ ATF_REQUIRE_EQ(issecure, ISC_FALSE); -+ -+ destroy_tables(); -+ dns_test_end(); -+} -+ -+ATF_TC(dump); -+ATF_TC_HEAD(dump, tc) { -+ atf_tc_set_md_var(tc, "descr", "check dns_keytable_dump()"); -+} -+ATF_TC_BODY(dump, tc) { -+ UNUSED(tc); -+ -+ ATF_REQUIRE_EQ(dns_test_begin(NULL, ISC_TRUE), ISC_R_SUCCESS); -+ create_tables(); -+ -+ /* -+ * Right now, we only confirm the dump attempt doesn't cause disruption -+ * (so we don't check the dump content). -+ */ -+ ATF_REQUIRE_EQ(dns_keytable_dump(keytable, stdout), ISC_R_SUCCESS); -+ -+ destroy_tables(); -+ dns_test_end(); -+} -+ -+ATF_TC(nta); -+ATF_TC_HEAD(nta, tc) { -+ atf_tc_set_md_var(tc, "descr", "check negative trust anchors"); -+} -+ATF_TC_BODY(nta, tc) { -+ isc_result_t result; -+ dst_key_t *key = NULL; -+ isc_boolean_t issecure, covered; -+ dns_view_t *view = NULL; -+ isc_stdtime_t now; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ result = dns_test_makeview("view", &view); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ result = isc_task_create(taskmgr, 0, &view->task); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ result = dns_view_initsecroots(view, mctx); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ result = dns_view_getsecroots(view, &keytable); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ result = dns_view_initntatable(view, taskmgr, timermgr); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ result = dns_view_getntatable(view, &ntatable); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ create_key(257, 3, 5, "example", keystr1, &key); -+ result = dns_keytable_add(keytable, ISC_FALSE, &key); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ isc_stdtime_get(&now); -+ result = dns_ntatable_add(ntatable, -+ str2name("insecure.example"), -+ ISC_FALSE, now, 1); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ /* Should be secure */ -+ result = dns_view_issecuredomain(view, -+ str2name("test.secure.example"), -+ now, ISC_TRUE, &issecure); -+ ATF_CHECK_EQ(result, ISC_R_SUCCESS); -+ ATF_CHECK(issecure); -+ -+ /* Should not be secure */ -+ result = dns_view_issecuredomain(view, -+ str2name("test.insecure.example"), -+ now, ISC_TRUE, &issecure); -+ ATF_CHECK_EQ(result, ISC_R_SUCCESS); -+ ATF_CHECK(!issecure); -+ -+ /* NTA covered */ -+ covered = dns_view_ntacovers(view, now, str2name("insecure.example"), -+ dns_rootname); -+ ATF_CHECK(covered); -+ -+ /* Not NTA covered */ -+ covered = dns_view_ntacovers(view, now, str2name("secure.example"), -+ dns_rootname); -+ ATF_CHECK(!covered); -+ -+ /* As of now + 2, the NTA should be clear */ -+ result = dns_view_issecuredomain(view, -+ str2name("test.insecure.example"), -+ now + 2, ISC_TRUE, &issecure); -+ ATF_CHECK_EQ(result, ISC_R_SUCCESS); -+ ATF_CHECK(issecure); -+ -+ /* Now check deletion */ -+ result = dns_ntatable_add(ntatable, str2name("new.example"), -+ ISC_FALSE, now, 3600); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ result = dns_view_issecuredomain(view, str2name("test.new.example"), -+ now, ISC_TRUE, &issecure); -+ ATF_CHECK_EQ(result, ISC_R_SUCCESS); -+ ATF_CHECK(!issecure); -+ -+ result = dns_ntatable_delete(ntatable, str2name("new.example")); -+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); -+ -+ result = dns_view_issecuredomain(view, str2name("test.new.example"), -+ now, ISC_TRUE, &issecure); -+ ATF_CHECK_EQ(result, ISC_R_SUCCESS); -+ ATF_CHECK(issecure); -+ -+ /* Clean up */ -+ dns_ntatable_detach(&ntatable); -+ dns_keytable_detach(&keytable); -+ dns_view_detach(&view); -+ -+ dns_test_end(); -+} -+ -+/* -+ * Main -+ */ -+ATF_TP_ADD_TCS(tp) { -+ ATF_TP_ADD_TC(tp, add); -+ ATF_TP_ADD_TC(tp, delete); -+ ATF_TP_ADD_TC(tp, deletekeynode); -+ ATF_TP_ADD_TC(tp, find); -+ ATF_TP_ADD_TC(tp, issecuredomain); -+ ATF_TP_ADD_TC(tp, dump); -+ ATF_TP_ADD_TC(tp, nta); -+ -+ return (atf_no_error()); -+} -diff --git a/lib/dns/validator.c b/lib/dns/validator.c -index 0c0f7b0c0f..6a9e101803 100644 ---- a/lib/dns/validator.c -+++ b/lib/dns/validator.c -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id$ */ -- - #include - - #include -@@ -1132,6 +1130,8 @@ static inline isc_result_t - create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, - isc_taskaction_t callback, const char *caller) - { -+ unsigned int fopts = 0; -+ - if (dns_rdataset_isassociated(&val->frdataset)) - dns_rdataset_disassociate(&val->frdataset); - if (dns_rdataset_isassociated(&val->fsigrdataset)) -@@ -1143,9 +1143,14 @@ create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, - return (DNS_R_NOVALIDSIG); - } - -+ if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0) -+ fopts |= DNS_FETCHOPT_NOCDFLAG; -+ if ((val->options & DNS_VALIDATOR_NONTA) != 0) -+ fopts |= DNS_FETCHOPT_NONTA; -+ - validator_logcreate(val, name, type, caller, "fetch"); - return (dns_resolver_createfetch(val->view->resolver, name, type, -- NULL, NULL, NULL, 0, -+ NULL, NULL, NULL, fopts, - val->event->ev_sender, - callback, val, - &val->frdataset, -@@ -1162,6 +1167,7 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, - isc_taskaction_t action, const char *caller) - { - isc_result_t result; -+ unsigned int vopts = 0; - - if (check_deadlock(val, name, type, rdataset, sigrdataset)) { - validator_log(val, ISC_LOG_DEBUG(3), -@@ -1169,9 +1175,12 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, - return (DNS_R_NOVALIDSIG); - } - -+ /* OK to clear other options, but preserve NOCDFLAG */ -+ vopts |= (val->options & DNS_VALIDATOR_NOCDFLAG); -+ - validator_logcreate(val, name, type, caller, "validator"); - result = dns_validator_create(val->view, name, type, -- rdataset, sigrdataset, NULL, 0, -+ rdataset, sigrdataset, NULL, vopts, - val->task, action, val, - &val->subvalidator); - if (result == ISC_R_SUCCESS) { -@@ -1550,7 +1559,7 @@ verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata, - */ - static isc_result_t - validate(dns_validator_t *val, isc_boolean_t resume) { -- isc_result_t result; -+ isc_result_t result, vresult = DNS_R_NOVALIDSIG; - dns_validatorevent_t *event; - dns_rdata_t rdata = DNS_RDATA_INIT; - -@@ -1615,9 +1624,9 @@ validate(dns_validator_t *val, isc_boolean_t resume) { - } - - do { -- result = verify(val, val->key, &rdata, -+ vresult = verify(val, val->key, &rdata, - val->siginfo->keyid); -- if (result == ISC_R_SUCCESS) -+ if (vresult == ISC_R_SUCCESS) - break; - if (val->keynode != NULL) { - dns_keynode_t *nextnode = NULL; -@@ -1641,16 +1650,13 @@ validate(dns_validator_t *val, isc_boolean_t resume) { - break; - } - } while (1); -- if (result != ISC_R_SUCCESS) -+ if (vresult != ISC_R_SUCCESS) - validator_log(val, ISC_LOG_DEBUG(3), - "failed to verify rdataset"); - else { -- isc_stdtime_t now; -- -- isc_stdtime_get(&now); - dns_rdataset_trimttl(event->rdataset, - event->sigrdataset, -- val->siginfo, now, -+ val->siginfo, val->start, - val->view->acceptexpired); - } - -@@ -1675,12 +1681,12 @@ validate(dns_validator_t *val, isc_boolean_t resume) { - validator_log(val, ISC_LOG_DEBUG(3), - "looking for noqname proof"); - return (nsecvalidate(val, ISC_FALSE)); -- } else if (result == ISC_R_SUCCESS) { -+ } else if (vresult == ISC_R_SUCCESS) { - marksecure(event); - validator_log(val, ISC_LOG_DEBUG(3), - "marking as secure, " - "noqname proof not needed"); -- return (result); -+ return (ISC_R_SUCCESS); - } else { - validator_log(val, ISC_LOG_DEBUG(3), - "verify failure: %s", -@@ -1696,7 +1702,7 @@ validate(dns_validator_t *val, isc_boolean_t resume) { - } - - validator_log(val, ISC_LOG_INFO, "no valid signature found"); -- return (DNS_R_NOVALIDSIG); -+ return (vresult); - } - - /*% -@@ -3069,6 +3075,11 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) { - markanswer(val, "startfinddlvsep (1)"); - return (ISC_R_SUCCESS); - } -+ if (result == DNS_R_NTACOVERED) { -+ validator_log(val, ISC_LOG_DEBUG(3), "DLV covered by NTA"); -+ validator_done(val, ISC_R_SUCCESS); -+ return (ISC_R_SUCCESS); -+ } - if (result != ISC_R_SUCCESS) { - validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s", - dns_result_totext(result)); -@@ -3158,6 +3169,10 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { - return (DNS_R_NOVALIDSIG); - } - -+ if (((val->options & DNS_VALIDATOR_NONTA) == 0) && -+ dns_view_ntacovers(val->view, val->start, dlvname, val->view->dlv)) -+ return (DNS_R_NTACOVERED); -+ - while (dns_name_countlabels(dlvname) >= - dns_name_countlabels(val->view->dlv) + val->dlvlabels) { - dns_name_format(dlvname, namebuf, sizeof(namebuf)); -@@ -3774,6 +3789,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, - dns_fixedname_init(&val->wild); - dns_fixedname_init(&val->nearest); - dns_fixedname_init(&val->closest); -+ isc_stdtime_get(&val->start); - ISC_LINK_INIT(val, link); - val->magic = VALIDATOR_MAGIC; - -@@ -3889,7 +3905,7 @@ dns_validator_destroy(dns_validator_t **validatorp) { - LOCK(&val->lock); - - val->attributes |= VALATTR_SHUTDOWN; -- validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy"); -+ validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_destroy"); - - want_destroy = exit_check(val); - -@@ -3922,8 +3938,8 @@ validator_logv(dns_validator_t *val, isc_logcategory_t *category, - dns_rdatatype_format(val->event->type, typebuf, - sizeof(typebuf)); - isc_log_write(dns_lctx, category, module, level, -- "%.*svalidating @%p: %s %s: %s", depth, spaces, -- val, namebuf, typebuf, msgbuf); -+ "%.*svalidating %s/%s: %s", depth, spaces, -+ namebuf, typebuf, msgbuf); - } else { - isc_log_write(dns_lctx, category, module, level, - "%.*svalidator @%p: %s", depth, spaces, -diff --git a/lib/dns/view.c b/lib/dns/view.c -index 35900b3f0b..01b82e6ff6 100644 ---- a/lib/dns/view.c -+++ b/lib/dns/view.c -@@ -23,6 +23,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -47,6 +48,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -57,10 +59,16 @@ - #include - #include - #include -+#include - #include - #include - #include - -+#define CHECK(op) \ -+ do { result = (op); \ -+ if (result != ISC_R_SUCCESS) goto cleanup; \ -+ } while (0) -+ - #define RESSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0) - #define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0) - #define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0) -@@ -77,6 +85,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, - { - dns_view_t *view; - isc_result_t result; -+ const char nta[] = ".nta"; -+ char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(nta)]; - - /* - * Create a view. -@@ -89,6 +99,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, - if (view == NULL) - return (ISC_R_NOMEMORY); - -+ view->nta_file = NULL; - view->mctx = NULL; - isc_mem_attach(mctx, &view->mctx); - view->name = isc_mem_strdup(mctx, name); -@@ -96,6 +107,16 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, - result = ISC_R_NOMEMORY; - goto cleanup_view; - } -+ -+ isc_sha256_data((void *)view->name, strlen(view->name), buffer); -+ /* Truncate the hash at 16 chars; full length is overkill */ -+ isc_string_printf(buffer + 16, sizeof(nta), "%s", nta); -+ view->nta_file = isc_mem_strdup(mctx, buffer); -+ if (view->nta_file == NULL) { -+ result = ISC_R_NOMEMORY; -+ goto cleanup_name; -+ } -+ - result = isc_mutex_init(&view->lock); - if (result != ISC_R_SUCCESS) - goto cleanup_name; -@@ -112,6 +133,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, - } - #endif - view->secroots_priv = NULL; -+ view->ntatable_priv = NULL; - view->fwdtable = NULL; - result = dns_fwdtable_create(mctx, &view->fwdtable); - if (result != ISC_R_SUCCESS) { -@@ -189,6 +211,8 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, - view->provideixfr = ISC_TRUE; - view->maxcachettl = 7 * 24 * 3600; - view->maxncachettl = 3 * 3600; -+ view->nta_lifetime = 0; -+ view->nta_recheck = 0; - view->dstport = 53; - view->preferred_glue = 0; - view->flush = ISC_FALSE; -@@ -263,6 +287,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, - #endif - DESTROYLOCK(&view->lock); - -+ if (view->nta_file != NULL) -+ isc_mem_free(mctx, view->nta_file); -+ - cleanup_name: - isc_mem_free(mctx, view->name); - -@@ -437,6 +464,8 @@ destroy(dns_view_t *view) { - if (view->secroots_priv != NULL) - dns_keytable_detach(&view->secroots_priv); - #ifdef BIND9 -+ if (view->ntatable_priv != NULL) -+ dns_ntatable_detach(&view->ntatable_priv); - for (dns64 = ISC_LIST_HEAD(view->dns64); - dns64 != NULL; - dns64 = ISC_LIST_HEAD(view->dns64)) { -@@ -453,6 +482,7 @@ destroy(dns_view_t *view) { - dns_aclenv_destroy(&view->aclenv); - DESTROYLOCK(&view->lock); - isc_refcount_destroy(&view->references); -+ isc_mem_free(view->mctx, view->nta_file); - isc_mem_free(view->mctx, view->name); - isc_mem_putanddetach(&view->mctx, view, sizeof(*view)); - } -@@ -1786,6 +1816,27 @@ dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) { - dns_stats_attach(view->resquerystats, statsp); - } - -+isc_result_t -+dns_view_initntatable(dns_view_t *view, -+ isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr) -+{ -+ REQUIRE(DNS_VIEW_VALID(view)); -+ if (view->ntatable_priv != NULL) -+ dns_ntatable_detach(&view->ntatable_priv); -+ return (dns_ntatable_create(view, taskmgr, timermgr, -+ &view->ntatable_priv)); -+} -+ -+isc_result_t -+dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) { -+ REQUIRE(DNS_VIEW_VALID(view)); -+ REQUIRE(ntp != NULL && *ntp == NULL); -+ if (view->ntatable_priv == NULL) -+ return (ISC_R_NOTFOUND); -+ dns_ntatable_attach(view->ntatable_priv, ntp); -+ return (ISC_R_SUCCESS); -+} -+ - isc_result_t - dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) { - REQUIRE(DNS_VIEW_VALID(view)); -@@ -1804,15 +1855,47 @@ dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) { - return (ISC_R_SUCCESS); - } - -+isc_boolean_t -+dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now, -+ dns_name_t *name, dns_name_t *anchor) -+{ -+ REQUIRE(DNS_VIEW_VALID(view)); -+ -+ if (view->ntatable_priv == NULL) -+ return (ISC_FALSE); -+ -+ return (dns_ntatable_covered(view->ntatable_priv, now, name, anchor)); -+} -+ - isc_result_t - dns_view_issecuredomain(dns_view_t *view, dns_name_t *name, -- isc_boolean_t *secure_domain) { -+ isc_stdtime_t now, isc_boolean_t checknta, -+ isc_boolean_t *secure_domain) -+{ -+ isc_result_t result; -+ isc_boolean_t secure = ISC_FALSE; -+ dns_fixedname_t fn; -+ dns_name_t *anchor; -+ - REQUIRE(DNS_VIEW_VALID(view)); - - if (view->secroots_priv == NULL) - return (ISC_R_NOTFOUND); -- return (dns_keytable_issecuredomain(view->secroots_priv, name, -- secure_domain)); -+ -+ dns_fixedname_init(&fn); -+ anchor = dns_fixedname_name(&fn); -+ -+ result = dns_keytable_issecuredomain(view->secroots_priv, name, -+ anchor, &secure); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ -+ if (checknta && secure && view->ntatable_priv != NULL && -+ dns_ntatable_covered(view->ntatable_priv, now, name, anchor)) -+ secure = ISC_FALSE; -+ -+ *secure_domain = secure; -+ return (ISC_R_SUCCESS); - } - - void -@@ -1882,3 +1965,151 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx, - UNUSED(cfg_destroy); - #endif - } -+ -+isc_result_t -+dns_view_saventa(dns_view_t *view) { -+#ifdef BIND9 -+ isc_result_t result; -+ isc_boolean_t remove = ISC_FALSE; -+ dns_ntatable_t *ntatable = NULL; -+ FILE *fp = NULL; -+ -+ REQUIRE(DNS_VIEW_VALID(view)); -+ -+ if (view->nta_lifetime == 0) -+ return (ISC_R_SUCCESS); -+ -+ /* Open NTA save file for overwrite. */ -+ CHECK(isc_stdio_open(view->nta_file, "w", &fp)); -+ -+ result = dns_view_getntatable(view, &ntatable); -+ if (result == ISC_R_NOTFOUND) { -+ remove = ISC_TRUE; -+ result = ISC_R_SUCCESS; -+ goto cleanup; -+ } else -+ CHECK(result); -+ -+ result = dns_ntatable_save(ntatable, fp); -+ if (result == ISC_R_NOTFOUND) { -+ remove = ISC_TRUE; -+ result = ISC_R_SUCCESS; -+ } -+ -+ cleanup: -+ if (ntatable != NULL) -+ dns_ntatable_detach(&ntatable); -+ -+ if (fp != NULL) -+ isc_stdio_close(fp); -+ -+ /* Don't leave half-baked NTA save files lying around. */ -+ if (result != ISC_R_SUCCESS || remove) -+ (void) isc_file_remove(view->nta_file); -+ -+ return (result); -+#else -+ REQUIRE(DNS_VIEW_VALID(view)); -+ return (ISC_R_NOTIMPLEMENTED); -+#endif -+} -+ -+#define TSTR(t) ((t).value.as_textregion.base) -+#define TLEN(t) ((t).value.as_textregion.length) -+ -+isc_result_t -+dns_view_loadnta(dns_view_t *view) { -+#ifdef BIND9 -+ isc_result_t result; -+ dns_ntatable_t *ntatable = NULL; -+ isc_lex_t *lex = NULL; -+ isc_token_t token; -+ isc_stdtime_t now; -+ -+ REQUIRE(DNS_VIEW_VALID(view)); -+ -+ if (view->nta_lifetime == 0) -+ return (ISC_R_SUCCESS); -+ -+ CHECK(isc_lex_create(view->mctx, 1025, &lex)); -+ CHECK(isc_lex_openfile(lex, view->nta_file)); -+ CHECK(dns_view_getntatable(view, &ntatable)); -+ isc_stdtime_get(&now); -+ -+ for (;;) { -+ int options = (ISC_LEXOPT_EOL | ISC_LEXOPT_EOF); -+ char *name, *type, *timestamp; -+ size_t len; -+ dns_fixedname_t fn; -+ dns_name_t *ntaname; -+ isc_buffer_t b; -+ isc_stdtime_t t; -+ isc_boolean_t forced; -+ -+ CHECK(isc_lex_gettoken(lex, options, &token)); -+ if (token.type == isc_tokentype_eof) -+ break; -+ else if (token.type != isc_tokentype_string) -+ CHECK(ISC_R_UNEXPECTEDTOKEN); -+ name = TSTR(token); -+ len = TLEN(token); -+ -+ if (strcmp(name, ".") == 0) -+ ntaname = dns_rootname; -+ else { -+ dns_fixedname_init(&fn); -+ ntaname = dns_fixedname_name(&fn); -+ -+ isc_buffer_init(&b, name, len); -+ isc_buffer_add(&b, len); -+ CHECK(dns_name_fromtext(ntaname, &b, dns_rootname, -+ 0, NULL)); -+ } -+ -+ CHECK(isc_lex_gettoken(lex, options, &token)); -+ if (token.type != isc_tokentype_string) -+ CHECK(ISC_R_UNEXPECTEDTOKEN); -+ type = TSTR(token); -+ -+ if (strcmp(type, "regular") == 0) -+ forced = ISC_FALSE; -+ else if (strcmp(type, "forced") == 0) -+ forced = ISC_TRUE; -+ else -+ CHECK(ISC_R_UNEXPECTEDTOKEN); -+ -+ CHECK(isc_lex_gettoken(lex, options, &token)); -+ if (token.type != isc_tokentype_string) -+ CHECK(ISC_R_UNEXPECTEDTOKEN); -+ timestamp = TSTR(token); -+ CHECK(dns_time32_fromtext(timestamp, &t)); -+ -+ CHECK(isc_lex_gettoken(lex, options, &token)); -+ if (token.type != isc_tokentype_eol && -+ token.type != isc_tokentype_eof) -+ CHECK(ISC_R_UNEXPECTEDTOKEN); -+ -+ if (now <= t) { -+ if (t > (now + 604800)) -+ t = now + 604800; -+ -+ (void) dns_ntatable_add(ntatable, ntaname, -+ forced, 0, t); -+ } -+ }; -+ -+ cleanup: -+ if (ntatable != NULL) -+ dns_ntatable_detach(&ntatable); -+ -+ if (lex != NULL) { -+ isc_lex_close(lex); -+ isc_lex_destroy(&lex); -+ } -+ -+ return (result); -+#else -+ REQUIRE(DNS_VIEW_VALID(view)); -+ return (ISC_R_NOTIMPLEMENTED); -+#endif -+} -diff --git a/lib/export/dns/Makefile.in b/lib/export/dns/Makefile.in -index 887acb9416..4719a5a809 100644 ---- a/lib/export/dns/Makefile.in -+++ b/lib/export/dns/Makefile.in -@@ -59,7 +59,7 @@ DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \ - keytable.@O@ \ - lib.@O@ log.@O@ \ - master.@O@ masterdump.@O@ message.@O@ \ -- name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ \ -+ name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ nta.@O@ \ - peer.@O@ portlist.@O@ \ - rbt.@O@ rbtdb.@O@ rcode.@O@ rdata.@O@ \ - rdatalist.@O@ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ \ -@@ -89,7 +89,7 @@ DNSSRCS = acl.c adb.c byaddr.c \ - keytable.c \ - lib.c log.c \ - master.c masterdump.c message.c \ -- name.c ncache.c nsec.c nsec3.c \ -+ name.c ncache.c nsec.c nsec3.c nta.c \ - peer.c portlist.c \ - rbt.c rbtdb.c rcode.c rdata.c \ - rdatalist.c rdataset.c rdatasetiter.c rdataslab.c \ -diff --git a/lib/isc/include/isc/log.h b/lib/isc/include/isc/log.h -index 741c532429..e609d913b7 100644 ---- a/lib/isc/include/isc/log.h -+++ b/lib/isc/include/isc/log.h -@@ -67,8 +67,9 @@ - #define ISC_LOG_PRINTLEVEL 0x0002 - #define ISC_LOG_PRINTCATEGORY 0x0004 - #define ISC_LOG_PRINTMODULE 0x0008 --#define ISC_LOG_PRINTTAG 0x0010 --#define ISC_LOG_PRINTALL 0x001F -+#define ISC_LOG_PRINTTAG 0x0010 /* tag and ":" */ -+#define ISC_LOG_PRINTPREFIX 0x0020 /* tag only, no colon */ -+#define ISC_LOG_PRINTALL 0x003F - #define ISC_LOG_DEBUGONLY 0x1000 - #define ISC_LOG_OPENERR 0x8000 /* internal */ - /*@}*/ -@@ -167,6 +168,7 @@ LIBISC_EXTERNAL_DATA extern isc_logmodule_t isc_modules[]; - #define ISC_LOGMODULE_INTERFACE (&isc_modules[2]) - #define ISC_LOGMODULE_TIMER (&isc_modules[3]) - #define ISC_LOGMODULE_FILE (&isc_modules[4]) -+#define ISC_LOGMODULE_OTHER (&isc_modules[5]) - - ISC_LANG_BEGINDECLS - -diff --git a/lib/isc/log.c b/lib/isc/log.c -index 35204cfb9a..65b78ea46d 100644 ---- a/lib/isc/log.c -+++ b/lib/isc/log.c -@@ -205,6 +205,7 @@ LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = { - { "interface", 0 }, - { "timer", 0 }, - { "file", 0 }, -+ { "other", 0 }, - { NULL, 0 } - }; - -@@ -1413,7 +1414,7 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, - const char *iformat; - struct stat statbuf; - isc_boolean_t matched = ISC_FALSE; -- isc_boolean_t printtime, printtag; -+ isc_boolean_t printtime, printtag, printcolon; - isc_boolean_t printcategory, printmodule, printlevel; - isc_logconfig_t *lcfg; - isc_logchannel_t *channel; -@@ -1641,7 +1642,10 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, - - printtime = ISC_TF((channel->flags & ISC_LOG_PRINTTIME) - != 0); -- printtag = ISC_TF((channel->flags & ISC_LOG_PRINTTAG) -+ printtag = ISC_TF((channel->flags & -+ (ISC_LOG_PRINTTAG|ISC_LOG_PRINTPREFIX)) -+ != 0 && lcfg->tag != NULL); -+ printcolon = ISC_TF((channel->flags & ISC_LOG_PRINTTAG) - != 0 && lcfg->tag != NULL); - printcategory = ISC_TF((channel->flags & ISC_LOG_PRINTCATEGORY) - != 0); -@@ -1695,11 +1699,12 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, - /* FALLTHROUGH */ - - case ISC_LOG_TOFILEDESC: -- fprintf(FILE_STREAM(channel), "%s%s%s%s%s%s%s%s%s%s\n", -+ fprintf(FILE_STREAM(channel), -+ "%s%s%s%s%s%s%s%s%s%s\n", - printtime ? time_string : "", - printtime ? " " : "", - printtag ? lcfg->tag : "", -- printtag ? ": " : "", -+ printcolon ? ": " : "", - printcategory ? category->name : "", - printcategory ? ": " : "", - printmodule ? (module != NULL ? module->name -@@ -1742,11 +1747,12 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, - printtime ? time_string : "", - printtime ? " " : "", - printtag ? lcfg->tag : "", -- printtag ? ": " : "", -+ printcolon ? ": " : "", - printcategory ? category->name : "", - printcategory ? ": " : "", -- printmodule ? (module != NULL ? module->name -- : "no_module") -+ printmodule ? (module != NULL -+ ? module->name -+ : "no_module") - : "", - printmodule ? ": " : "", - printlevel ? level_string : "", -diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c -index d97d7c6bbc..3338b60173 100644 ---- a/lib/isc/unix/app.c -+++ b/lib/isc/unix/app.c -@@ -232,7 +232,6 @@ ISC_APPFUNC_SCOPE isc_result_t - isc__app_ctxstart(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - isc_result_t result; -- - REQUIRE(VALID_APPCTX(ctx)); - - /* -diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c -index 8773be8446..d9b1df158a 100644 ---- a/lib/isccfg/namedconf.c -+++ b/lib/isccfg/namedconf.c -@@ -29,6 +29,8 @@ - #include - #include - -+#include -+ - #include - #include - #include -@@ -130,6 +132,7 @@ static cfg_type_t cfg_type_sizenodefault; - static cfg_type_t cfg_type_sockaddr4wild; - static cfg_type_t cfg_type_sockaddr6wild; - static cfg_type_t cfg_type_statschannels; -+static cfg_type_t cfg_type_ttlval; - static cfg_type_t cfg_type_view; - static cfg_type_t cfg_type_viewopts; - static cfg_type_t cfg_type_zone; -@@ -1441,6 +1444,8 @@ view_clauses[] = { - { "max-udp-size", &cfg_type_uint32, 0 }, - { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, - { "minimal-responses", &cfg_type_boolean, 0 }, -+ { "nta-recheck", &cfg_type_ttlval, 0 }, -+ { "nta-lifetime", &cfg_type_ttlval, 0 }, - { "preferred-glue", &cfg_type_astring, 0 }, - { "provide-ixfr", &cfg_type_boolean, 0 }, - /* -@@ -3068,3 +3073,43 @@ static cfg_type_t cfg_type_masterselement = { - "masters_element", parse_masterselement, NULL, - doc_masterselement, NULL, NULL - }; -+ -+static isc_result_t -+parse_ttlval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { -+ isc_result_t result; -+ cfg_obj_t *obj = NULL; -+ isc_uint32_t ttl; -+ -+ UNUSED(type); -+ -+ CHECK(cfg_gettoken(pctx, 0)); -+ if (pctx->token.type != isc_tokentype_string) { -+ result = ISC_R_UNEXPECTEDTOKEN; -+ goto cleanup; -+ } -+ -+ result = dns_ttl_fromtext(&pctx->token.value.as_textregion, &ttl); -+ if (result == ISC_R_RANGE ) { -+ cfg_parser_error(pctx, CFG_LOG_NEAR, "TTL out of range "); -+ return (result); -+ } else if (result != ISC_R_SUCCESS) -+ goto cleanup; -+ -+ CHECK(cfg_create_obj(pctx, &cfg_type_uint32, &obj)); -+ obj->value.uint32 = ttl; -+ *ret = obj; -+ return (ISC_R_SUCCESS); -+ -+ cleanup: -+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected integer and optional unit"); -+ return (result); -+} -+ -+/*% -+ * A TTL value (number + optional unit). -+ */ -+static cfg_type_t cfg_type_ttlval = { -+ "ttlval", parse_ttlval, cfg_print_uint64, cfg_doc_terminal, -+ &cfg_rep_uint64, NULL -+}; -+ -diff --git a/make/includes.in b/make/includes.in -index f2f1b3f451..42b19bcc39 100644 ---- a/make/includes.in -+++ b/make/includes.in -@@ -37,6 +37,9 @@ ISCCFG_INCLUDES = @BIND9_ISCCFG_BUILDINCLUDE@ \ - DNS_INCLUDES = @BIND9_DNS_BUILDINCLUDE@ \ - -I${top_srcdir}/lib/dns/include - -+IRS_INCLUDES = @BIND9_IRS_BUILDINCLUDE@ \ -+ -I${top_srcdir}/lib/irs/include -+ - LWRES_INCLUDES = @BIND9_LWRES_BUILDINCLUDE@ \ - -I${top_srcdir}/lib/lwres/unix/include \ - -I${top_srcdir}/lib/lwres/include -diff --git a/make/rules.in b/make/rules.in -index 37bc50d82f..bc6f92e9f3 100644 ---- a/make/rules.in -+++ b/make/rules.in -@@ -48,9 +48,10 @@ top_builddir = @BIND9_TOP_BUILDDIR@ - ### All - ### - ### Makefile may define: -+### PREREQS - ### TARGETS - --all: subdirs ${TARGETS} testdirs -+all: ${PREREQS} subdirs ${TARGETS} testdirs - - ### - ### Subdirectories --- -2.14.4 - diff --git a/SOURCES/bind99-rh1067424.patch b/SOURCES/bind99-rh1067424.patch deleted file mode 100644 index 9f5faf8..0000000 --- a/SOURCES/bind99-rh1067424.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 09f1a6e812c02bd8bf1644e2253e21c26d25613a Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Thu, 20 Feb 2014 11:01:00 +0100 -Subject: [PATCH] check TSIG key ID when receiving NOTIFY - -Signed-off-by: Tomas Hozza ---- - lib/dns/zone.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/lib/dns/zone.c b/lib/dns/zone.c -index 01ff97b..54b7896 100644 ---- a/lib/dns/zone.c -+++ b/lib/dns/zone.c -@@ -11846,6 +11846,8 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, - int match = 0; - isc_netaddr_t netaddr; - isc_sockaddr_t local, remote; -+ dns_tsigkey_t *tsigkey; -+ dns_name_t *tsig; - - REQUIRE(DNS_ZONE_VALID(zone)); - -@@ -11928,10 +11930,12 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, - - /* - * Accept notify requests from non masters if they are on -- * 'zone->notify_acl'. -+ * 'zone->notify_acl' or if used key ID match the ACLs. - */ -+ tsigkey = dns_message_gettsigkey(msg); -+ tsig = dns_tsigkey_identity(tsigkey); - if (i >= zone->masterscnt && zone->notify_acl != NULL && -- dns_acl_match(&netaddr, NULL, zone->notify_acl, -+ dns_acl_match(&netaddr, tsig, zone->notify_acl, - &zone->view->aclenv, - &match, NULL) == ISC_R_SUCCESS && - match > 0) --- -1.8.5.3 - diff --git a/SOURCES/bind99-rh1072379.patch b/SOURCES/bind99-rh1072379.patch deleted file mode 100644 index 2eb0cc2..0000000 --- a/SOURCES/bind99-rh1072379.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 7f5bdf7f4063c2fefb18900468d2c851f8de7816 Mon Sep 17 00:00:00 2001 -From: Evan Hunt -Date: Tue, 18 Feb 2014 23:32:02 -0800 -Subject: [PATCH] [master] fix dns_resolver_destroyfetch race - -3747. [bug] A race condition could lead to a core dump when - destroying a resolver fetch object. [RT #35385] ---- - lib/dns/resolver.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index fa188c1..66ab41f 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -357,6 +357,7 @@ typedef struct { - - struct dns_fetch { - unsigned int magic; -+ isc_mem_t * mctx; - fetchctx_t * private; - }; - -@@ -8561,6 +8562,8 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name, - fetch = isc_mem_get(res->mctx, sizeof(*fetch)); - if (fetch == NULL) - return (ISC_R_NOMEMORY); -+ fetch->mctx = NULL; -+ isc_mem_attach(res->mctx, &fetch->mctx); - - bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets; - -@@ -8651,7 +8654,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name, - FTRACE("created"); - *fetchp = fetch; - } else -- isc_mem_put(res->mctx, fetch, sizeof(*fetch)); -+ isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch)); - - return (result); - } -@@ -8742,7 +8745,7 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) { - - UNLOCK(&res->buckets[bucketnum].lock); - -- isc_mem_put(res->mctx, fetch, sizeof(*fetch)); -+ isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch)); - *fetchp = NULL; - - if (bucket_empty) --- -1.9.0 - diff --git a/SOURCES/bind99-rh1098959.patch b/SOURCES/bind99-rh1098959.patch deleted file mode 100644 index ef4ce0a..0000000 --- a/SOURCES/bind99-rh1098959.patch +++ /dev/null @@ -1,164 +0,0 @@ -diff -up bind-9.8.2rc1/bin/named/include/named/lwresd.h.lwres_tasks_clients bind-9.8.2rc1/bin/named/include/named/lwresd.h ---- bind-9.8.2rc1/bin/named/include/named/lwresd.h.lwres_tasks_clients 2007-06-20 01:46:59.000000000 +0200 -+++ bind-9.8.2rc1/bin/named/include/named/lwresd.h 2014-05-19 09:41:56.792427201 +0200 -@@ -36,6 +36,8 @@ struct ns_lwresd { - dns_view_t *view; - ns_lwsearchlist_t *search; - unsigned int ndots; -+ unsigned int ntasks; -+ unsigned int nclients; - isc_mem_t *mctx; - isc_boolean_t shutting_down; - unsigned int refs; -diff -up bind-9.8.2rc1/bin/named/lwresd.c.lwres_tasks_clients bind-9.8.2rc1/bin/named/lwresd.c ---- bind-9.8.2rc1/bin/named/lwresd.c.lwres_tasks_clients 2009-09-03 01:48:01.000000000 +0200 -+++ bind-9.8.2rc1/bin/named/lwresd.c 2014-05-19 09:41:56.793427201 +0200 -@@ -60,11 +60,7 @@ - #define LWRESLISTENER_MAGIC ISC_MAGIC('L', 'W', 'R', 'L') - #define VALID_LWRESLISTENER(l) ISC_MAGIC_VALID(l, LWRESLISTENER_MAGIC) - --/*! -- * The total number of clients we can handle will be NTASKS * NRECVS. -- */ --#define NTASKS 2 /*%< tasks to create to handle lwres queries */ --#define NRECVS 2 /*%< max clients per task */ -+#define LWRESD_NCLIENTS_MAX 32768 /*%< max clients per task */ - - typedef ISC_LIST(ns_lwreslistener_t) ns_lwreslistenerlist_t; - -@@ -395,6 +391,24 @@ ns_lwdmanager_create(isc_mem_t *mctx, co - } - } - -+ obj = NULL; -+ (void)cfg_map_get(lwres, "lwres-tasks", &obj); -+ if (obj != NULL) -+ lwresd->ntasks = cfg_obj_asuint32(obj); -+ else -+ lwresd->ntasks = ns_g_cpus; -+ -+ obj = NULL; -+ (void)cfg_map_get(lwres, "lwres-clients", &obj); -+ if (obj != NULL) { -+ lwresd->nclients = cfg_obj_asuint32(obj); -+ if (lwresd->nclients > LWRESD_NCLIENTS_MAX) -+ lwresd->nclients = LWRESD_NCLIENTS_MAX; -+ } else if (ns_g_lwresdonly) -+ lwresd->nclients = 1024; -+ else -+ lwresd->nclients = 256; -+ - lwresd->magic = LWRESD_MAGIC; - - *lwresdp = lwresd; -@@ -604,15 +618,24 @@ static isc_result_t - listener_startclients(ns_lwreslistener_t *listener) { - ns_lwdclientmgr_t *cm; - unsigned int i; -- isc_result_t result; -+ isc_result_t result = ISC_R_SUCCESS; -+ -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_LWRESD, ISC_LOG_DEBUG(6), -+ "listener_startclients: creating %d " -+ "managers with %d clients each", -+ listener->manager->ntasks, listener->manager->nclients); - - /* - * Create the client managers. - */ -- result = ISC_R_SUCCESS; -- for (i = 0; i < NTASKS && result == ISC_R_SUCCESS; i++) -- result = ns_lwdclientmgr_create(listener, NRECVS, -+ for (i = 0; i < listener->manager->ntasks; i++) { -+ result = ns_lwdclientmgr_create(listener, -+ listener->manager->nclients, - ns_g_taskmgr); -+ if (result != ISC_R_SUCCESS) -+ break; -+ } - - /* - * Ensure that we have created at least one. -diff -up bind-9.8.2rc1/bin/named/named.conf.docbook.lwres_tasks_clients bind-9.8.2rc1/bin/named/named.conf.docbook ---- bind-9.8.2rc1/bin/named/named.conf.docbook.lwres_tasks_clients 2011-11-07 01:31:47.000000000 +0100 -+++ bind-9.8.2rc1/bin/named/named.conf.docbook 2014-05-19 09:41:56.793427201 +0200 -@@ -185,6 +185,8 @@ lwres { - view string optional_class; - search { string; ... }; - ndots integer; -+ lwres-tasks integer; -+ lwres-clients integer; - }; - - -diff -up bind-9.8.2rc1/doc/arm/Bv9ARM-book.xml.lwres_tasks_clients bind-9.8.2rc1/doc/arm/Bv9ARM-book.xml ---- bind-9.8.2rc1/doc/arm/Bv9ARM-book.xml.lwres_tasks_clients 2014-05-19 09:41:56.770427201 +0200 -+++ bind-9.8.2rc1/doc/arm/Bv9ARM-book.xml 2014-05-19 10:26:40.147380836 +0200 -@@ -2964,7 +2964,12 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2. - be configured to act as a lightweight resolver daemon using the - lwres statement in named.conf. - -- -+ -+ The number of client queries that the lwresd -+ daemon is able to serve can be set using the -+ and -+ statements in the configuration. -+ - - - -@@ -4959,6 +4964,8 @@ badresp:1,adberr:0,findfail:0,valfail:0] - view view_name; - search { domain_name ; domain_name ; ... }; - ndots number; -+ lwres-tasks number; -+ lwres-clients number; - }; - - -@@ -5017,6 +5024,31 @@ badresp:1,adberr:0,findfail:0,valfail:0] - number of dots in a relative domain name that should result in an - exact match lookup before search path elements are appended. - -+ -+ The statement specifies the number -+ of worker threads the lightweight resolver will dedicate to serving -+ clients. By default the number is the same as the number of CPUs on -+ the system; this can be overridden using the -+ command line option when starting the server. -+ -+ -+ The specifies -+ the number of client objects per thread the lightweight -+ resolver should create to serve client queries. -+ By default, if the lightweight resolver runs as a part -+ of named, 256 client objects are -+ created for each task; if it runs as lwresd, -+ 1024 client objects are created for each thread. The maximum -+ value is 32768; higher values will be silently ignored and -+ the maximum will be used instead. -+ Note that setting too high a value may overconsume -+ system resources. -+ -+ -+ The maximum number of client queries that the lightweight -+ resolver can handle at any one time equals -+ times . -+ - - - <command>masters</command> Statement Grammar -diff -up bind-9.8.2rc1/lib/isccfg/namedconf.c.lwres_tasks_clients bind-9.8.2rc1/lib/isccfg/namedconf.c ---- bind-9.8.2rc1/lib/isccfg/namedconf.c.lwres_tasks_clients 2014-05-19 09:41:56.771427201 +0200 -+++ bind-9.8.2rc1/lib/isccfg/namedconf.c 2014-05-19 09:41:56.797427201 +0200 -@@ -2563,6 +2563,8 @@ lwres_clauses[] = { - { "view", &cfg_type_lwres_view, 0 }, - { "search", &cfg_type_lwres_searchlist, 0 }, - { "ndots", &cfg_type_uint32, 0 }, -+ { "lwres-tasks", &cfg_type_uint32, 0}, -+ { "lwres-clients", &cfg_type_uint32, 0}, - { NULL, NULL, 0 } - }; - diff --git a/SOURCES/bind99-rh1214827.patch b/SOURCES/bind99-rh1214827.patch deleted file mode 100644 index 19c35ac..0000000 --- a/SOURCES/bind99-rh1214827.patch +++ /dev/null @@ -1,408 +0,0 @@ -From c8cd2cd7f21ce56f93532a6d5f26239e60657acb Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Thu, 25 Jun 2015 14:53:31 +0200 -Subject: [PATCH] nsupdate: Don't extract REAML from ticket, but leave it up to - GSSAPI - -The current implementation of nsupdate does not work correctly with -GSSAPI in cross realm trust scenarios. The realm is currently -extracted from local kerberos ticket instead of letting GSSAPI to -figure out the realm based on the remote nameserver hostname. - -RFC 4752 section 3.1 states that the client should use -GSS_C_NT_HOSTBASED_SERVICE when calling gss_import_name(). - -nsupdate now leaves the realm detection up to GSSAPI, if the realm is -not specified explicitly using the 'realm' option. If the option is -used, the old behavior is preserved. - -Signed-off-by: Tomas Hozza ---- - bin/nsupdate/nsupdate.1 | 3 +- - bin/nsupdate/nsupdate.c | 72 ++++++++----------------------------------- - bin/nsupdate/nsupdate.docbook | 2 +- - bin/nsupdate/nsupdate.html | 2 +- - bin/tests/dst/gsstest.c | 4 +-- - lib/dns/gssapictx.c | 16 +++++++--- - lib/dns/include/dns/tkey.h | 24 +++++++++------ - lib/dns/include/dst/gssapi.h | 8 +++-- - lib/dns/tkey.c | 28 +++++++++-------- - 9 files changed, 65 insertions(+), 94 deletions(-) - -diff --git a/bin/nsupdate/nsupdate.1 b/bin/nsupdate/nsupdate.1 -index 1e2dcaf..c847fb8 100644 ---- a/bin/nsupdate/nsupdate.1 -+++ b/bin/nsupdate/nsupdate.1 -@@ -259,8 +259,7 @@ on the commandline. - .RS 4 - When using GSS\-TSIG use - \fIrealm_name\fR --rather than the default realm in --\fIkrb5.conf\fR. If no realm is specified the saved realm is cleared. -+rather than leaving the realm detection up to GSSAPI. If no realm is specified the saved realm is cleared. - .RE - .PP - \fB[prereq]\fR\fB nxdomain\fR {domain\-name} -diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c -index b901e03..644e3d9 100644 ---- a/bin/nsupdate/nsupdate.c -+++ b/bin/nsupdate/nsupdate.c -@@ -2489,57 +2489,6 @@ sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, - - #ifdef GSSAPI - --/* -- * Get the realm from the users kerberos ticket if possible -- */ --static void --get_ticket_realm(isc_mem_t *mctx) --{ -- krb5_context ctx; -- krb5_error_code rc; -- krb5_ccache ccache; -- krb5_principal princ; -- char *name, *ticket_realm; -- -- rc = krb5_init_context(&ctx); -- if (rc != 0) -- return; -- -- rc = krb5_cc_default(ctx, &ccache); -- if (rc != 0) { -- krb5_free_context(ctx); -- return; -- } -- -- rc = krb5_cc_get_principal(ctx, ccache, &princ); -- if (rc != 0) { -- krb5_cc_close(ctx, ccache); -- krb5_free_context(ctx); -- return; -- } -- -- rc = krb5_unparse_name(ctx, princ, &name); -- if (rc != 0) { -- krb5_free_principal(ctx, princ); -- krb5_cc_close(ctx, ccache); -- krb5_free_context(ctx); -- return; -- } -- -- ticket_realm = strrchr(name, '@'); -- if (ticket_realm != NULL) { -- realm = isc_mem_strdup(mctx, ticket_realm); -- } -- -- free(name); -- krb5_free_principal(ctx, princ); -- krb5_cc_close(ctx, ccache); -- krb5_free_context(ctx); -- if (realm != NULL && debugging) -- fprintf(stderr, "Found realm from ticket: %s\n", realm+1); --} -- -- - static void - start_gssrequest(dns_name_t *master) { - gss_ctx_id_t context; -@@ -2580,11 +2529,15 @@ start_gssrequest(dns_name_t *master) { - dns_fixedname_init(&fname); - servname = dns_fixedname_name(&fname); - -- if (realm == NULL) -- get_ticket_realm(mctx); -- -- result = isc_string_printf(servicename, sizeof(servicename), -- "DNS/%s%s", namestr, realm ? realm : ""); -+ if (realm != NULL) { -+ /* Use explicit REALM passed as argument */ -+ result = isc_string_printf(servicename, sizeof(servicename), -+ "DNS/%s%s", namestr, realm); -+ } else { -+ /* Use service@host as advised in RFC4752 section 3.1 */ -+ result = isc_string_printf(servicename, sizeof(servicename), -+ "DNS@%s", namestr); -+ } - if (result != ISC_R_SUCCESS) - fatal("isc_string_printf(servicename) failed: %s", - isc_result_totext(result)); -@@ -2623,9 +2576,9 @@ start_gssrequest(dns_name_t *master) { - - /* Build first request. */ - context = GSS_C_NO_CONTEXT; -- result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0, -- &context, use_win2k_gsstsig, -- mctx, &err_message); -+ result = dns_tkey_buildgssquery(rmsg, keyname, servname, -+ realm != NULL ? ISC_TRUE : ISC_FALSE, NULL, 0, -+ &context, use_win2k_gsstsig, mctx, &err_message); - if (result == ISC_R_FAILURE) - fatal("tkey query failed: %s", - err_message != NULL ? err_message : "unknown error"); -@@ -2765,6 +2718,7 @@ recvgss(isc_task_t *task, isc_event_t *event) { - - tsigkey = NULL; - result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, -+ realm != NULL ? ISC_TRUE : ISC_FALSE, - &context, &tsigkey, gssring, - use_win2k_gsstsig, - &err_message); -diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook -index c54211c..bbcc681 100644 ---- a/bin/nsupdate/nsupdate.docbook -+++ b/bin/nsupdate/nsupdate.docbook -@@ -418,7 +418,7 @@ - - - When using GSS-TSIG use realm_name rather -- than the default realm in krb5.conf. If no -+ than leaving the realm detection up to GSSAPI. If no - realm is specified the saved realm is cleared. - - -diff --git a/bin/nsupdate/nsupdate.html b/bin/nsupdate/nsupdate.html -index 276d4af..9c0eba0 100644 ---- a/bin/nsupdate/nsupdate.html -+++ b/bin/nsupdate/nsupdate.html -@@ -327,7 +327,7 @@ - -

- When using GSS-TSIG use realm_name rather -- than the default realm in krb5.conf. If no -+ than leaving the realm detection up to GSSAPI. If no - realm is specified the saved realm is cleared. -

-
-diff --git a/bin/tests/dst/gsstest.c b/bin/tests/dst/gsstest.c -index c1296f7..7c85d0b 100755 ---- a/bin/tests/dst/gsstest.c -+++ b/bin/tests/dst/gsstest.c -@@ -309,7 +309,7 @@ initctx2(isc_task_t *task, isc_event_t *event) { - printf("Received token from server, calling gss_init_sec_context()\n"); - isc_buffer_init(&outtoken, array, DNS_NAME_MAXTEXT + 1); - result = dns_tkey_processgssresponse(query, response, -- dns_fixedname_name(&gssname), -+ dns_fixedname_name(&gssname), ISC_FALSE, - &gssctx, &outtoken, - &tsigkey, ring, NULL); - gssctx = *gssctxp; -@@ -396,7 +396,7 @@ initctx1(isc_task_t *task, isc_event_t *event) { - printf("Calling gss_init_sec_context()\n"); - gssctx = GSS_C_NO_CONTEXT; - result = dns_tkey_buildgssquery(query, dns_fixedname_name(&servername), -- dns_fixedname_name(&gssname), -+ dns_fixedname_name(&gssname), ISC_FALSE, - NULL, 36000, &gssctx, ISC_TRUE, - mctx, NULL); - CHECK("dns_tkey_buildgssquery", result); -diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c -index aeaeb85..21222e0 100644 ---- a/lib/dns/gssapictx.c -+++ b/lib/dns/gssapictx.c -@@ -558,14 +558,15 @@ gss_err_message(isc_mem_t *mctx, isc_uint32_t major, isc_uint32_t minor, - #endif - - isc_result_t --dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, -- isc_buffer_t *outtoken, gss_ctx_id_t *gssctx, -- isc_mem_t *mctx, char **err_message) -+dst_gssapi_initctx(dns_name_t *name, isc_boolean_t explicit_realm, -+ isc_buffer_t *intoken, isc_buffer_t *outtoken, -+ gss_ctx_id_t *gssctx, isc_mem_t *mctx, char **err_message) - { - #ifdef GSSAPI - isc_region_t r; - isc_buffer_t namebuf; - gss_name_t gname; -+ gss_OID gname_type; - OM_uint32 gret, minor, ret_flags, flags; - gss_buffer_desc gintoken, *gintokenp, gouttoken = GSS_C_EMPTY_BUFFER; - isc_result_t result; -@@ -580,7 +581,13 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, - name_to_gbuffer(name, &namebuf, &gnamebuf); - - /* Get the name as a GSS name */ -- gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); -+ if (explicit_realm == ISC_TRUE) { -+ gname_type = GSS_C_NO_OID; -+ } else { -+ gname_type = GSS_C_NT_HOSTBASED_SERVICE; -+ } -+ -+ gret = gss_import_name(&minor, &gnamebuf, gname_type, &gname); - if (gret != GSS_S_COMPLETE) { - gss_err_message(mctx, gret, minor, err_message); - result = ISC_R_FAILURE; -@@ -642,6 +649,7 @@ dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, - return (result); - #else - UNUSED(name); -+ UNUSED(explicit_realm); - UNUSED(intoken); - UNUSED(outtoken); - UNUSED(gssctx); -diff --git a/lib/dns/include/dns/tkey.h b/lib/dns/include/dns/tkey.h -index 0dcec1e..a0e6c2a 100644 ---- a/lib/dns/include/dns/tkey.h -+++ b/lib/dns/include/dns/tkey.h -@@ -123,9 +123,9 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name, - - isc_result_t - dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, -- isc_buffer_t *intoken, isc_uint32_t lifetime, -- gss_ctx_id_t *context, isc_boolean_t win2k, -- isc_mem_t *mctx, char **err_message); -+ isc_boolean_t explicit_realm, isc_buffer_t *intoken, -+ isc_uint32_t lifetime, gss_ctx_id_t *context, -+ isc_boolean_t win2k, isc_mem_t *mctx, char **err_message); - /*%< - * Builds a query containing a TKEY that will generate a GSSAPI context. - * The key is requested to have the specified lifetime (in seconds). -@@ -134,6 +134,8 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, - *\li 'msg' is a valid message - *\li 'name' is a valid name - *\li 'gname' is a valid name -+ *\li 'explicit_realm' ISC_TRUE if an explicit realm is used, -+ * ISC_FALSE if the realm detection is left up to GSSAPI. - *\li 'context' is a pointer to a valid gss_ctx_id_t - * (which may have the value GSS_C_NO_CONTEXT) - *\li 'win2k' when true says to turn on some hacks to work -@@ -188,9 +190,10 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg, - - isc_result_t - dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, -- dns_name_t *gname, gss_ctx_id_t *context, -- isc_buffer_t *outtoken, dns_tsigkey_t **outkey, -- dns_tsig_keyring_t *ring, char **err_message); -+ dns_name_t *gname, isc_boolean_t explicit_realm, -+ gss_ctx_id_t *context, isc_buffer_t *outtoken, -+ dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring, -+ char **err_message); - /*%< - * XXX - */ -@@ -216,9 +219,10 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg, - - isc_result_t - dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, -- dns_name_t *server, gss_ctx_id_t *context, -- dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring, -- isc_boolean_t win2k, char **err_message); -+ dns_name_t *server, isc_boolean_t explicit_realm, -+ gss_ctx_id_t *context, dns_tsigkey_t **outkey, -+ dns_tsig_keyring_t *ring, isc_boolean_t win2k, -+ char **err_message); - - /* - * Client side negotiation of GSS-TSIG. Process the response -@@ -231,6 +235,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, - * it will be filled with the new message to send - * 'rmsg' is a valid message, the incoming TKEY message - * 'server' is the server name -+ * 'explicit_realm' ISC_TRUE if an explicit realm is used, -+ * ISC_FALSE if the realm detection is left up to GSSAPI. - * 'context' is the input context handle - * 'outkey' receives the established key, if non-NULL; - * if non-NULL must point to NULL -diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h -index 1e81a55..d093fa3 100644 ---- a/lib/dns/include/dst/gssapi.h -+++ b/lib/dns/include/dst/gssapi.h -@@ -93,15 +93,17 @@ dst_gssapi_releasecred(gss_cred_id_t *cred); - */ - - isc_result_t --dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken, -- isc_buffer_t *outtoken, gss_ctx_id_t *gssctx, -- isc_mem_t *mctx, char **err_message); -+dst_gssapi_initctx(dns_name_t *name, isc_boolean_t explicit_realm, -+ isc_buffer_t *intoken, isc_buffer_t *outtoken, -+ gss_ctx_id_t *gssctx, isc_mem_t *mctx, char **err_message); - /* - * Initiates a GSS context. - * - * Requires: - * 'name' is a valid name, preferably one known by the GSS - * provider -+ * 'explicit_realm' True if the REALM is explicitly included in the 'name', -+ * otherwise leave the REALM detection up to GSSAPI - * 'intoken' is a token received from the acceptor, or NULL if - * there isn't one - * 'outtoken' is a buffer to receive the token generated by -diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c -index 20c98e5..3463d3a 100644 ---- a/lib/dns/tkey.c -+++ b/lib/dns/tkey.c -@@ -1016,9 +1016,9 @@ dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name, - - isc_result_t - dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, -- isc_buffer_t *intoken, isc_uint32_t lifetime, -- gss_ctx_id_t *context, isc_boolean_t win2k, -- isc_mem_t *mctx, char **err_message) -+ isc_boolean_t explicit_realm, isc_buffer_t *intoken, -+ isc_uint32_t lifetime, gss_ctx_id_t *context, -+ isc_boolean_t win2k, isc_mem_t *mctx, char **err_message) - { - dns_rdata_tkey_t tkey; - isc_result_t result; -@@ -1035,7 +1035,7 @@ dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname, - REQUIRE(mctx != NULL); - - isc_buffer_init(&token, array, sizeof(array)); -- result = dst_gssapi_initctx(gname, NULL, &token, context, -+ result = dst_gssapi_initctx(gname, explicit_realm, NULL, &token, context, - mctx, err_message); - if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) - return (result); -@@ -1251,9 +1251,10 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg, - - isc_result_t - dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, -- dns_name_t *gname, gss_ctx_id_t *context, -- isc_buffer_t *outtoken, dns_tsigkey_t **outkey, -- dns_tsig_keyring_t *ring, char **err_message) -+ dns_name_t *gname, isc_boolean_t explicit_realm, -+ gss_ctx_id_t *context, isc_buffer_t *outtoken, -+ dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring, -+ char **err_message) - { - dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT; - dns_name_t *tkeyname; -@@ -1304,7 +1305,7 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, - - isc_buffer_init(outtoken, array, sizeof(array)); - isc_buffer_init(&intoken, rtkey.key, rtkey.keylen); -- RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context, -+ RETERR(dst_gssapi_initctx(gname, explicit_realm, &intoken, outtoken, context, - ring->mctx, err_message)); - - RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx, -@@ -1384,9 +1385,10 @@ dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg, - - isc_result_t - dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, -- dns_name_t *server, gss_ctx_id_t *context, -- dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring, -- isc_boolean_t win2k, char **err_message) -+ dns_name_t *server, isc_boolean_t explicit_realm, -+ gss_ctx_id_t *context, dns_tsigkey_t **outkey, -+ dns_tsig_keyring_t *ring, isc_boolean_t win2k, -+ char **err_message) - { - dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT; - dns_name_t *tkeyname; -@@ -1430,8 +1432,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, - isc_buffer_init(&intoken, rtkey.key, rtkey.keylen); - isc_buffer_init(&outtoken, array, sizeof(array)); - -- result = dst_gssapi_initctx(server, &intoken, &outtoken, context, -- ring->mctx, err_message); -+ result = dst_gssapi_initctx(server, explicit_realm, &intoken, &outtoken, -+ context, ring->mctx, err_message); - if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS) - return (result); - --- -2.4.3 - diff --git a/SOURCES/bind99-rh1215164.patch b/SOURCES/bind99-rh1215164.patch deleted file mode 100644 index 80bef02..0000000 --- a/SOURCES/bind99-rh1215164.patch +++ /dev/null @@ -1,178 +0,0 @@ -diff --git a/bin/check/named-checkzone.8 b/bin/check/named-checkzone.8 -index 8538ca8..0ab0049 100644 ---- a/bin/check/named-checkzone.8 -+++ b/bin/check/named-checkzone.8 -@@ -251,7 +251,7 @@ so that include directives in the configuration file are processed as if run by - .PP - \-T \fImode\fR - .RS 4 --Check if Sender Policy Framework records (TXT and SPF) both exist or both don't exist. A warning is issued if they don't match. Possible modes are -+Check if Sender Policy Framework (SPF) records exist and issues a warning if an SPF-formatted TXT record is not also present. Possible modes are - \fB"warn"\fR - (default), - \fB"ignore"\fR. -diff --git a/bin/check/named-checkzone.docbook b/bin/check/named-checkzone.docbook -index ea37fa2..e78d574 100644 ---- a/bin/check/named-checkzone.docbook -+++ b/bin/check/named-checkzone.docbook -@@ -408,10 +408,10 @@ - -T mode - - -- Check if Sender Policy Framework records (TXT and SPF) -- both exist or both don't exist. A warning is issued -- if they don't match. Possible modes are -- "warn" (default), "ignore". -+ Check if Sender Policy Framework (SPF) records exist -+ and issues a warning if an SPF-formatted TXT record is -+ not also present. Possible modes are "warn" -+ (default), "ignore". - - - -diff --git a/bin/tests/system/checkzone/tests.sh b/bin/tests/system/checkzone/tests.sh -index 2353c14..7d9192e 100644 ---- a/bin/tests/system/checkzone/tests.sh -+++ b/bin/tests/system/checkzone/tests.sh -@@ -44,12 +44,12 @@ echo "I:checking with spf warnings ($n)" - ret=0 - $CHECKZONE example zones/spf.db > test.out1.$n 2>&1 || ret=1 - $CHECKZONE -T ignore example zones/spf.db > test.out2.$n 2>&1 || ret=1 --grep "'x.example' found SPF/TXT" test.out1.$n > /dev/null || ret=1 --grep "'y.example' found SPF/SPF" test.out1.$n > /dev/null || ret=1 --grep "'example' found SPF/" test.out1.$n > /dev/null && ret=1 --grep "'x.example' found SPF/" test.out2.$n > /dev/null && ret=1 --grep "'y.example' found SPF/" test.out2.$n > /dev/null && ret=1 --grep "'example' found SPF/" test.out2.$n > /dev/null && ret=1 -+grep "'x.example' found type SPF" test.out1.$n > /dev/null && ret=1 -+grep "'y.example' found type SPF" test.out1.$n > /dev/null || ret=1 -+grep "'example' found type SPF" test.out1.$n > /dev/null && ret=1 -+grep "'x.example' found type SPF" test.out2.$n > /dev/null && ret=1 -+grep "'y.example' found type SPF" test.out2.$n > /dev/null && ret=1 -+grep "'example' found type SPF" test.out2.$n > /dev/null && ret=1 - n=`expr $n + 1` - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` -diff --git a/bin/tests/system/spf/tests.sh b/bin/tests/system/spf/tests.sh -index 6acd283..3da6e2e 100644 ---- a/bin/tests/system/spf/tests.sh -+++ b/bin/tests/system/spf/tests.sh -@@ -24,19 +24,16 @@ echo "I:checking that SPF warnings have been correctly generated ($n)" - ret=0 - - grep "zone spf/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1 --grep "'x.spf' found SPF/TXT" ns1/named.run > /dev/null || ret=1 --grep "'y.spf' found SPF/SPF" ns1/named.run > /dev/null || ret=1 --grep "'spf' found SPF/" ns1/named.run > /dev/null && ret=1 -+grep "'y.spf' found type SPF" ns1/named.run > /dev/null || ret=1 -+grep "'spf' found type SPF" ns1/named.run > /dev/null && ret=1 - - grep "zone warn/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1 --grep "'x.warn' found SPF/TXT" ns1/named.run > /dev/null || ret=1 --grep "'y.warn' found SPF/SPF" ns1/named.run > /dev/null || ret=1 --grep "'warn' found SPF/" ns1/named.run > /dev/null && ret=1 -+grep "'y.warn' found type SPF" ns1/named.run > /dev/null || ret=1 -+grep "'warn' found type SPF" ns1/named.run > /dev/null && ret=1 - - grep "zone nowarn/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1 --grep "'x.nowarn' found SPF/" ns1/named.run > /dev/null && ret=1 --grep "'y.nowarn' found SPF/" ns1/named.run > /dev/null && ret=1 --grep "'nowarn' found SPF/" ns1/named.run > /dev/null && ret=1 -+grep "'y.nowarn' found type SPF" ns1/named.run > /dev/null && ret=1 -+grep "'nowarn' found type SPF" ns1/named.run > /dev/null && ret=1 - n=`expr $n + 1` - if [ $ret != 0 ]; then echo "I:failed"; fi - status=`expr $status + $ret` -diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml -index 96c9faf..bd42e11 100644 ---- a/doc/arm/Bv9ARM-book.xml -+++ b/doc/arm/Bv9ARM-book.xml -@@ -4750,7 +4750,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] - check-mx-cname ( warn | fail | ignore ); - check-srv-cname ( warn | fail | ignore ); - check-sibling yes_or_no; -- check-spf ( warn | fail | ignore ); -+ check-spf ( warn | ignore ); - allow-new-zones { yes_or_no }; - allow-notify { address_match_list }; - allow-query { address_match_list }; -@@ -6573,10 +6573,13 @@ options { - The default is yes. - - -- Check that the two forms of Sender Policy Framework -- records (TXT records starting with "v=spf1" and SPF) either -- both exist or both don't exist. Warnings are -- emitted it they don't and be suppressed with -+ The use of the SPF record for publishing Sender -+ Policy Framework is deprecated as the migration -+ from using TXT records to SPF records was abandoned. -+ Enabling this option also checks that a TXT Sender -+ Policy Framework record exists (starts with "v=spf1") -+ if there is an SPF record. Warnings are emitted if the -+ TXT record does not exist and can be suppressed with - check-spf. - - -@@ -6618,11 +6621,11 @@ options { - check-spf - - -- When performing integrity checks, check that the -- two forms of Sender Policy Framwork records (TXT -- records starting with "v=spf1" and SPF) both exist -- or both don't exist and issue a warning if not -- met. The default is warn. -+ If check-integrity is set then -+ check that there is a TXT Sender Policy Framework -+ record present (starts with "v=spf1") if there is an -+ SPF record present. The default is -+ warn. - - - -@@ -10372,7 +10375,7 @@ view "external" { - check-names (warn|fail|ignore) ; - check-mx (warn|fail|ignore) ; - check-wildcard yes_or_no; -- check-spf ( warn | fail | ignore ); -+ check-spf ( warn | ignore ); - check-integrity yes_or_no ; - dialup dialup_option ; - file string ; -diff --git a/lib/dns/zone.c b/lib/dns/zone.c -index 86fad98..08c6d10 100644 ---- a/lib/dns/zone.c -+++ b/lib/dns/zone.c -@@ -2612,8 +2612,8 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { - - checkspf: - /* -- * Check if there is a type TXT spf record without a type SPF -- * RRset being present. -+ * Check if there is a type SPF record without an -+ * SPF-formatted type TXT record also being present. - */ - if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) - goto next; -@@ -2642,16 +2642,13 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { - dns_rdataset_disassociate(&rdataset); - - notxt: -- if (have_spf != have_txt) { -+ if (have_spf && !have_txt) { - char namebuf[DNS_NAME_FORMATSIZE]; -- const char *found = have_txt ? "TXT" : "SPF"; -- const char *need = have_txt ? "SPF" : "TXT"; - - dns_name_format(name, namebuf, sizeof(namebuf)); -- dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s " -- "record but no SPF/%s record found, add " -- "matching type %s record", namebuf, found, -- need, need); -+ dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type " -+ "SPF record but no SPF TXT record found, " -+ "add matching type TXT record", namebuf); - } - - next: diff --git a/SOURCES/bind99-rh1215687-limits.patch b/SOURCES/bind99-rh1215687-limits.patch deleted file mode 100644 index 7922b7e..0000000 --- a/SOURCES/bind99-rh1215687-limits.patch +++ /dev/null @@ -1,67 +0,0 @@ -diff -up bind-9.9.4/bin/named/interfacemgr.c.rh1215687-limits bind-9.9.4/bin/named/interfacemgr.c ---- bind-9.9.4/bin/named/interfacemgr.c.rh1215687-limits 2015-05-20 16:08:21.286007013 +0200 -+++ bind-9.9.4/bin/named/interfacemgr.c 2015-05-20 16:21:49.227001713 +0200 -@@ -275,7 +275,7 @@ ns_interface_listenudp(ns_interface_t *i - result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr, - ns_g_socketmgr, - ns_g_taskmgr, &ifp->addr, -- 4096, 1000, 32768, 8219, 8237, -+ 4096, 32768, 32768, 8219, 8237, - attrs, attrmask, - &ifp->udpdispatch[disp], - disp == 0 -diff -up bind-9.9.4/bin/named/server.c.rh1215687-limits bind-9.9.4/bin/named/server.c ---- bind-9.9.4/bin/named/server.c.rh1215687-limits 2015-05-20 16:08:21.272006979 +0200 -+++ bind-9.9.4/bin/named/server.c 2015-05-20 16:08:21.288007018 +0200 -@@ -992,7 +992,7 @@ get_view_querysource_dispatch(const cfg_ - } - if (isc_sockaddr_getport(&sa) == 0) { - attrs |= DNS_DISPATCHATTR_EXCLUSIVE; -- maxdispatchbuffers = 4096; -+ maxdispatchbuffers = 32768; - } else { - INSIST(obj != NULL); - if (is_firstview) { -@@ -1001,7 +1001,7 @@ get_view_querysource_dispatch(const cfg_ - "suppresses port randomization and can be " - "insecure."); - } -- maxdispatchbuffers = 1000; -+ maxdispatchbuffers = 32768; - } - - attrmask = 0; -@@ -6491,7 +6491,7 @@ ns_add_reserved_dispatch(ns_server_t *se - - result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, - ns_g_taskmgr, &dispatch->addr, 4096, -- 1000, 32768, 16411, 16433, -+ 32768, 32768, 16411, 16433, - attrs, attrmask, &dispatch->dispatch); - if (result != ISC_R_SUCCESS) - goto cleanup; -diff -up bind-9.9.4/lib/dns/dispatch.c.rh1215687-limits bind-9.9.4/lib/dns/dispatch.c -diff -up bind-9.9.4/lib/dns/request.c.rh1215687-limits bind-9.9.4/lib/dns/request.c ---- bind-9.9.4/lib/dns/request.c.rh1215687-limits 2013-09-05 07:09:08.000000000 +0200 -+++ bind-9.9.4/lib/dns/request.c 2015-05-20 16:08:21.286007013 +0200 -@@ -601,7 +601,7 @@ find_udp_dispatch(dns_requestmgr_t *requ - requestmgr->socketmgr, - requestmgr->taskmgr, - srcaddr, 4096, -- 1000, 32768, 16411, 16433, -+ 32768, 32768, 16411, 16433, - attrs, attrmask, - dispatchp)); - } -diff -up bind-9.9.4/lib/dns/resolver.c.rh1215687-limits bind-9.9.4/lib/dns/resolver.c ---- bind-9.9.4/lib/dns/resolver.c.rh1215687-limits 2015-05-20 16:08:21.277006991 +0200 -+++ bind-9.9.4/lib/dns/resolver.c 2015-05-20 16:08:21.285007010 +0200 -@@ -1489,7 +1489,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddr - result = dns_dispatch_getudp(res->dispatchmgr, - res->socketmgr, - res->taskmgr, &addr, -- 4096, 1000, 32768, 16411, -+ 4096, 20000, 32768, 16411, - 16433, attrs, attrmask, - &query->dispatch); - if (result != ISC_R_SUCCESS) diff --git a/SOURCES/bind99-rh1220594-geoip.patch b/SOURCES/bind99-rh1220594-geoip.patch deleted file mode 100644 index 3e65b99..0000000 --- a/SOURCES/bind99-rh1220594-geoip.patch +++ /dev/null @@ -1,5539 +0,0 @@ -From 34c87ea385ff013ca2f2058b884f53886065a4a3 Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Wed, 13 Apr 2016 09:57:31 +0200 -Subject: [PATCH] Added support for GeoIP - -Signed-off-by: Tomas Hozza ---- - bin/named/Makefile.in | 8 +- - bin/named/geoip.c | 148 +++++ - bin/named/include/named/geoip.h | 31 + - bin/named/include/named/globals.h | 5 + - bin/named/interfacemgr.c | 3 + - bin/named/server.c | 38 +- - bin/tests/system/Makefile.in | 2 +- - bin/tests/system/conf.sh.in | 2 +- - bin/tests/system/geoip/Makefile.in | 55 ++ - bin/tests/system/geoip/clean.sh | 23 + - bin/tests/system/geoip/data/GeoIP.csv | 7 + - bin/tests/system/geoip/data/GeoIPASNum.csv | 7 + - bin/tests/system/geoip/data/GeoIPASNumv6.csv | 7 + - bin/tests/system/geoip/data/GeoIPCity.csv | 7 + - bin/tests/system/geoip/data/GeoIPCityv6.csv | 7 + - bin/tests/system/geoip/data/GeoIPDomain.csv | 7 + - bin/tests/system/geoip/data/GeoIPISP.csv | 7 + - bin/tests/system/geoip/data/GeoIPNetSpeed.csv | 7 + - bin/tests/system/geoip/data/GeoIPOrg.csv | 7 + - bin/tests/system/geoip/data/GeoIPRegion.csv | 7 + - bin/tests/system/geoip/data/GeoIPv6.csv | 7 + - bin/tests/system/geoip/data/README | 29 + - bin/tests/system/geoip/geoip.c | 31 + - bin/tests/system/geoip/ns2/example.db.in | 24 + - bin/tests/system/geoip/ns2/named1.conf | 104 ++++ - bin/tests/system/geoip/ns2/named10.conf | 104 ++++ - bin/tests/system/geoip/ns2/named11.conf | 104 ++++ - bin/tests/system/geoip/ns2/named12.conf | 80 +++ - bin/tests/system/geoip/ns2/named13.conf | 45 ++ - bin/tests/system/geoip/ns2/named14.conf | 112 ++++ - bin/tests/system/geoip/ns2/named15.conf | 55 ++ - bin/tests/system/geoip/ns2/named2.conf | 104 ++++ - bin/tests/system/geoip/ns2/named3.conf | 104 ++++ - bin/tests/system/geoip/ns2/named4.conf | 96 +++ - bin/tests/system/geoip/ns2/named5.conf | 104 ++++ - bin/tests/system/geoip/ns2/named6.conf | 104 ++++ - bin/tests/system/geoip/ns2/named7.conf | 104 ++++ - bin/tests/system/geoip/ns2/named8.conf | 104 ++++ - bin/tests/system/geoip/ns2/named9.conf | 104 ++++ - bin/tests/system/geoip/options.conf | 42 ++ - bin/tests/system/geoip/prereq.sh | 23 + - bin/tests/system/geoip/setup.sh | 27 + - bin/tests/system/geoip/tests.sh | 328 +++++++++++ - config.h.in | 9 + - configure.in | 94 +++ - doc/arm/Bv9ARM-book.xml | 72 +++ - lib/dns/Makefile.in | 8 +- - lib/dns/acl.c | 23 +- - lib/dns/geoip.c | 820 ++++++++++++++++++++++++++ - lib/dns/include/dns/Makefile.in | 6 +- - lib/dns/include/dns/acl.h | 24 +- - lib/dns/include/dns/geoip.h | 119 ++++ - lib/dns/tests/Makefile.in | 9 +- - lib/dns/tests/geoip_test.c | 694 ++++++++++++++++++++++ - lib/export/dns/Makefile.in | 6 +- - lib/isccfg/aclconf.c | 361 +++++++++++- - lib/isccfg/include/isccfg/aclconf.h | 6 + - lib/isccfg/namedconf.c | 129 +++- - 58 files changed, 4671 insertions(+), 33 deletions(-) - create mode 100644 bin/named/geoip.c - create mode 100644 bin/named/include/named/geoip.h - create mode 100644 bin/tests/system/geoip/Makefile.in - create mode 100644 bin/tests/system/geoip/clean.sh - create mode 100644 bin/tests/system/geoip/data/GeoIP.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPASNum.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPASNumv6.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPCity.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPCityv6.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPDomain.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPISP.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPNetSpeed.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPOrg.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPRegion.csv - create mode 100644 bin/tests/system/geoip/data/GeoIPv6.csv - create mode 100644 bin/tests/system/geoip/data/README - create mode 100644 bin/tests/system/geoip/geoip.c - create mode 100644 bin/tests/system/geoip/ns2/example.db.in - create mode 100644 bin/tests/system/geoip/ns2/named1.conf - create mode 100644 bin/tests/system/geoip/ns2/named10.conf - create mode 100644 bin/tests/system/geoip/ns2/named11.conf - create mode 100644 bin/tests/system/geoip/ns2/named12.conf - create mode 100644 bin/tests/system/geoip/ns2/named13.conf - create mode 100644 bin/tests/system/geoip/ns2/named14.conf - create mode 100644 bin/tests/system/geoip/ns2/named15.conf - create mode 100644 bin/tests/system/geoip/ns2/named2.conf - create mode 100644 bin/tests/system/geoip/ns2/named3.conf - create mode 100644 bin/tests/system/geoip/ns2/named4.conf - create mode 100644 bin/tests/system/geoip/ns2/named5.conf - create mode 100644 bin/tests/system/geoip/ns2/named6.conf - create mode 100644 bin/tests/system/geoip/ns2/named7.conf - create mode 100644 bin/tests/system/geoip/ns2/named8.conf - create mode 100644 bin/tests/system/geoip/ns2/named9.conf - create mode 100644 bin/tests/system/geoip/options.conf - create mode 100644 bin/tests/system/geoip/prereq.sh - create mode 100644 bin/tests/system/geoip/setup.sh - create mode 100644 bin/tests/system/geoip/tests.sh - create mode 100644 lib/dns/geoip.c - create mode 100644 lib/dns/include/dns/geoip.h - create mode 100644 lib/dns/tests/geoip_test.c - -diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in -index 8ec9ad7..8b9e87a 100644 ---- a/bin/named/Makefile.in -+++ b/bin/named/Makefile.in -@@ -83,8 +83,10 @@ SUBDIRS = unix - - TARGETS = named@EXEEXT@ lwresd@EXEEXT@ - -+GEOIPLINKOBJS = geoip.@O@ -+ - OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \ -- controlconf.@O@ interfacemgr.@O@ \ -+ controlconf.@O@ @GEOIPLINKOBJS@ interfacemgr.@O@ \ - listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \ - query.@O@ server.@O@ sortlist.@O@ statschannel.@O@ \ - tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ -@@ -97,8 +99,10 @@ UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@ - - SYMOBJS = symtbl.@O@ - -+GEOIPLINKSRCS = geoip.c -+ - SRCS = builtin.c client.c config.c control.c \ -- controlconf.c interfacemgr.c \ -+ controlconf.c @GEOIPLINKSRCS@ interfacemgr.c \ - listenlist.c log.c logconf.c main.c notify.c \ - query.c server.c sortlist.c statschannel.c symtbl.c symtbl-empty.c \ - tkeyconf.c tsigconf.c update.c xfrout.c \ -diff --git a/bin/named/geoip.c b/bin/named/geoip.c -new file mode 100644 -index 0000000..c8f0c62 ---- /dev/null -+++ b/bin/named/geoip.c -@@ -0,0 +1,148 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+ -+#include -+#include -+ -+#include -+ -+#ifdef HAVE_GEOIP -+static dns_geoip_databases_t geoip_table = { -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -+}; -+ -+static void -+init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback, -+ GeoIPOptions method, const char *name) -+{ -+ char *info; -+ GeoIP *db; -+ -+ REQUIRE(dbp != NULL); -+ -+ db = *dbp; -+ -+ if (db != NULL) { -+ GeoIP_delete(db); -+ db = *dbp = NULL; -+ } -+ -+ if (! GeoIP_db_avail(edition)) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_INFO, -+ "GeoIP %s (type %d) DB not available", name, edition); -+ goto fail; -+ } -+ -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_INFO, -+ "initializing GeoIP %s (type %d) DB", name, edition); -+ -+ db = GeoIP_open_type(edition, method); -+ if (db == NULL) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR, -+ "failed to initialize GeoIP %s (type %d) DB%s", -+ name, edition, fallback == 0 -+ ? "geoip matches using this database will fail" : ""); -+ goto fail; -+ } -+ -+ info = GeoIP_database_info(db); -+ if (info != NULL) -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_INFO, -+ "%s", info); -+ -+ *dbp = db; -+ return; -+ fail: -+ if (fallback != 0) -+ init_geoip_db(dbp, fallback, 0, method, name); -+ -+} -+#endif /* HAVE_GEOIP */ -+ -+void -+ns_geoip_init(void) { -+#ifndef HAVE_GEOIP -+ return; -+#else -+ GeoIP_cleanup(); -+ if (ns_g_geoip == NULL) -+ ns_g_geoip = &geoip_table; -+#endif -+} -+ -+void -+ns_geoip_load(char *dir) { -+#ifndef HAVE_GEOIP -+ -+ UNUSED(dir); -+ -+ return; -+#else -+ GeoIPOptions method; -+ -+#ifdef _WIN32 -+ method = GEOIP_STANDARD; -+#else -+ method = GEOIP_MMAP_CACHE; -+#endif -+ -+ ns_geoip_init(); -+ if (dir != NULL) { -+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, -+ NS_LOGMODULE_SERVER, ISC_LOG_INFO, -+ "using \"%s\" as GeoIP directory", dir); -+ GeoIP_setup_custom_directory(dir); -+ } -+ -+ init_geoip_db(&ns_g_geoip->country_v4, GEOIP_COUNTRY_EDITION, 0, -+ method, "Country (IPv4)"); -+#ifdef HAVE_GEOIP_V6 -+ init_geoip_db(&ns_g_geoip->country_v6, GEOIP_COUNTRY_EDITION_V6, 0, -+ method, "Country (IPv6)"); -+#endif -+ -+ init_geoip_db(&ns_g_geoip->city_v4, GEOIP_CITY_EDITION_REV1, -+ GEOIP_CITY_EDITION_REV0, method, "City (IPv4)"); -+#if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6) -+ init_geoip_db(&ns_g_geoip->city_v6, GEOIP_CITY_EDITION_REV1_V6, -+ GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)"); -+#endif -+ -+ init_geoip_db(&ns_g_geoip->region, GEOIP_REGION_EDITION_REV1, -+ GEOIP_REGION_EDITION_REV0, method, "Region"); -+ -+ init_geoip_db(&ns_g_geoip->isp, GEOIP_ISP_EDITION, 0, -+ method, "ISP"); -+ init_geoip_db(&ns_g_geoip->org, GEOIP_ORG_EDITION, 0, -+ method, "Org"); -+ init_geoip_db(&ns_g_geoip->as, GEOIP_ASNUM_EDITION, 0, -+ method, "AS"); -+ init_geoip_db(&ns_g_geoip->domain, GEOIP_DOMAIN_EDITION, 0, -+ method, "Domain"); -+ init_geoip_db(&ns_g_geoip->netspeed, GEOIP_NETSPEED_EDITION, 0, -+ method, "NetSpeed"); -+#endif /* HAVE_GEOIP */ -+} -diff --git a/bin/named/include/named/geoip.h b/bin/named/include/named/geoip.h -new file mode 100644 -index 0000000..e1a66a7 ---- /dev/null -+++ b/bin/named/include/named/geoip.h -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef _GEOIP_H -+#define _GEOIP_H -+ -+#ifdef HAVE_GEOIP -+#include -+#include -+#endif /* HAVE_GEOIP */ -+ -+void ns_geoip_init(void); -+void ns_geoip_load(char *dir); -+ -+#ifdef HAVE_GEOIP -+extern dns_geoip_databases_t *ns_g_geoip; -+#endif /* HAVE_GEOIP */ -+#endif -diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h -index aad462d..412b3a7 100644 ---- a/bin/named/include/named/globals.h -+++ b/bin/named/include/named/globals.h -@@ -29,6 +29,7 @@ - #include - #include - -+#include - #include - - #include -@@ -160,6 +161,10 @@ EXTERN isc_boolean_t ns_g_nosoa INIT(ISC_FALSE); - EXTERN isc_boolean_t ns_g_noaa INIT(ISC_FALSE); - EXTERN isc_boolean_t ns_g_nonearest INIT(ISC_FALSE); - -+#ifdef HAVE_GEOIP -+EXTERN dns_geoip_databases_t *ns_g_geoip INIT(NULL); -+#endif -+ - #undef EXTERN - #undef INIT - -diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c -index 9206ebb..4f6b0f3 100644 ---- a/bin/named/interfacemgr.c -+++ b/bin/named/interfacemgr.c -@@ -108,6 +108,9 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, - result = dns_aclenv_init(mctx, &mgr->aclenv); - if (result != ISC_R_SUCCESS) - goto cleanup_listenon; -+#ifdef HAVE_GEOIP -+ mgr->aclenv.geoip = ns_g_geoip; -+#endif - - mgr->references = 1; - mgr->magic = IFMGR_MAGIC; -diff --git a/bin/named/server.c b/bin/named/server.c -index 6260f8f..e3ffc2e 100644 ---- a/bin/named/server.c -+++ b/bin/named/server.c -@@ -99,6 +99,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -114,6 +115,9 @@ - #include - #include - #endif -+#ifdef HAVE_GEOIP -+#include -+#endif /* HAVE_GEOIP */ - - #ifndef PATH_MAX - #define PATH_MAX 1024 -@@ -3795,6 +3799,10 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, - if (result != ISC_R_SUCCESS) - return (result); - -+#ifdef HAVE_GEOIP -+ view->aclenv.geoip = ns_g_geoip; -+#endif -+ - ISC_LIST_APPEND(*viewlist, view, link); - dns_view_attach(view, viewp); - return (ISC_R_SUCCESS); -@@ -5122,6 +5130,24 @@ load_configuration(const char *filename, ns_server_t *server, - } - isc__socketmgr_setreserved(ns_g_socketmgr, reserved); - -+#ifdef HAVE_GEOIP -+ /* -+ * Initialize GeoIP databases from the configured location. -+ * This should happen before configuring any ACLs, so that we -+ * know what databases are available and can reject any GeoIP -+ * ACLs that can't work. -+ */ -+ obj = NULL; -+ result = ns_config_get(maps, "geoip-directory", &obj); -+ if (result == ISC_R_SUCCESS && cfg_obj_isstring(obj)) { -+ char *dir; -+ DE_CONST(cfg_obj_asstring(obj), dir); -+ ns_geoip_load(dir); -+ } else -+ ns_geoip_load(NULL); -+ ns_g_aclconfctx->geoip = ns_g_geoip; -+#endif /* HAVE_GEOIP */ -+ - /* - * Configure various server options. - */ -@@ -6134,6 +6160,10 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { - if (server->blackholeacl != NULL) - dns_acl_detach(&server->blackholeacl); - -+#ifdef HAVE_GEOIP -+ dns_geoip_shutdown(); -+#endif -+ - dns_db_detach(&server->in_roothints); - - isc_task_endexclusive(server->task); -@@ -6155,7 +6185,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { - server->task = NULL; - - /* Initialize configuration data with default values. */ -- - result = isc_quota_init(&server->xfroutquota, 10); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - result = isc_quota_init(&server->tcpquota, 10); -@@ -6163,9 +6192,16 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { - result = isc_quota_init(&server->recursionquota, 100); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - -+ - result = dns_aclenv_init(mctx, &server->aclenv); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - -+#ifdef HAVE_GEOIP -+ /* Initialize GeoIP before using ACL environment */ -+ ns_geoip_init(); -+ server->aclenv.geoip = ns_g_geoip; -+#endif -+ - /* Initialize server data structures. */ - server->zonemgr = NULL; - server->interfacemgr = NULL; -diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in -index af8b82c..0c7fdff 100644 ---- a/bin/tests/system/Makefile.in -+++ b/bin/tests/system/Makefile.in -@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@ - - @BIND9_MAKE_INCLUDES@ - --SUBDIRS = dlzexternal dyndb filter-aaaa lwresd rpz rrl \ -+SUBDIRS = dlzexternal dyndb filter-aaaa geoip lwresd rpz rrl \ - rsabigexponent tkey tsiggss - TARGETS = - -diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in -index eb02236..6df4734 100644 ---- a/bin/tests/system/conf.sh.in -+++ b/bin/tests/system/conf.sh.in -@@ -65,7 +65,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin - lwresd masterfile masterformat metadata notify nsupdate pending - @PKCS11_TEST@ redirect resolver rndc rpz rrl rrsetorder rsabigexponent - smartsign sortlist spf staticstub stub tkey tsig tsiggss unknown -- upforwd verify views wildcard xfer xferquota zero zonechecks" -+ upforwd verify views wildcard xfer xferquota zero zonechecks geoip filter-aaaa" - - # PERL will be an empty string if no perl interpreter was found. - PERL=@PERL@ -diff --git a/bin/tests/system/geoip/Makefile.in b/bin/tests/system/geoip/Makefile.in -new file mode 100644 -index 0000000..ab48003 ---- /dev/null -+++ b/bin/tests/system/geoip/Makefile.in -@@ -0,0 +1,55 @@ -+# Copyright (C) 2010-2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id: Makefile.in,v 1.4 2011/07/28 23:47:58 tbox Exp $ -+ -+srcdir = @srcdir@ -+VPATH = @srcdir@ -+top_srcdir = @top_srcdir@ -+ -+@BIND9_VERSION@ -+ -+@BIND9_MAKE_INCLUDES@ -+ -+CINCLUDES = ${ISC_INCLUDES} -+ -+CDEFINES = -+CWARNINGS = -+ -+DNSLIBS = -+ISCLIBS = . -+ -+DNSDEPLIBS = -+ISCDEPLIBS = -+ -+DEPLIBS = -+ -+LIBS = @LIBS@ -+ -+TARGETS = geoip@EXEEXT@ -+ -+FILTEROBJS = geoip.@O@ -+ -+SRCS = geoip.c -+ -+@BIND9_MAKE_RULES@ -+ -+all: geoip@EXEEXT@ -+ -+geoip@EXEEXT@: ${FILTEROBJS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${FILTEROBJS} ${LIBS} -+ -+clean distclean:: -+ rm -f ${TARGETS} -+ -diff --git a/bin/tests/system/geoip/clean.sh b/bin/tests/system/geoip/clean.sh -new file mode 100644 -index 0000000..b04ca2d ---- /dev/null -+++ b/bin/tests/system/geoip/clean.sh -@@ -0,0 +1,23 @@ -+#!/bin/sh -+# -+# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+rm -f ns2/named.conf -+rm -f ns2/example*.db -+rm -f dig.out.* rndc.out.* -+rm -f data2/*dat -+[ -d data2 ] && rmdir data2 -+rm -f ns?/named.run -+rm -f ns?/named.memstats -diff --git a/bin/tests/system/geoip/data/GeoIP.csv b/bin/tests/system/geoip/data/GeoIP.csv -new file mode 100644 -index 0000000..f158a5b ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIP.csv -@@ -0,0 +1,7 @@ -+10.53.0.1/32 AU -+10.53.0.2/32 US -+10.53.0.3/32 GB -+10.53.0.4/32 CA -+10.53.0.5/32 CL -+10.53.0.6/32 DE -+10.53.0.7/32 EH -diff --git a/bin/tests/system/geoip/data/GeoIPASNum.csv b/bin/tests/system/geoip/data/GeoIPASNum.csv -new file mode 100644 -index 0000000..774edd1 ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPASNum.csv -@@ -0,0 +1,7 @@ -+10.53.0.1/32 AS100001 One Systems, Inc. -+10.53.0.2/32 AS100002 Two Technology Ltd. -+10.53.0.3/32 AS100003 Three Network Labs -+10.53.0.4/32 AS100004 Four University -+10.53.0.5/32 AS100005 Five Telecom -+10.53.0.6/32 AS100006 Six Company -+10.53.0.7/32 AS100007 Seven Communications -diff --git a/bin/tests/system/geoip/data/GeoIPASNumv6.csv b/bin/tests/system/geoip/data/GeoIPASNumv6.csv -new file mode 100644 -index 0000000..4074289 ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPASNumv6.csv -@@ -0,0 +1,7 @@ -+fd92:7065:b8e:ffff::1/128,AS100001 One Systems, Inc. -+fd92:7065:b8e:ffff::2/128,AS100002 Two Technology Ltd. -+fd92:7065:b8e:ffff::3/128,AS100003 Three Network Labs -+fd92:7065:b8e:ffff::4/128,AS100004 Four University -+fd92:7065:b8e:ffff::5/128,AS100005 Five Telecom -+fd92:7065:b8e:ffff::6/128,AS100006 Six Company -+fd92:7065:b8e:ffff::7/128,AS100007 Seven Communications -diff --git a/bin/tests/system/geoip/data/GeoIPCity.csv b/bin/tests/system/geoip/data/GeoIPCity.csv -new file mode 100644 -index 0000000..14900d5 ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPCity.csv -@@ -0,0 +1,7 @@ -+10.53.0.1/32,US,CA,"Redwood City",94063,37.4914,-122.2110,807,650 -+10.53.0.2/32,US,CA,"Santa Cruz",95060,37.0448,-122.1021,828,831 -+10.53.0.3/32,US,OK,"Oklahoma City",73120,35.5798,-97.5731,650,405 -+10.53.0.4/32,US,VA,Ashland,23005,37.7563,-77.4888,556,804 -+10.53.0.5/32,US,GA,Atlanta,30345,33.8477,-84.2814,524,404 -+10.53.0.6/32,US,CO,Morrison,80465,39.6081,-105.2072,751,303 -+10.53.0.7/32,US,AK,Ketchikan,99901,55.6153,-131.5848,747,907 -diff --git a/bin/tests/system/geoip/data/GeoIPCityv6.csv b/bin/tests/system/geoip/data/GeoIPCityv6.csv -new file mode 100644 -index 0000000..5f09e62 ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPCityv6.csv -@@ -0,0 +1,7 @@ -+"fd92:7065:b8e:ffff::1","fd92:7065:b8e:ffff::1","US","CA","Redwood City","94063",37.4914,-122.2110,807,650 -+"fd92:7065:b8e:ffff::2","fd92:7065:b8e:ffff::2","US","CA","Santa Cruz","95060",37.0448,-122.1021,828,831 -+"fd92:7065:b8e:ffff::3","fd92:7065:b8e:ffff::3","US","OK","Oklahoma City","73120",35.5798,-97.5731,650,405 -+"fd92:7065:b8e:ffff::4","fd92:7065:b8e:ffff::4","DE","07","Lotte","",52.2833,7.9167,0,0 -+"fd92:7065:b8e:ffff::5","fd92:7065:b8e:ffff::5","US","GA","Atlanta","30345",33.8477,-84.2814,524,404 -+"fd92:7065:b8e:ffff::6","fd92:7065:b8e:ffff::6","US","CO","Morrison","80465",39.6081,-105.2072,751,303 -+"fd92:7065:b8e:ffff::7","fd92:7065:b8e:ffff::7","US","AK","Ketchikan","99901",55.6153,-131.5848,747,907 -diff --git a/bin/tests/system/geoip/data/GeoIPDomain.csv b/bin/tests/system/geoip/data/GeoIPDomain.csv -new file mode 100644 -index 0000000..8611d65 ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPDomain.csv -@@ -0,0 +1,7 @@ -+10.53.0.1/32 one.de -+10.53.0.2/32 two.com -+10.53.0.3/32 three.com -+10.53.0.4/32 four.com -+10.53.0.5/32 five.es -+10.53.0.6/32 six.it -+10.53.0.7/32 seven.org -diff --git a/bin/tests/system/geoip/data/GeoIPISP.csv b/bin/tests/system/geoip/data/GeoIPISP.csv -new file mode 100644 -index 0000000..3d5b4fa ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPISP.csv -@@ -0,0 +1,7 @@ -+10.53.0.1/32 One Systems, Inc. -+10.53.0.2/32 Two Technology Ltd. -+10.53.0.3/32 Three Network Labs -+10.53.0.4/32 Four University -+10.53.0.5/32 Five Telecom -+10.53.0.6/32 Six Company -+10.53.0.7/32 Seven Communications -diff --git a/bin/tests/system/geoip/data/GeoIPNetSpeed.csv b/bin/tests/system/geoip/data/GeoIPNetSpeed.csv -new file mode 100644 -index 0000000..4ede137 ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPNetSpeed.csv -@@ -0,0 +1,7 @@ -+10.53.0.1/32 0 -+10.53.0.2/32 1 -+10.53.0.3/32 2 -+10.53.0.4/32 3 -+10.53.0.5/32 0 -+10.53.0.6/32 1 -+10.53.0.7/32 2 -diff --git a/bin/tests/system/geoip/data/GeoIPOrg.csv b/bin/tests/system/geoip/data/GeoIPOrg.csv -new file mode 100644 -index 0000000..3d5b4fa ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPOrg.csv -@@ -0,0 +1,7 @@ -+10.53.0.1/32 One Systems, Inc. -+10.53.0.2/32 Two Technology Ltd. -+10.53.0.3/32 Three Network Labs -+10.53.0.4/32 Four University -+10.53.0.5/32 Five Telecom -+10.53.0.6/32 Six Company -+10.53.0.7/32 Seven Communications -diff --git a/bin/tests/system/geoip/data/GeoIPRegion.csv b/bin/tests/system/geoip/data/GeoIPRegion.csv -new file mode 100644 -index 0000000..0bcd872 ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPRegion.csv -@@ -0,0 +1,7 @@ -+10.53.0.1/32 US CA -+10.53.0.2/32 CA BC -+10.53.0.3/32 US OK -+10.53.0.4/32 AU -+10.53.0.5/32 US CO -+10.53.0.6/32 CA ON -+10.53.0.7/32 NL -diff --git a/bin/tests/system/geoip/data/GeoIPv6.csv b/bin/tests/system/geoip/data/GeoIPv6.csv -new file mode 100644 -index 0000000..919bf86 ---- /dev/null -+++ b/bin/tests/system/geoip/data/GeoIPv6.csv -@@ -0,0 +1,7 @@ -+"fd92:7065:b8e:ffff::1/128",AU -+"fd92:7065:b8e:ffff::2/128",US -+"fd92:7065:b8e:ffff::3/128",GB -+"fd92:7065:b8e:ffff::4/128",CA -+"fd92:7065:b8e:ffff::5/128",CL -+"fd92:7065:b8e:ffff::6/128",DE -+"fd92:7065:b8e:ffff::7/128",EH -diff --git a/bin/tests/system/geoip/data/README b/bin/tests/system/geoip/data/README -new file mode 100644 -index 0000000..0711cde ---- /dev/null -+++ b/bin/tests/system/geoip/data/README -@@ -0,0 +1,29 @@ -+The data data files in this directory are sample GeoIP databases, -+generated from the corresponding CSV files. Thanks to MaxMind, Inc. -+for assistance with producing these files. -+ -+Unless otherwise noted, the databases only support IPv4: -+ -+GeoIP.dat: Country (IPv4) -+GeoIPv6.dat: Country (IPv6) -+GeoIPCity.dat: City (IPv4) -+GeoIPCityv6.dat: City (IPv6) -+GeoIPRegion.dat: Region -+GeoIPISP.dat: ISP -+GeoIPOrg.dat: Organization -+GeoIPDoain.dat: Domain Name -+GeoIPASNum.dat: AS Number -+GeoIPNetSpeed.dat: Net Speed -+ -+GeoIP.dat can also be generated using the open source 'geoip-csv-to-dat' -+utility: -+ -+$ geoip-csv-to-dat -i "BIND9 geoip test data v1" -o GeoIP.dat << EOF -+"10.53.0.1","10.53.0.1","171245569","171245569","AU","Australia" -+"10.53.0.2","10.53.0.2","171245570","171245570","US","United States" -+"10.53.0.3","10.53.0.3","171245571","171245571","GB","United Kingdom" -+"10.53.0.4","10.53.0.4","171245572","171245572","CA","Canada" -+"10.53.0.5","10.53.0.5","171245573","171245573","CL","Chile" -+"10.53.0.6","10.53.0.6","171245574","171245574","DE","Germany" -+"10.53.0.7","10.53.0.7","171245575","171245575","EH","Western Sahara" -+EOF -diff --git a/bin/tests/system/geoip/geoip.c b/bin/tests/system/geoip/geoip.c -new file mode 100644 -index 0000000..e0dadad ---- /dev/null -+++ b/bin/tests/system/geoip/geoip.c -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include -+#include -+ -+int -+main(int argc, char **argv) { -+ -+ UNUSED(argc); -+ UNUSED(argv); -+ -+#ifdef HAVE_GEOIP -+ return (0); -+#else -+ return (1); -+#endif -+} -diff --git a/bin/tests/system/geoip/ns2/example.db.in b/bin/tests/system/geoip/ns2/example.db.in -new file mode 100644 -index 0000000..52a233b ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/example.db.in -@@ -0,0 +1,24 @@ -+; Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") -+; -+; Permission to use, copy, modify, and/or distribute this software for any -+; purpose with or without fee is hereby granted, provided that the above -+; copyright notice and this permission notice appear in all copies. -+; -+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+; PERFORMANCE OF THIS SOFTWARE. -+ -+$TTL 300 ; 5 minutes -+@ IN SOA mname1. . ( -+ 2000042407 ; serial -+ 20 ; refresh (20 seconds) -+ 20 ; retry (20 seconds) -+ 1814400 ; expire (3 weeks) -+ 3600 ; minimum (1 hour) -+ ) -+ NS ns2 -+ns2 A 10.53.0.2 -diff --git a/bin/tests/system/geoip/ns2/named1.conf b/bin/tests/system/geoip/ns2/named1.conf -new file mode 100644 -index 0000000..66aca6f ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named1.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip db country country AU; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip db country country US; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip db country country GB; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip db country country CA; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip db country country CL; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip db country country DE; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip db country country EH; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named10.conf b/bin/tests/system/geoip/ns2/named10.conf -new file mode 100644 -index 0000000..2dd52ae ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named10.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip asnum "AS100001"; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip asnum "AS100002"; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip asnum "AS100003"; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip asnum "AS100004"; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip asnum "AS100005"; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip asnum "AS100006"; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip asnum "AS100007"; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named11.conf b/bin/tests/system/geoip/ns2/named11.conf -new file mode 100644 -index 0000000..af87edf ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named11.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip domain one.de; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip domain two.com; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip domain three.com; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip domain four.com; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip domain five.es; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip domain six.it; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip domain seven.org; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named12.conf b/bin/tests/system/geoip/ns2/named12.conf -new file mode 100644 -index 0000000..85c0d32 ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named12.conf -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip netspeed 0; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip netspeed 1; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip netspeed 2; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip netspeed 3; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named13.conf b/bin/tests/system/geoip/ns2/named13.conf -new file mode 100644 -index 0000000..a650a63 ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named13.conf -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+acl blocking { -+ geoip db country country AU; -+}; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+ blackhole { blocking; }; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named14.conf b/bin/tests/system/geoip/ns2/named14.conf -new file mode 100644 -index 0000000..f92d252 ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named14.conf -@@ -0,0 +1,112 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+acl gAU { geoip db country country AU; }; -+acl gUS { geoip db country country US; }; -+acl gGB { geoip db country country GB; }; -+acl gCA { geoip db country country CA; }; -+acl gCL { geoip db country country CL; }; -+acl gDE { geoip db country country DE; }; -+acl gEH { geoip db country country EH; }; -+ -+view one { -+ match-clients { gAU; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { gUS; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { gGB; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { gCA; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { gCL; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { gDE; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { gEH; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named15.conf b/bin/tests/system/geoip/ns2/named15.conf -new file mode 100644 -index 0000000..6ac837b ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named15.conf -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { fd92:7065:b8e:ffff::2; }; -+ recursion no; -+ geoip-directory "../data2"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-sha256; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view two { -+ match-clients { geoip country US; }; -+ zone "example" { -+ type master; -+ file "../ns2/example2.db"; -+ }; -+}; -+ -+view none { -+ zone "example" { -+ type master; -+ file "examplebogus.db"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named2.conf b/bin/tests/system/geoip/ns2/named2.conf -new file mode 100644 -index 0000000..67a5155 ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named2.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip db country country AUS; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip db country country USA; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip db country country GBR; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip db country country CAN; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip db country country CHL; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip db country country DEU; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip db country country ESH; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named3.conf b/bin/tests/system/geoip/ns2/named3.conf -new file mode 100644 -index 0000000..65113a6 ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named3.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip db country country Australia; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip db country country "United States"; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip db country country "United Kingdom"; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip db country country Canada; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip db country country Chile; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip db country country Germany; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip db country country "Western Sahara"; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named4.conf b/bin/tests/system/geoip/ns2/named4.conf -new file mode 100644 -index 0000000..d2393d5 ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named4.conf -@@ -0,0 +1,96 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip region CA; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip region OK; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip region VA; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip region GA; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip region CO; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip region AK; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named5.conf b/bin/tests/system/geoip/ns2/named5.conf -new file mode 100644 -index 0000000..011e310 ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named5.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip db region region "California"; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip db region region "British Columbia"; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip db region region "Oklahoma"; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip db region country AU; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip db region region "Colorado"; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip db region region "Ontario"; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip db region country NL; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named6.conf b/bin/tests/system/geoip/ns2/named6.conf -new file mode 100644 -index 0000000..7ef7b19 ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named6.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { fd92:7065:b8e:ffff::1; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip city "Redwood City"; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip city "Santa Cruz"; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip city "Oklahoma City"; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip city "Ashland"; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip city "Atlanta"; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip city "Morrison"; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip city "Ketchikan"; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named7.conf b/bin/tests/system/geoip/ns2/named7.conf -new file mode 100644 -index 0000000..118bdbe ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named7.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip isp "One Systems, Inc."; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip isp "Two Technology Ltd."; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip isp "Three Network Labs"; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip isp "Four University"; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip isp "Five Telecom"; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip isp "Six Company"; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip isp "Seven Communications"; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named8.conf b/bin/tests/system/geoip/ns2/named8.conf -new file mode 100644 -index 0000000..9cb5c0a ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named8.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip org "One Systems, Inc."; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip org "Two Technology Ltd."; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip org "Three Network Labs"; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip org "Four University"; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip org "Five Telecom"; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip org "Six Company"; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip org "Seven Communications"; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/ns2/named9.conf b/bin/tests/system/geoip/ns2/named9.conf -new file mode 100644 -index 0000000..af2f7ff ---- /dev/null -+++ b/bin/tests/system/geoip/ns2/named9.conf -@@ -0,0 +1,104 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "../data"; -+}; -+ -+key rndc_key { -+ secret "1234abcd8765"; -+ algorithm hmac-md5; -+}; -+ -+controls { -+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; -+}; -+ -+view one { -+ match-clients { geoip asnum "AS100001 One Systems, Inc."; }; -+ zone "example" { -+ type master; -+ file "example1.db"; -+ }; -+}; -+ -+view two { -+ match-clients { geoip asnum "AS100002 Two Technology Ltd."; }; -+ zone "example" { -+ type master; -+ file "example2.db"; -+ }; -+}; -+ -+view three { -+ match-clients { geoip asnum "AS100003 Three Network Labs"; }; -+ zone "example" { -+ type master; -+ file "example3.db"; -+ }; -+}; -+ -+view four { -+ match-clients { geoip asnum "AS100004 Four University"; }; -+ zone "example" { -+ type master; -+ file "example4.db"; -+ }; -+}; -+ -+view five { -+ match-clients { geoip asnum "AS100005 Five Telecom"; }; -+ zone "example" { -+ type master; -+ file "example5.db"; -+ }; -+}; -+ -+view six { -+ match-clients { geoip asnum "AS100006 Six Company"; }; -+ zone "example" { -+ type master; -+ file "example6.db"; -+ }; -+}; -+ -+view seven { -+ match-clients { geoip asnum "AS100007 Seven Communications"; }; -+ zone "example" { -+ type master; -+ file "example7.db"; -+ }; -+}; -+ -+view none { -+ match-clients { any; }; -+ zone "example" { -+ type master; -+ file "example.db.in"; -+ }; -+}; -diff --git a/bin/tests/system/geoip/options.conf b/bin/tests/system/geoip/options.conf -new file mode 100644 -index 0000000..b4d46cb ---- /dev/null -+++ b/bin/tests/system/geoip/options.conf -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+// NS2 -+ -+controls { /* empty */ }; -+ -+options { -+ query-source address 10.53.0.2; -+ notify-source 10.53.0.2; -+ transfer-source 10.53.0.2; -+ port 5300; -+ pid-file "named.pid"; -+ listen-on { 10.53.0.2; }; -+ listen-on-v6 { none; }; -+ recursion no; -+ geoip-directory "data"; -+ allow-query { -+ geoip area 831; -+ geoip areacode 831; -+ geoip metro 828; -+ geoip metrocode 828; -+ geoip tz PST; -+ geoip timezone PST; -+ geoip postal 95060; -+ geoip postalcode 95060; -+ }; -+}; -+ -diff --git a/bin/tests/system/geoip/prereq.sh b/bin/tests/system/geoip/prereq.sh -new file mode 100644 -index 0000000..b78be41 ---- /dev/null -+++ b/bin/tests/system/geoip/prereq.sh -@@ -0,0 +1,23 @@ -+#!/bin/sh -+# -+# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+if ./geoip -+then -+ : -+else -+ echo "I:This test requires GeoIP support." >&2 -+ exit 1 -+fi -diff --git a/bin/tests/system/geoip/setup.sh b/bin/tests/system/geoip/setup.sh -new file mode 100644 -index 0000000..5c5e2ca ---- /dev/null -+++ b/bin/tests/system/geoip/setup.sh -@@ -0,0 +1,27 @@ -+#!/bin/sh -+# -+# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+sh clean.sh -+ -+cp ns2/named1.conf ns2/named.conf -+ -+for i in 1 2 3 4 5 6 7 other bogus; do -+ cp ns2/example.db.in ns2/example${i}.db -+ echo "@ IN TXT \"$i\"" >> ns2/example$i.db -+done -+ -+mkdir -p data2 -+cp data/GeoIPv6.dat data2/ -diff --git a/bin/tests/system/geoip/tests.sh b/bin/tests/system/geoip/tests.sh -new file mode 100644 -index 0000000..07635b1 ---- /dev/null -+++ b/bin/tests/system/geoip/tests.sh -@@ -0,0 +1,328 @@ -+#!/bin/sh -+# -+# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+SYSTEMTESTTOP=.. -+. $SYSTEMTESTTOP/conf.sh -+ -+status=0 -+n=0 -+ -+rm -f dig.out.* -+ -+DIGOPTS="+tcp +short -p 5300 @10.53.0.2" -+DIGOPTS6="+tcp +short -p 5300 @fd92:7065:b8e:ffff::2" -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP country database by code ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named2.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP country database by three-letter code ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named3.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP country database by name ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named4.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP region code, no specified database ($n)" -+ret=0 -+lret=0 -+# skipping 2 on purpose here; it has the same region code as 1 -+for i in 1 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named5.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP region database by region name and country code ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named6.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+if $TESTSOCK6 fd92:7065:b8e:ffff::3 -+then -+ n=`expr $n + 1` -+ echo "I:checking GeoIP city database by city name using IPv6 ($n)" -+ ret=0 -+ $DIG +tcp +short -p 5300 @fd92:7065:b8e:ffff::1 -6 txt example -b fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n || ret=1 -+ [ $ret -eq 0 ] || echo "I:failed" -+ status=`expr $status + $ret` -+else -+ echo "I:IPv6 unavailable; skipping" -+fi -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP city database by city name ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named7.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP isp database ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named8.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP org database ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named9.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP asnum database ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named10.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP asnum database - ASNNNN only ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named11.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP domain database ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named12.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP netspeed database ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named13.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP blackhole ACL ($n)" -+ret=0 -+$DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n || ret=1 -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 status 2>&1 > rndc.out.ns2.test$n || ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:reloading server" -+cp -f ns2/named14.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP country database by code (using nested ACLs) ($n)" -+ret=0 -+lret=0 -+for i in 1 2 3 4 5 6 7; do -+ $DIG $DIGOPTS txt example -b 10.53.0.$i > dig.out.ns2.test$n.$i || lret=1 -+ j=`cat dig.out.ns2.test$n.$i | tr -d '"'` -+ [ "$i" = "$j" ] || lret=1 -+ [ $lret -eq 1 ] && break -+done -+[ $lret -eq 1 ] && ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+n=`expr $n + 1` -+echo "I:reloading server with different geoip-directory ($n)" -+ret=0 -+cp -f ns2/named15.conf ns2/named.conf -+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /' -+sleep 3 -+awk '/using "..\/data2" as GeoIP directory/ {m=1} ; { if (m>0) { print } }' ns2/named.run | grep "GeoIP City .* DB not available" > /dev/null || ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+n=`expr $n + 1` -+echo "I:checking GeoIP v4/v6 when only IPv6 database is available ($n)" -+ret=0 -+$DIG $DIGOPTS -4 txt example -b 10.53.0.2 > dig.out.ns2.test$n.1 || ret=1 -+j=`cat dig.out.ns2.test$n.1 | tr -d '"'` -+[ "$j" = "bogus" ] || ret=1 -+if $TESTSOCK6 fd92:7065:b8e:ffff::2; then -+ $DIG $DIGOPTS6 txt example -b fd92:7065:b8e:ffff::2 > dig.out.ns2.test$n.2 || ret=1 -+ j=`cat dig.out.ns2.test$n.2 | tr -d '"'` -+ [ "$j" = "2" ] || ret=1 -+fi -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+n=`expr $n + 1` -+echo "I:checking other GeoIP options are parsed correctly ($n)" -+ret=0 -+$CHECKCONF options.conf || ret=1 -+[ $ret -eq 0 ] || echo "I:failed" -+status=`expr $status + $ret` -+ -+echo "I:exit status: $status" -+exit $status -diff --git a/config.h.in b/config.h.in -index f2eb59a..6ed8381 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -214,6 +214,15 @@ int sigwait(const unsigned int *set, int *sig); - /* Define to 1 if you have the header file. */ - #undef HAVE_FCNTL_H - -+/* Build with GeoIP support */ -+#undef HAVE_GEOIP -+ -+/* Build with GeoIP City IPv6 support */ -+#undef HAVE_GEOIP_CITY_V6 -+ -+/* Build with GeoIP Country IPv6 support */ -+#undef HAVE_GEOIP_V6 -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_GSSAPI_GSSAPI_H - -diff --git a/configure.in b/configure.in -index e8c68fc..71e90c1 100644 ---- a/configure.in -+++ b/configure.in -@@ -1252,6 +1252,99 @@ if test "$have_clock_gt" = "yes"; then - fi - - -+GEOIPLINKSRCS= -+GEOIPLINKOBJS= -+AC_ARG_WITH(geoip, -+[ --with-geoip=PATH Build with GeoIP support (yes|no|path)], -+ use_geoip="$withval", use_geoip="no") -+ -+if test "$use_geoip" = "yes" -+then -+ for d in /usr /usr/local /opt/local -+ do -+ if test -f $d/include/GeoIP.h -+ then -+ use_geoip=$d -+ break -+ fi -+ done -+fi -+ -+case "$use_geoip" in -+ no|'') -+ AC_MSG_CHECKING([for GeoIP support]) -+ AC_MSG_RESULT([disabled]) -+ ;; -+ *) -+ if test -d "$use_geoip" -o -L "$use_geoip" -+ then -+ CFLAGS="$CFLAGS -I$use_geoip/include" -+ CPPFLAGS="$CPPFLAGS -I$use_geoip/include" -+ LIBS="$LIBS -L$use_geoip/lib" -+ case "$host_os" in -+ netbsd*|openbsd*|solaris*) -+ LIBS="$LIBS -Wl,-rpath=$use_geoip/lib" -+ ;; -+ esac -+ elif test "$use_geoip" = "yes" -+ then -+ AC_MSG_ERROR([GeoIP path not found]) -+ else -+ AC_MSG_ERROR([GeoIP path $use_geoip does not exist]) -+ fi -+ AC_CHECK_HEADER(GeoIP.h, [], -+ [AC_MSG_ERROR([GeoIP header file not found])] -+ ) -+ AC_SEARCH_LIBS(GeoIP_open, GeoIP, [], -+ [AC_MSG_ERROR([GeoIP library not found])] -+ ) -+ AC_SEARCH_LIBS(fabsf, m, [], -+ [AC_MSG_ERROR([Math library not found])] -+ ) -+ AC_DEFINE(HAVE_GEOIP, 1, Build with GeoIP support) -+ GEOIPLINKSRCS='${GEOIPLINKSRCS}' -+ GEOIPLINKOBJS='${GEOIPLINKOBJS}' -+ AC_MSG_CHECKING([for GeoIP support]) -+ AC_MSG_RESULT([yes]) -+ -+ AC_MSG_CHECKING([for GeoIP Country IPv6 support]) -+ AC_COMPILE_IFELSE( -+ [AC_LANG_PROGRAM([ -+ #include -+ #include -+ ], [ -+ struct in6_addr in6; -+ GeoIP_country_name_by_ipnum_v6(NULL, in6); -+ ])], -+ [ -+ AC_MSG_RESULT([yes]) -+ AC_DEFINE(HAVE_GEOIP_V6, 1, Build with GeoIP Country IPv6 support) -+ ], -+ [AC_MSG_RESULT([no])] -+ ) -+ -+ AC_MSG_CHECKING([for GeoIP City IPv6 support]) -+ AC_COMPILE_IFELSE( -+ [AC_LANG_PROGRAM([ -+ #include -+ #include -+ #include -+ ], [ -+ struct in6_addr in6; -+ int i = GEOIP_CITY_EDITION_REV0_V6; -+ GeoIP_record_by_ipnum_v6(NULL, in6); -+ ])], -+ [ -+ AC_MSG_RESULT([yes]) -+ AC_DEFINE(HAVE_GEOIP_CITY_V6, 1, Build with GeoIP City IPv6 support) -+ ], -+ [AC_MSG_RESULT([no])] -+ ) -+ ;; -+esac -+AC_SUBST(GEOIPLINKSRCS) -+AC_SUBST(GEOIPLINKOBJS) -+ - AC_MSG_CHECKING(for GSSAPI library) - AC_ARG_WITH(gssapi, - [ --with-gssapi=PATH Specify path for system-supplied GSSAPI [[default=yes]]], -@@ -3965,6 +4058,7 @@ AC_CONFIG_FILES([ - bin/tests/system/dyndb/driver/Makefile - bin/tests/system/ecdsa/prereq.sh - bin/tests/system/filter-aaaa/Makefile -+ bin/tests/system/geoip/Makefile - bin/tests/system/gost/prereq.sh - bin/tests/system/lwresd/Makefile - bin/tests/system/rpz/Makefile -diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml -index 16b50a3..b79bfa0 100644 ---- a/doc/arm/Bv9ARM-book.xml -+++ b/doc/arm/Bv9ARM-book.xml -@@ -3412,6 +3412,62 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. - - - -+ -+ When BIND 9 is built with GeoIP support, -+ ACLs can also be used for geographic access restrictions. -+ This is done by specifying an ACL element of the form: -+ geoip db database field value -+ -+ -+ The field indicates which field -+ to search for a match. Available fields are "country", -+ "region", "city", "continent", "postal" (postal code), -+ "metro" (metro code), "area" (area code), "tz" (timezone), -+ "isp", "org", "asnum", "domain" and "netspeed". -+ -+ -+ value is the value to searched for -+ within the database. A string may be quoted if it contains -+ spaces or other special characters. If this is a "country" -+ search and the string is two characters long, then it must be a -+ standard ISO-3166-1 two-letter country code, and if it is three -+ characters long then it must be an ISO-3166-1 three-letter -+ country code; otherwise it is the full name of the country. -+ Similarly, if this is a "region" search and the string is -+ two characters long, then it must be a standard two-letter state -+ or province abbreviation; otherwise it is the full name of the -+ state or province. -+ -+ -+ The database field indicates which -+ GeoIP database to search for a match. In most cases this is -+ unnecessary, because most search fields can only be found in -+ a single database. However, searches for country can be -+ answered from the "city", "region", or "country" databases, -+ and searches for region (i.e., state or provice) can be -+ answered from the "city" or "region" databases. For these -+ search types, specifying a database -+ will force the query to be answered from that database and no -+ other. If database is not -+ specified, then these queries will be answered from the "city", -+ database if it is installed, or the "region" database if it is -+ installed, or the "country" database, in that order. -+ -+ -+ Some example GeoIP ACLs: -+ -+ geoip country US; -+geoip country JAP; -+geoip db country country Canada; -+geoip db region region WA; -+geoip city "San Francisco"; -+geoip region Oklahoma; -+geoip postal 95062; -+geoip tz "America/Los_Angeles"; -+geoip org "Internet Systems Consortium"; -+ -+ -+ - - - <command>controls</command> Statement Grammar -@@ -4692,6 +4748,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] - hostname hostname_string; - server-id server_id_string; - directory path_name; -+ geoip-directory path_name; - key-directory path_name; - managed-keys-directory path_name; - named-xfer path_name; -@@ -5048,6 +5105,21 @@ badresp:1,adberr:0,findfail:0,valfail:0] - - - -+ geoip-directory -+ -+ -+ Specifies the directory containing GeoIP -+ .dat database files for GeoIP -+ initialization. By default, this option is unset -+ and the GeoIP support will use libGeoIP's -+ built-in directory. -+ (For details, see about the -+ geoip ACL.) -+ -+ -+ -+ -+ - key-directory - - -diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in -index 2efcc5a..ae316c5 100644 ---- a/lib/dns/Makefile.in -+++ b/lib/dns/Makefile.in -@@ -56,6 +56,8 @@ DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ @PKCS11LINKOBJS@ \ - - RRLOBJS = rrl.@O@ - -+GEOIPLINKOBJS = geoip.@O@ -+ - # Alphabetically - DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ - cache.@O@ callbacks.@O@ clientinfo.@O@ compress.@O@ \ -@@ -75,7 +77,7 @@ DNSOBJS = acache.@O@ acl.@O@ adb.@O@ byaddr.@O@ \ - tsec.@O@ tsig.@O@ ttl.@O@ update.@O@ validator.@O@ \ - version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ zt.@O@ - --OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} @RRLLINKOBJS@ -+OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} @RRLLINKOBJS@ @GEOIPLINKOBJS@ - - # Alphabetically - OPENSSLGOSTLINKSRCS = opensslgost_link.c -@@ -90,6 +92,8 @@ DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ @PKCS11LINKSRCS@ \ - dst_result.c gssapi_link.c gssapictx.c \ - hmac_link.c key.c - -+GEOIOLINKSRCS = geoip.c -+ - DNSSRCS = acache.c acl.c adb.c byaddr.c \ - cache.c callbacks.c clientinfo.c compress.c \ - db.c dbiterator.c dbtable.c diff.c dispatch.c \ -@@ -107,7 +111,7 @@ DNSSRCS = acache.c acl.c adb.c byaddr.c \ - - RRLSRCS = rrl.c - --SRCS = ${DSTSRCS} ${DNSSRCS} @RRLLINKSRCS@ -+SRCS = ${DSTSRCS} ${DNSSRCS} @RRLLINKSRCS@ @GEOIPLINKSRCS@ - - SUBDIRS = include - TARGETS = include/dns/enumtype.h include/dns/enumclass.h \ -diff --git a/lib/dns/acl.c b/lib/dns/acl.c -index 3221d30..aad9aa5 100644 ---- a/lib/dns/acl.c -+++ b/lib/dns/acl.c -@@ -29,6 +29,7 @@ - #include - #include - -+ - /* - * Create a new ACL, including an IP table and an array with room - * for 'n' ACL elements. The elements are uninitialized and the -@@ -336,6 +337,14 @@ dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos) - return result; - } - -+#ifdef HAVE_GEOIP -+ /* Duplicate GeoIP data */ -+ if (source->elements[i].type == dns_aclelementtype_geoip) { -+ dest->elements[nelem + i].geoip_elem = -+ source->elements[i].geoip_elem; -+ } -+#endif -+ - /* reverse sense of positives if this is a negative acl */ - if (!pos && source->elements[i].negative == ISC_FALSE) { - dest->elements[nelem + i].negative = ISC_TRUE; -@@ -386,9 +395,8 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr, - if (matchelt != NULL) - *matchelt = e; - return (ISC_TRUE); -- } else { -+ } else - return (ISC_FALSE); -- } - - case dns_aclelementtype_nestedacl: - inner = e->nestedacl; -@@ -406,6 +414,12 @@ dns_aclelement_match(const isc_netaddr_t *reqaddr, - inner = env->localnets; - break; - -+#ifdef HAVE_GEOIP -+ case dns_aclelementtype_geoip: -+ if (env == NULL || env->geoip == NULL) -+ return (ISC_FALSE); -+ return (dns_geoip_match(reqaddr, env->geoip, &e->geoip_elem)); -+#endif - default: - /* Should be impossible. */ - INSIST(0); -@@ -560,7 +574,7 @@ dns_acl_isinsecure(const dns_acl_t *a) { - insecure = insecure_prefix_found; - UNLOCK(&insecure_prefix_lock); - if (insecure) -- return(ISC_TRUE); -+ return (ISC_TRUE); - - /* Now check non-radix elements */ - for (i = 0; i < a->length; i++) { -@@ -609,6 +623,9 @@ dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) { - if (result != ISC_R_SUCCESS) - goto cleanup_localhost; - env->match_mapped = ISC_FALSE; -+#ifdef HAVE_GEOIP -+ env->geoip = NULL; -+#endif - return (ISC_R_SUCCESS); - - cleanup_localhost: -diff --git a/lib/dns/geoip.c b/lib/dns/geoip.c -new file mode 100644 -index 0000000..5387ebb ---- /dev/null -+++ b/lib/dns/geoip.c -@@ -0,0 +1,820 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#ifdef HAVE_GEOIP -+#include -+#include -+ -+/* -+ * This structure preserves state from the previous GeoIP lookup, -+ * so that successive lookups for the same data from the same IP -+ * address will not require repeated calls into the GeoIP library -+ * to look up data in the database. This should improve performance -+ * somewhat. -+ * -+ * For lookups in the City and Region databases, we preserve pointers -+ * to the GeoIPRecord and GeoIPregion structures; these will need to be -+ * freed by GeoIPRecord_delete() and GeoIPRegion_delete(). -+ * -+ * for lookups in ISP, AS, Org and Domain we prserve a pointer to -+ * the returned name; these must be freed by free(). -+ * -+ * For lookups in Country we preserve a pointer to the text of -+ * the country code, name, etc (we use a different pointer for this -+ * than for the names returned by Org, ISP, etc, because those need -+ * to be freed but country lookups do not). -+ * -+ * For lookups in Netspeed we preserve the returned ID. -+ * -+ * XXX: Currently this mechanism is only used for IPv4 lookups; the -+ * family and addr6 fields are to be used IPv6 is added. -+ */ -+typedef struct geoip_state { -+ isc_uint16_t subtype; -+ unsigned int family; -+ isc_uint32_t ipnum; -+ geoipv6_t ipnum6; -+ GeoIPRecord *record; -+ GeoIPRegion *region; -+ const char *text; -+ char *name; -+ int id; -+ isc_mem_t *mctx; -+} geoip_state_t; -+ -+#ifdef ISC_PLATFORM_USETHREADS -+static isc_mutex_t key_mutex; -+static isc_boolean_t state_key_initialized = ISC_FALSE; -+static isc_thread_key_t state_key; -+static isc_once_t mutex_once = ISC_ONCE_INIT; -+static isc_mem_t *state_mctx = NULL; -+ -+static void -+key_mutex_init(void) { -+ RUNTIME_CHECK(isc_mutex_init(&key_mutex) == ISC_R_SUCCESS); -+} -+ -+static void -+free_state(void *arg) { -+ geoip_state_t *state = arg; -+ if (state != NULL && state->record != NULL) -+ GeoIPRecord_delete(state->record); -+ if (state != NULL) -+ isc_mem_putanddetach(&state->mctx, -+ state, sizeof(geoip_state_t)); -+ isc_thread_key_setspecific(state_key, NULL); -+} -+ -+static isc_result_t -+state_key_init(void) { -+ isc_result_t result; -+ -+ result = isc_once_do(&mutex_once, key_mutex_init); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ -+ if (!state_key_initialized) { -+ LOCK(&key_mutex); -+ if (!state_key_initialized) { -+ int ret; -+ -+ if (state_mctx == NULL) -+ result = isc_mem_create2(0, 0, &state_mctx, 0); -+ if (result != ISC_R_SUCCESS) -+ goto unlock; -+ isc_mem_setname(state_mctx, "geoip_state", NULL); -+ isc_mem_setdestroycheck(state_mctx, ISC_FALSE); -+ -+ ret = isc_thread_key_create(&state_key, free_state); -+ if (ret == 0) -+ state_key_initialized = ISC_TRUE; -+ else -+ result = ISC_R_FAILURE; -+ } -+ unlock: -+ UNLOCK(&key_mutex); -+ } -+ -+ return (result); -+} -+#else -+static geoip_state_t saved_state; -+#endif -+ -+static void -+clean_state(geoip_state_t *state) { -+ if (state == NULL) -+ return; -+ -+ if (state->record != NULL) { -+ GeoIPRecord_delete(state->record); -+ state->record = NULL; -+ } -+ if (state->region != NULL) { -+ GeoIPRegion_delete(state->region); -+ state->region = NULL; -+ } -+ if (state->name != NULL) { -+ free (state->name); -+ state->name = NULL; -+ } -+ state->ipnum = 0; -+ state->text = NULL; -+ state->id = 0; -+} -+ -+static isc_result_t -+set_state(unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6, -+ dns_geoip_subtype_t subtype, GeoIPRecord *record, -+ GeoIPRegion *region, char *name, const char *text, int id) -+{ -+ geoip_state_t *state = NULL; -+#ifdef ISC_PLATFORM_USETHREADS -+ isc_result_t result; -+ -+ result = state_key_init(); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ -+ state = (geoip_state_t *) isc_thread_key_getspecific(state_key); -+ if (state == NULL) { -+ state = (geoip_state_t *) isc_mem_get(state_mctx, -+ sizeof(geoip_state_t)); -+ if (state == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(state, 0, sizeof(*state)); -+ -+ result = isc_thread_key_setspecific(state_key, state); -+ if (result != ISC_R_SUCCESS) { -+ isc_mem_put(state_mctx, state, sizeof(geoip_state_t)); -+ return (result); -+ } -+ -+ isc_mem_attach(state_mctx, &state->mctx); -+ } else -+ clean_state(state); -+#else -+ state = &saved_state; -+ clean_state(state); -+#endif -+ -+ if (family == AF_INET) -+ state->ipnum = ipnum; -+ else -+ state->ipnum6 = *ipnum6; -+ -+ state->family = family; -+ state->subtype = subtype; -+ state->record = record; -+ state->region = region; -+ state->name = name; -+ state->text = text; -+ state->id = id; -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static geoip_state_t * -+get_state_for(unsigned int family, isc_uint32_t ipnum, -+ const geoipv6_t *ipnum6) -+{ -+ geoip_state_t *state; -+ -+#ifdef ISC_PLATFORM_USETHREADS -+ isc_result_t result; -+ -+ result = state_key_init(); -+ if (result != ISC_R_SUCCESS) -+ return (NULL); -+ -+ state = (geoip_state_t *) isc_thread_key_getspecific(state_key); -+ if (state == NULL) -+ return (NULL); -+#else -+ state = &saved_state; -+#endif -+ -+ if (state->family == family && -+ ((state->family == AF_INET && state->ipnum == ipnum) || -+ (state->family == AF_INET6 && ipnum6 != NULL && -+ memcmp(state->ipnum6.s6_addr, ipnum6->s6_addr, 16) == 0))) -+ return (state); -+ -+ return (NULL); -+} -+ -+/* -+ * Country lookups are performed if the previous lookup was from a -+ * different IP address than the current, or was for a search of a -+ * different subtype. -+ */ -+static const char * -+country_lookup(GeoIP *db, dns_geoip_subtype_t subtype, -+ unsigned int family, -+ isc_uint32_t ipnum, const geoipv6_t *ipnum6) -+{ -+ geoip_state_t *prev_state = NULL; -+ const char *text = NULL; -+ -+ REQUIRE(db != NULL); -+ -+#ifndef HAVE_GEOIP_V6 -+ /* no IPv6 support? give up now */ -+ if (family == AF_INET6) -+ return (NULL); -+#endif -+ -+ prev_state = get_state_for(family, ipnum, ipnum6); -+ if (prev_state != NULL && prev_state->subtype == subtype) -+ text = prev_state->text; -+ -+ if (text == NULL) { -+ switch (subtype) { -+ case dns_geoip_country_code: -+ if (family == AF_INET) -+ text = GeoIP_country_code_by_ipnum(db, ipnum); -+#ifdef HAVE_GEOIP_V6 -+ else -+ text = GeoIP_country_code_by_ipnum_v6(db, -+ *ipnum6); -+#endif -+ break; -+ case dns_geoip_country_code3: -+ if (family == AF_INET) -+ text = GeoIP_country_code3_by_ipnum(db, ipnum); -+#ifdef HAVE_GEOIP_V6 -+ else -+ text = GeoIP_country_code3_by_ipnum_v6(db, -+ *ipnum6); -+#endif -+ break; -+ case dns_geoip_country_name: -+ if (family == AF_INET) -+ text = GeoIP_country_name_by_ipnum(db, ipnum); -+#ifdef HAVE_GEOIP_V6 -+ else -+ text = GeoIP_country_name_by_ipnum_v6(db, -+ *ipnum6); -+#endif -+ break; -+ default: -+ INSIST(0); -+ } -+ -+ set_state(family, ipnum, ipnum6, subtype, -+ NULL, NULL, NULL, text, 0); -+ } -+ -+ return (text); -+} -+ -+static char * -+city_string(GeoIPRecord *record, dns_geoip_subtype_t subtype, int *maxlen) { -+ const char *s; -+ char *deconst; -+ -+ REQUIRE(record != NULL); -+ REQUIRE(maxlen != NULL); -+ -+ /* Set '*maxlen' to the maximum length of this subtype, if any */ -+ switch (subtype) { -+ case dns_geoip_city_countrycode: -+ case dns_geoip_city_region: -+ case dns_geoip_city_continentcode: -+ *maxlen = 2; -+ break; -+ -+ case dns_geoip_city_countrycode3: -+ *maxlen = 3; -+ break; -+ -+ default: -+ /* No fixed length; just use strcasecmp() for comparison */ -+ *maxlen = 255; -+ } -+ -+ switch (subtype) { -+ case dns_geoip_city_countrycode: -+ return (record->country_code); -+ case dns_geoip_city_countrycode3: -+ return (record->country_code3); -+ case dns_geoip_city_countryname: -+ return (record->country_name); -+ case dns_geoip_city_region: -+ return (record->region); -+ case dns_geoip_city_regionname: -+ s = GeoIP_region_name_by_code(record->country_code, -+ record->region); -+ DE_CONST(s, deconst); -+ return (deconst); -+ case dns_geoip_city_name: -+ return (record->city); -+ case dns_geoip_city_postalcode: -+ return (record->postal_code); -+ case dns_geoip_city_continentcode: -+ return (record->continent_code); -+ case dns_geoip_city_timezonecode: -+ s = GeoIP_time_zone_by_country_and_region(record->country_code, -+ record->region); -+ DE_CONST(s, deconst); -+ return (deconst); -+ default: -+ INSIST(0); -+ } -+} -+ -+static isc_boolean_t -+is_city(dns_geoip_subtype_t subtype) { -+ switch (subtype) { -+ case dns_geoip_city_countrycode: -+ case dns_geoip_city_countrycode3: -+ case dns_geoip_city_countryname: -+ case dns_geoip_city_region: -+ case dns_geoip_city_regionname: -+ case dns_geoip_city_name: -+ case dns_geoip_city_postalcode: -+ case dns_geoip_city_continentcode: -+ case dns_geoip_city_timezonecode: -+ case dns_geoip_city_metrocode: -+ case dns_geoip_city_areacode: -+ return (ISC_TRUE); -+ default: -+ return (ISC_FALSE); -+ } -+} -+ -+/* -+ * GeoIPRecord lookups are performed if the previous lookup was -+ * from a different IP address than the current, or was for a search -+ * outside the City database. -+ */ -+static GeoIPRecord * -+city_lookup(GeoIP *db, dns_geoip_subtype_t subtype, -+ unsigned int family, isc_uint32_t ipnum, const geoipv6_t *ipnum6) -+{ -+ GeoIPRecord *record = NULL; -+ geoip_state_t *prev_state = NULL; -+ -+ REQUIRE(db != NULL); -+ -+#ifndef HAVE_GEOIP_V6 -+ /* no IPv6 support? give up now */ -+ if (family == AF_INET6) -+ return (NULL); -+#endif -+ -+ prev_state = get_state_for(family, ipnum, ipnum6); -+ if (prev_state != NULL && is_city(prev_state->subtype)) -+ record = prev_state->record; -+ -+ if (record == NULL) { -+ if (family == AF_INET) -+ record = GeoIP_record_by_ipnum(db, ipnum); -+#ifdef HAVE_GEOIP_V6 -+ else -+ record = GeoIP_record_by_ipnum_v6(db, *ipnum6); -+#endif -+ if (record == NULL) -+ return (NULL); -+ -+ set_state(family, ipnum, ipnum6, subtype, -+ record, NULL, NULL, NULL, 0); -+ } -+ -+ return (record); -+} -+ -+static char * -+region_string(GeoIPRegion *region, dns_geoip_subtype_t subtype, int *maxlen) { -+ const char *s; -+ char *deconst; -+ -+ REQUIRE(region != NULL); -+ REQUIRE(maxlen != NULL); -+ -+ switch (subtype) { -+ case dns_geoip_region_countrycode: -+ *maxlen = 2; -+ return (region->country_code); -+ case dns_geoip_region_code: -+ *maxlen = 2; -+ return (region->region); -+ case dns_geoip_region_name: -+ *maxlen = 255; -+ s = GeoIP_region_name_by_code(region->country_code, -+ region->region); -+ DE_CONST(s, deconst); -+ return (deconst); -+ default: -+ INSIST(0); -+ } -+} -+ -+static isc_boolean_t -+is_region(dns_geoip_subtype_t subtype) { -+ switch (subtype) { -+ case dns_geoip_region_countrycode: -+ case dns_geoip_region_code: -+ return (ISC_TRUE); -+ default: -+ return (ISC_FALSE); -+ } -+} -+ -+/* -+ * GeoIPRegion lookups are performed if the previous lookup was -+ * from a different IP address than the current, or was for a search -+ * outside the Region database. -+ */ -+static GeoIPRegion * -+region_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) { -+ GeoIPRegion *region = NULL; -+ geoip_state_t *prev_state = NULL; -+ -+ REQUIRE(db != NULL); -+ -+ prev_state = get_state_for(AF_INET, ipnum, NULL); -+ if (prev_state != NULL && is_region(prev_state->subtype)) -+ region = prev_state->region; -+ -+ if (region == NULL) { -+ region = GeoIP_region_by_ipnum(db, ipnum); -+ if (region == NULL) -+ return (NULL); -+ -+ set_state(AF_INET, ipnum, NULL, -+ subtype, NULL, region, NULL, NULL, 0); -+ } -+ -+ return (region); -+} -+ -+/* -+ * ISP, Organization, AS Number and Domain lookups are performed if -+ * the previous lookup was from a different IP address than the current, -+ * or was for a search of a different subtype. -+ */ -+static char * -+name_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) { -+ char *name = NULL; -+ geoip_state_t *prev_state = NULL; -+ -+ REQUIRE(db != NULL); -+ -+ prev_state = get_state_for(AF_INET, ipnum, NULL); -+ if (prev_state != NULL && prev_state->subtype == subtype) -+ name = prev_state->name; -+ -+ if (name == NULL) { -+ name = GeoIP_name_by_ipnum(db, ipnum); -+ if (name == NULL) -+ return (NULL); -+ -+ set_state(AF_INET, ipnum, NULL, -+ subtype, NULL, NULL, name, NULL, 0); -+ } -+ -+ return (name); -+} -+ -+/* -+ * Netspeed lookups are performed if the previous lookup was from a -+ * different IP address than the current, or was for a search of a -+ * different subtype. -+ */ -+static int -+netspeed_lookup(GeoIP *db, dns_geoip_subtype_t subtype, isc_uint32_t ipnum) { -+ geoip_state_t *prev_state = NULL; -+ isc_boolean_t found = ISC_FALSE; -+ int id = -1; -+ -+ REQUIRE(db != NULL); -+ -+ prev_state = get_state_for(AF_INET, ipnum, NULL); -+ if (prev_state != NULL && prev_state->subtype == subtype) { -+ id = prev_state->id; -+ found = ISC_TRUE; -+ } -+ -+ if (!found) { -+ id = GeoIP_id_by_ipnum(db, ipnum); -+ set_state(AF_INET, ipnum, NULL, -+ subtype, NULL, NULL, NULL, NULL, id); -+ } -+ -+ return (id); -+} -+#endif /* HAVE_GEOIP */ -+ -+#define DB46(addr, geoip, name) \ -+ ((addr->family == AF_INET) ? (geoip->name##_v4) : (geoip->name##_v6)) -+ -+#ifdef HAVE_GEOIP -+/* -+ * Find the best database to answer a generic subtype -+ */ -+static dns_geoip_subtype_t -+fix_subtype(const isc_netaddr_t *reqaddr, const dns_geoip_databases_t *geoip, -+ dns_geoip_subtype_t subtype) -+{ -+ dns_geoip_subtype_t ret = subtype; -+ -+ switch (subtype) { -+ case dns_geoip_countrycode: -+ if (DB46(reqaddr, geoip, city) != NULL) -+ ret = dns_geoip_city_countrycode; -+ else if (reqaddr->family == AF_INET && geoip->region != NULL) -+ ret = dns_geoip_region_countrycode; -+ else if (DB46(reqaddr, geoip, country) != NULL) -+ ret = dns_geoip_country_code; -+ break; -+ case dns_geoip_countrycode3: -+ if (DB46(reqaddr, geoip, city) != NULL) -+ ret = dns_geoip_city_countrycode3; -+ else if (DB46(reqaddr, geoip, country) != NULL) -+ ret = dns_geoip_country_code3; -+ break; -+ case dns_geoip_countryname: -+ if (DB46(reqaddr, geoip, city) != NULL) -+ ret = dns_geoip_city_countryname; -+ else if (DB46(reqaddr, geoip, country) != NULL) -+ ret = dns_geoip_country_name; -+ break; -+ case dns_geoip_region: -+ if (DB46(reqaddr, geoip, city) != NULL) -+ ret = dns_geoip_city_region; -+ else if (reqaddr->family == AF_INET && geoip->region != NULL) -+ ret = dns_geoip_region_code; -+ break; -+ case dns_geoip_regionname: -+ if (DB46(reqaddr, geoip, city) != NULL) -+ ret = dns_geoip_city_regionname; -+ else if (reqaddr->family == AF_INET && geoip->region != NULL) -+ ret = dns_geoip_region_name; -+ break; -+ default: -+ break; -+ } -+ -+ return (ret); -+} -+#endif /* HAVE_GEOIP */ -+ -+isc_boolean_t -+dns_geoip_match(const isc_netaddr_t *reqaddr, -+ const dns_geoip_databases_t *geoip, -+ const dns_geoip_elem_t *elt) -+{ -+#ifndef HAVE_GEOIP -+ UNUSED(reqaddr); -+ UNUSED(geoip); -+ UNUSED(elt); -+ -+ return (ISC_FALSE); -+#else -+ GeoIP *db; -+ GeoIPRecord *record; -+ GeoIPRegion *region; -+ dns_geoip_subtype_t subtype; -+ isc_uint32_t ipnum = 0; -+ int maxlen = 0, id, family; -+ const char *cs; -+ char *s; -+#ifdef HAVE_GEOIP_V6 -+ const geoipv6_t *ipnum6 = NULL; -+#else -+ const void *ipnum6 = NULL; -+#endif -+ -+ INSIST(geoip != NULL); -+ -+ family = reqaddr->family; -+ switch (family) { -+ case AF_INET: -+ ipnum = ntohl(reqaddr->type.in.s_addr); -+ break; -+ case AF_INET6: -+#ifdef HAVE_GEOIP_V6 -+ ipnum6 = &reqaddr->type.in6; -+ break; -+#else -+ return (ISC_FALSE); -+#endif -+ default: -+ return (ISC_FALSE); -+ } -+ -+ subtype = fix_subtype(reqaddr, geoip, elt->subtype); -+ -+ switch (subtype) { -+ case dns_geoip_country_code: -+ maxlen = 2; -+ goto getcountry; -+ -+ case dns_geoip_country_code3: -+ maxlen = 3; -+ goto getcountry; -+ -+ case dns_geoip_country_name: -+ maxlen = 255; -+ getcountry: -+ db = DB46(reqaddr, geoip, country); -+ if (db == NULL) -+ return (ISC_FALSE); -+ -+ INSIST(elt->as_string != NULL); -+ -+ cs = country_lookup(db, subtype, family, ipnum, ipnum6); -+ if (cs != NULL && strncasecmp(elt->as_string, cs, maxlen) == 0) -+ return (ISC_TRUE); -+ break; -+ -+ case dns_geoip_city_countrycode: -+ case dns_geoip_city_countrycode3: -+ case dns_geoip_city_countryname: -+ case dns_geoip_city_region: -+ case dns_geoip_city_regionname: -+ case dns_geoip_city_name: -+ case dns_geoip_city_postalcode: -+ case dns_geoip_city_continentcode: -+ case dns_geoip_city_timezonecode: -+ INSIST(elt->as_string != NULL); -+ -+ db = DB46(reqaddr, geoip, city); -+ if (db == NULL) -+ return (ISC_FALSE); -+ -+ record = city_lookup(db, subtype, family, ipnum, ipnum6); -+ if (record == NULL) -+ break; -+ -+ s = city_string(record, subtype, &maxlen); -+ INSIST(maxlen != 0); -+ if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0) -+ return (ISC_TRUE); -+ break; -+ -+ case dns_geoip_city_metrocode: -+ db = DB46(reqaddr, geoip, city); -+ if (db == NULL) -+ return (ISC_FALSE); -+ -+ record = city_lookup(db, subtype, family, ipnum, ipnum6); -+ if (record == NULL) -+ break; -+ -+ if (elt->as_int == record->metro_code) -+ return (ISC_TRUE); -+ break; -+ -+ case dns_geoip_city_areacode: -+ db = DB46(reqaddr, geoip, city); -+ if (db == NULL) -+ return (ISC_FALSE); -+ -+ record = city_lookup(db, subtype, family, ipnum, ipnum6); -+ if (record == NULL) -+ break; -+ -+ if (elt->as_int == record->area_code) -+ return (ISC_TRUE); -+ break; -+ -+ case dns_geoip_region_countrycode: -+ case dns_geoip_region_code: -+ case dns_geoip_region_name: -+ case dns_geoip_region: -+ if (geoip->region == NULL) -+ return (ISC_FALSE); -+ -+ INSIST(elt->as_string != NULL); -+ -+ /* Region DB is not supported for IPv6 */ -+ if (family == AF_INET6) -+ return (ISC_FALSE); -+ -+ region = region_lookup(geoip->region, subtype, ipnum); -+ if (region == NULL) -+ break; -+ -+ s = region_string(region, subtype, &maxlen); -+ INSIST(maxlen != 0); -+ if (s != NULL && strncasecmp(elt->as_string, s, maxlen) == 0) -+ return (ISC_TRUE); -+ break; -+ -+ case dns_geoip_isp_name: -+ db = geoip->isp; -+ goto getname; -+ -+ case dns_geoip_org_name: -+ db = geoip->org; -+ goto getname; -+ -+ case dns_geoip_as_asnum: -+ db = geoip->as; -+ goto getname; -+ -+ case dns_geoip_domain_name: -+ db = geoip->domain; -+ -+ getname: -+ if (db == NULL) -+ return (ISC_FALSE); -+ -+ INSIST(elt->as_string != NULL); -+ /* ISP, Org, AS, and Domain are not supported for IPv6 */ -+ if (family == AF_INET6) -+ return (ISC_FALSE); -+ -+ s = name_lookup(db, subtype, ipnum); -+ if (s != NULL) { -+ size_t l; -+ if (strcasecmp(elt->as_string, s) == 0) -+ return (ISC_TRUE); -+ if (subtype != dns_geoip_as_asnum) -+ break; -+ /* -+ * Just check if the ASNNNN value matches. -+ */ -+ l = strlen(elt->as_string); -+ if (l > 0U && strchr(elt->as_string, ' ') == NULL && -+ strncasecmp(elt->as_string, s, l) == 0 && -+ s[l] == ' ') -+ return (ISC_TRUE); -+ } -+ break; -+ -+ case dns_geoip_netspeed_id: -+ INSIST(geoip->netspeed != NULL); -+ -+ /* Netspeed DB is not supported for IPv6 */ -+ if (family == AF_INET6) -+ return (ISC_FALSE); -+ -+ id = netspeed_lookup(geoip->netspeed, subtype, ipnum); -+ if (id == elt->as_int) -+ return (ISC_TRUE); -+ break; -+ -+ case dns_geoip_countrycode: -+ case dns_geoip_countrycode3: -+ case dns_geoip_countryname: -+ case dns_geoip_regionname: -+ /* -+ * If these were not remapped by fix_subtype(), -+ * the database was unavailable. Always return false. -+ */ -+ break; -+ -+ default: -+ INSIST(0); -+ } -+ -+ return (ISC_FALSE); -+#endif -+} -+ -+void -+dns_geoip_shutdown(void) { -+#ifdef HAVE_GEOIP -+ GeoIP_cleanup(); -+#ifdef ISC_PLATFORM_USETHREADS -+ if (state_mctx != NULL) -+ isc_mem_detach(&state_mctx); -+#endif -+#else -+ return; -+#endif -+} -diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in -index a37b35e..2fcbd1e 100644 ---- a/lib/dns/include/dns/Makefile.in -+++ b/lib/dns/include/dns/Makefile.in -@@ -23,9 +23,9 @@ top_srcdir = @top_srcdir@ - - HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ - clientinfo.h db.h dbiterator.h dbtable.h diff.h dispatch.h \ -- dlz.h dyndb.h dnssec.h ds.h events.h fixedname.h iptable.h \ -- journal.h keyflags.h keytable.h keyvalues.h lib.h log.h \ -- master.h masterdump.h message.h name.h ncache.h nsec.h \ -+ dlz.h dyndb.h dnssec.h ds.h events.h fixedname.h geoip.h \ -+ iptable.h journal.h keyflags.h keytable.h keyvalues.h lib.h \ -+ log.h master.h masterdump.h message.h name.h ncache.h nsec.h \ - peer.h portlist.h private.h rbt.h rcode.h \ - rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \ - rdataslab.h rdatatype.h request.h resolver.h result.h \ -diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h -index f4fc4a3..2c3bb37 100644 ---- a/lib/dns/include/dns/acl.h -+++ b/lib/dns/include/dns/acl.h -@@ -38,10 +38,17 @@ - #include - #include - -+#ifdef HAVE_GEOIP -+#include -+#endif - #include - #include - #include - -+#ifdef HAVE_GEOIP -+#include -+#endif -+ - /*** - *** Types - ***/ -@@ -52,8 +59,11 @@ typedef enum { - dns_aclelementtype_nestedacl, - dns_aclelementtype_localhost, - dns_aclelementtype_localnets, -+#ifdef HAVE_GEOIP -+ dns_aclelementtype_geoip, -+#endif /* HAVE_GEOIP */ - dns_aclelementtype_any --} dns_aclelemettype_t; -+} dns_aclelementtype_t; - - typedef struct dns_aclipprefix dns_aclipprefix_t; - -@@ -63,9 +73,12 @@ struct dns_aclipprefix { - }; - - struct dns_aclelement { -- dns_aclelemettype_t type; -+ dns_aclelementtype_t type; - isc_boolean_t negative; - dns_name_t keyname; -+#ifdef HAVE_GEOIP -+ dns_geoip_elem_t geoip_elem; -+#endif /* HAVE_GEOIP */ - dns_acl_t *nestedacl; - int node_num; - }; -@@ -88,6 +101,9 @@ struct dns_aclenv { - dns_acl_t *localhost; - dns_acl_t *localnets; - isc_boolean_t match_mapped; -+#ifdef HAVE_GEOIP -+ dns_geoip_databases_t *geoip; -+#endif - }; - - #define DNS_ACL_MAGIC ISC_MAGIC('D','a','c','l') -@@ -214,6 +230,10 @@ dns_acl_match(const isc_netaddr_t *reqaddr, - * and 'matchelt' is non-NULL, *matchelt will be pointed to the matching - * element. - * -+ * 'env' points to the current ACL environment, including the -+ * current values of localhost and localnets and (if applicable) -+ * the GeoIP context. -+ * - * Returns: - *\li #ISC_R_SUCCESS Always succeeds. - */ -diff --git a/lib/dns/include/dns/geoip.h b/lib/dns/include/dns/geoip.h -new file mode 100644 -index 0000000..bad9485 ---- /dev/null -+++ b/lib/dns/include/dns/geoip.h -@@ -0,0 +1,119 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef DNS_GEOIP_H -+#define DNS_GEOIP_H 1 -+ -+/***** -+ ***** Module Info -+ *****/ -+ -+/*! \file dns/acl.h -+ * \brief -+ * Address match list handling. -+ */ -+ -+/*** -+ *** Imports -+ ***/ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#ifdef HAVE_GEOIP -+#include -+#else -+typedef void GeoIP; -+#endif -+ -+/*** -+ *** Types -+ ***/ -+ -+typedef enum { -+ dns_geoip_countrycode, -+ dns_geoip_countrycode3, -+ dns_geoip_countryname, -+ dns_geoip_region, -+ dns_geoip_regionname, -+ dns_geoip_country_code, -+ dns_geoip_country_code3, -+ dns_geoip_country_name, -+ dns_geoip_region_countrycode, -+ dns_geoip_region_code, -+ dns_geoip_region_name, -+ dns_geoip_city_countrycode, -+ dns_geoip_city_countrycode3, -+ dns_geoip_city_countryname, -+ dns_geoip_city_region, -+ dns_geoip_city_regionname, -+ dns_geoip_city_name, -+ dns_geoip_city_postalcode, -+ dns_geoip_city_metrocode, -+ dns_geoip_city_areacode, -+ dns_geoip_city_continentcode, -+ dns_geoip_city_timezonecode, -+ dns_geoip_isp_name, -+ dns_geoip_org_name, -+ dns_geoip_as_asnum, -+ dns_geoip_domain_name, -+ dns_geoip_netspeed_id -+} dns_geoip_subtype_t; -+ -+typedef struct dns_geoip_elem { -+ dns_geoip_subtype_t subtype; -+ GeoIP *db; -+ union { -+ char as_string[256]; -+ int as_int; -+ }; -+} dns_geoip_elem_t; -+ -+typedef struct dns_geoip_databases { -+ GeoIP *country_v4; /* DB 1 */ -+ GeoIP *city_v4; /* DB 2 or 6 */ -+ GeoIP *region; /* DB 3 or 7 */ -+ GeoIP *isp; /* DB 4 */ -+ GeoIP *org; /* DB 5 */ -+ GeoIP *as; /* DB 9 */ -+ GeoIP *netspeed; /* DB 10 */ -+ GeoIP *domain; /* DB 11 */ -+ GeoIP *country_v6; /* DB 12 */ -+ GeoIP *city_v6; /* DB 30 or 31 */ -+} dns_geoip_databases_t; -+ -+/*** -+ *** Functions -+ ***/ -+ -+ISC_LANG_BEGINDECLS -+ -+isc_boolean_t -+dns_geoip_match(const isc_netaddr_t *reqaddr, -+ const dns_geoip_databases_t *geoip, -+ const dns_geoip_elem_t *elt); -+ -+void -+dns_geoip_shutdown(void); -+ -+ISC_LANG_ENDDECLS -+#endif /* DNS_GEOIP_H */ -diff --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in -index 3b19784..8d1b83e 100644 ---- a/lib/dns/tests/Makefile.in -+++ b/lib/dns/tests/Makefile.in -@@ -40,13 +40,13 @@ LIBS = @LIBS@ @ATFLIBS@ - OBJS = dnstest.@O@ - SRCS = dnstest.c gost_test.c master_test.c dbiterator_test.c time_test.c \ - private_test.c update_test.c zonemgr_test.c zt_test.c \ -- dbdiff_test.c dispatch_test.c nsec3_test.c \ -+ dbdiff_test.c geoip_test.c dispatch_test.c nsec3_test.c \ - rdataset_test.c rdata_test.c - - SUBDIRS = - TARGETS = gost_test@EXEEXT@ master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \ - private_test@EXEEXT@ update_test@EXEEXT@ zonemgr_test@EXEEXT@ \ -- zt_test@EXEEXT@ dbversion_test@EXEEXT@ dbdiff_test@EXEEXT@ \ -+ zt_test@EXEEXT@ dbversion_test@EXEEXT@ dbdiff_test@EXEEXT@ geoip_test@EXEEXT@ \ - dispatch_test@EXEEXT@ nsec3_test@EXEEXT@ \ - rdataset_test@EXEEXT@ rdata_test@EXEEXT@ - -@@ -129,6 +129,11 @@ gost_test@EXEEXT@: gost_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - gost_test.@O@ dnstest.@O@ ${DNSLIBS} \ - ${ISCLIBS} ${LIBS} - -+geoip_test@EXEEXT@: geoip_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ -+ geoip_test.@O@ dnstest.@O@ ${DNSLIBS} \ -+ ${ISCLIBS} ${LIBS} -+ - unit:: - sh ${top_srcdir}/unit/unittest.sh - -diff --git a/lib/dns/tests/geoip_test.c b/lib/dns/tests/geoip_test.c -new file mode 100644 -index 0000000..ad983b0 ---- /dev/null -+++ b/lib/dns/tests/geoip_test.c -@@ -0,0 +1,694 @@ -+/* -+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* $Id$ */ -+ -+/*! \file */ -+ -+#include -+ -+#include -+ -+#include -+ -+#include -+ -+#include -+ -+#include "dnstest.h" -+ -+#ifdef HAVE_GEOIP -+#include -+ -+/* We use GeoIP databases from the 'geoip' system test */ -+#define TEST_GEOIP_DATA "../../../bin/tests/system/geoip/data" -+ -+/* -+ * Helper functions -+ * (Mostly copied from bin/named/geoip.c) -+ */ -+static dns_geoip_databases_t geoip = { -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -+}; -+ -+static void -+init_geoip_db(GeoIP **dbp, GeoIPDBTypes edition, GeoIPDBTypes fallback, -+ GeoIPOptions method, const char *name) -+{ -+ char *info; -+ GeoIP *db; -+ -+ REQUIRE(dbp != NULL); -+ -+ db = *dbp; -+ -+ if (db != NULL) { -+ GeoIP_delete(db); -+ db = *dbp = NULL; -+ } -+ -+ if (! GeoIP_db_avail(edition)) { -+ fprintf(stderr, "GeoIP %s (type %d) DB not available\n", -+ name, edition); -+ goto fail; -+ } -+ -+ fprintf(stderr, "initializing GeoIP %s (type %d) DB\n", -+ name, edition); -+ -+ db = GeoIP_open_type(edition, method); -+ if (db == NULL) { -+ fprintf(stderr, -+ "failed to initialize GeoIP %s (type %d) DB%s\n", -+ name, edition, fallback == 0 -+ ? "; geoip matches using this database will fail" -+ : ""); -+ goto fail; -+ } -+ -+ info = GeoIP_database_info(db); -+ if (info != NULL) -+ fprintf(stderr, "%s\n", info); -+ -+ *dbp = db; -+ return; -+ -+ fail: -+ if (fallback != 0) -+ init_geoip_db(dbp, fallback, 0, method, name); -+} -+ -+static void -+load_geoip(const char *dir) { -+ GeoIPOptions method; -+ -+#ifdef _WIN32 -+ method = GEOIP_STANDARD; -+#else -+ method = GEOIP_MMAP_CACHE; -+#endif -+ -+ if (dir != NULL) { -+ char *p; -+ DE_CONST(dir, p); -+ GeoIP_setup_custom_directory(p); -+ } -+ -+ init_geoip_db(&geoip.country_v4, GEOIP_COUNTRY_EDITION, 0, -+ method, "Country (IPv4)"); -+#ifdef HAVE_GEOIP_V6 -+ init_geoip_db(&geoip.country_v6, GEOIP_COUNTRY_EDITION_V6, 0, -+ method, "Country (IPv6)"); -+#endif -+ -+ init_geoip_db(&geoip.city_v4, GEOIP_CITY_EDITION_REV1, -+ GEOIP_CITY_EDITION_REV0, method, "City (IPv4)"); -+#if defined(HAVE_GEOIP_V6) && defined(HAVE_GEOIP_CITY_V6) -+ init_geoip_db(&geoip.city_v6, GEOIP_CITY_EDITION_REV1_V6, -+ GEOIP_CITY_EDITION_REV0_V6, method, "City (IPv6)"); -+#endif -+ -+ init_geoip_db(&geoip.region, GEOIP_REGION_EDITION_REV1, -+ GEOIP_REGION_EDITION_REV0, method, "Region"); -+ init_geoip_db(&geoip.isp, GEOIP_ISP_EDITION, 0, -+ method, "ISP"); -+ init_geoip_db(&geoip.org, GEOIP_ORG_EDITION, 0, -+ method, "Org"); -+ init_geoip_db(&geoip.as, GEOIP_ASNUM_EDITION, 0, -+ method, "AS"); -+ init_geoip_db(&geoip.domain, GEOIP_DOMAIN_EDITION, 0, -+ method, "Domain"); -+ init_geoip_db(&geoip.netspeed, GEOIP_NETSPEED_EDITION, 0, -+ method, "NetSpeed"); -+} -+ -+static isc_boolean_t -+do_lookup_string(const char *addr, dns_geoip_subtype_t subtype, -+ const char *string) -+{ -+ dns_geoip_elem_t elt; -+ struct in_addr in4; -+ isc_netaddr_t na; -+ -+ inet_pton(AF_INET, addr, &in4); -+ isc_netaddr_fromin(&na, &in4); -+ -+ elt.subtype = subtype; -+ strcpy(elt.as_string, string); -+ -+ return (dns_geoip_match(&na, &geoip, &elt)); -+} -+ -+static isc_boolean_t -+do_lookup_string_v6(const char *addr, dns_geoip_subtype_t subtype, -+ const char *string) -+{ -+ dns_geoip_elem_t elt; -+ struct in6_addr in6; -+ isc_netaddr_t na; -+ -+ inet_pton(AF_INET6, addr, &in6); -+ isc_netaddr_fromin6(&na, &in6); -+ -+ elt.subtype = subtype; -+ strcpy(elt.as_string, string); -+ -+ return (dns_geoip_match(&na, &geoip, &elt)); -+} -+ -+static isc_boolean_t -+do_lookup_int(const char *addr, dns_geoip_subtype_t subtype, int id) { -+ dns_geoip_elem_t elt; -+ struct in_addr in4; -+ isc_netaddr_t na; -+ -+ inet_pton(AF_INET, addr, &in4); -+ isc_netaddr_fromin(&na, &in4); -+ -+ elt.subtype = subtype; -+ elt.as_int = id; -+ -+ return (dns_geoip_match(&na, &geoip, &elt)); -+} -+ -+/* -+ * Individual unit tests -+ */ -+ -+/* GeoIP country matching */ -+ATF_TC(country); -+ATF_TC_HEAD(country, tc) { -+ atf_tc_set_md_var(tc, "descr", "test country database matching"); -+} -+ATF_TC_BODY(country, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.country_v4 == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string("10.53.0.1", dns_geoip_country_code, "AU"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_country_code3, "AUS"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_country_name, "Australia"); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+/* GeoIP country (ipv6) matching */ -+ATF_TC(country_v6); -+ATF_TC_HEAD(country_v6, tc) { -+ atf_tc_set_md_var(tc, "descr", "test country (ipv6) database matching"); -+} -+ATF_TC_BODY(country_v6, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.country_v6 == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_country_code, "AU"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_country_code3, "AUS"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_country_name, "Australia"); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+/* GeoIP city (ipv4) matching */ -+ATF_TC(city); -+ATF_TC_HEAD(city, tc) { -+ atf_tc_set_md_var(tc, "descr", "test city database matching"); -+} -+ATF_TC_BODY(city, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.city_v4 == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_city_continentcode, "NA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_city_countrycode, "US"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_city_countrycode3, "USA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_city_countryname, "United States"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_city_region, "CA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_city_regionname, "California"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_city_name, "Redwood City"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_city_postalcode, "94063"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_int("10.53.0.1", dns_geoip_city_areacode, 650); -+ ATF_CHECK(match); -+ -+ match = do_lookup_int("10.53.0.1", dns_geoip_city_metrocode, 807); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+/* GeoIP city (ipv6) matching */ -+ATF_TC(city_v6); -+ATF_TC_HEAD(city_v6, tc) { -+ atf_tc_set_md_var(tc, "descr", "test city (ipv6) database matching"); -+} -+ATF_TC_BODY(city_v6, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.city_v6 == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_city_continentcode, "NA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_city_countrycode, "US"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_city_countrycode3, "USA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_city_countryname, -+ "United States"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_city_region, "CA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_city_regionname, "California"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_city_name, "Redwood City"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string_v6("fd92:7065:b8e:ffff::1", -+ dns_geoip_city_postalcode, "94063"); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+ -+/* GeoIP region matching */ -+ATF_TC(region); -+ATF_TC_HEAD(region, tc) { -+ atf_tc_set_md_var(tc, "descr", "test region database matching"); -+} -+ATF_TC_BODY(region, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.region == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_region_code, "CA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_region_name, "California"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.1", -+ dns_geoip_region_countrycode, "US"); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+/* -+ * GeoIP best-database matching -+ * (With no specified databse and a city database available, answers -+ * should come from city database. With city database unavailable, region -+ * database. Region database unavailable, country database.) -+ */ -+ATF_TC(best); -+ATF_TC_HEAD(best, tc) { -+ atf_tc_set_md_var(tc, "descr", "test best database matching"); -+} -+ATF_TC_BODY(best, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.region == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countrycode, "US"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countrycode3, "USA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countryname, "United States"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_regionname, "Virginia"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_region, "VA"); -+ ATF_CHECK(match); -+ -+ GeoIP_delete(geoip.city_v4); -+ geoip.city_v4 = NULL; -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countrycode, "AU"); -+ ATF_CHECK(match); -+ -+ /* -+ * Note, region doesn't support code3 or countryname, so -+ * the next two would be answered from the country database instead -+ */ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countrycode3, "CAN"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countryname, "Canada"); -+ ATF_CHECK(match); -+ -+ GeoIP_delete(geoip.region); -+ geoip.region = NULL; -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countrycode, "CA"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countrycode3, "CAN"); -+ ATF_CHECK(match); -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_countryname, "Canada"); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+ -+/* GeoIP asnum matching */ -+ATF_TC(asnum); -+ATF_TC_HEAD(asnum, tc) { -+ atf_tc_set_md_var(tc, "descr", "test asnum database matching"); -+} -+ATF_TC_BODY(asnum, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.as == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ -+ match = do_lookup_string("10.53.0.3", dns_geoip_as_asnum, -+ "AS100003 Three Network Labs"); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+/* GeoIP isp matching */ -+ATF_TC(isp); -+ATF_TC_HEAD(isp, tc) { -+ atf_tc_set_md_var(tc, "descr", "test isp database matching"); -+} -+ATF_TC_BODY(isp, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.isp == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string("10.53.0.1", dns_geoip_isp_name, -+ "One Systems, Inc."); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+/* GeoIP org matching */ -+ATF_TC(org); -+ATF_TC_HEAD(org, tc) { -+ atf_tc_set_md_var(tc, "descr", "test org database matching"); -+} -+ATF_TC_BODY(org, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.org == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string("10.53.0.2", dns_geoip_org_name, -+ "Two Technology Ltd."); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+/* GeoIP domain matching */ -+ATF_TC(domain); -+ATF_TC_HEAD(domain, tc) { -+ atf_tc_set_md_var(tc, "descr", "test domain database matching"); -+} -+ATF_TC_BODY(domain, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.domain == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_string("10.53.0.4", -+ dns_geoip_domain_name, "four.com"); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+ -+/* GeoIP netspeed matching */ -+ATF_TC(netspeed); -+ATF_TC_HEAD(netspeed, tc) { -+ atf_tc_set_md_var(tc, "descr", "test netspeed database matching"); -+} -+ATF_TC_BODY(netspeed, tc) { -+ isc_result_t result; -+ isc_boolean_t match; -+ -+ UNUSED(tc); -+ -+ result = dns_test_begin(NULL, ISC_TRUE); -+ ATF_REQUIRE(result == ISC_R_SUCCESS); -+ -+ /* Use databases from the geoip system test */ -+ load_geoip(TEST_GEOIP_DATA); -+ -+ if (geoip.netspeed == NULL) { -+ dns_test_end(); -+ atf_tc_skip("Database not available"); -+ } -+ -+ match = do_lookup_int("10.53.0.1", dns_geoip_netspeed_id, 0); -+ ATF_CHECK(match); -+ -+ match = do_lookup_int("10.53.0.2", dns_geoip_netspeed_id, 1); -+ ATF_CHECK(match); -+ -+ match = do_lookup_int("10.53.0.3", dns_geoip_netspeed_id, 2); -+ ATF_CHECK(match); -+ -+ match = do_lookup_int("10.53.0.4", dns_geoip_netspeed_id, 3); -+ ATF_CHECK(match); -+ -+ dns_test_end(); -+} -+#else -+ATF_TC(untested); -+ATF_TC_HEAD(untested, tc) { -+ atf_tc_set_md_var(tc, "descr", "skipping geoip test"); -+} -+ATF_TC_BODY(untested, tc) { -+ UNUSED(tc); -+ atf_tc_skip("GeoIP not available"); -+} -+#endif -+ -+/* -+ * Main -+ */ -+ATF_TP_ADD_TCS(tp) { -+#ifdef HAVE_GEOIP -+ ATF_TP_ADD_TC(tp, country); -+ ATF_TP_ADD_TC(tp, country_v6); -+ ATF_TP_ADD_TC(tp, city); -+ ATF_TP_ADD_TC(tp, city_v6); -+ ATF_TP_ADD_TC(tp, region); -+ ATF_TP_ADD_TC(tp, best); -+ ATF_TP_ADD_TC(tp, asnum); -+ ATF_TP_ADD_TC(tp, isp); -+ ATF_TP_ADD_TC(tp, org); -+ ATF_TP_ADD_TC(tp, domain); -+ ATF_TP_ADD_TC(tp, netspeed); -+#else -+ ATF_TP_ADD_TC(tp, untested); -+#endif -+ -+ return (atf_no_error()); -+} -+ -diff --git a/lib/export/dns/Makefile.in b/lib/export/dns/Makefile.in -index e10bf59..887acb9 100644 ---- a/lib/export/dns/Makefile.in -+++ b/lib/export/dns/Makefile.in -@@ -67,8 +67,9 @@ DNSOBJS = acl.@O@ adb.@O@ byaddr.@O@ \ - tcpmsg.@O@ time.@O@ tsec.@O@ tsig.@O@ ttl.@O@ \ - validator.@O@ version.@O@ view.@O@ - PORTDNSOBJS = ecdb.@O@ -+GEOIPLINKOBJS = geoip.@O@ - --OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} ${PORTDNSOBJS} -+OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS} ${PORTDNSOBJS} @GEOIPLINKOBJS@ - - # Alphabetically - -@@ -96,8 +97,9 @@ DNSSRCS = acl.c adb.c byaddr.c \ - tcpmsg.c time.c tsec.c tsig.c ttl.c \ - validator.c version.c view.c - PORTDNSSRCS = ecdb.c -+GEOIPLINKSRCS = geoip.c - --SRCS = ${DSTSRCS} ${DNSSRCS} ${PORTDNSSRCS} -+SRCS = ${DSTSRCS} ${DNSSRCS} ${PORTDNSSRCS} @GEOIPLINKSRCS@ - - SUBDIRS = include - TARGETS = include/dns/enumtype.h include/dns/enumclass.h \ -diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c -index af56599..c415a98 100644 ---- a/lib/isccfg/aclconf.c -+++ b/lib/isccfg/aclconf.c -@@ -31,6 +31,11 @@ - #include - #include - -+#ifdef HAVE_GEOIP -+#include -+#include -+#endif /* HAVE_GEOIP */ -+ - #define LOOP_MAGIC ISC_MAGIC('L','O','O','P') - - isc_result_t -@@ -53,6 +58,10 @@ cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **ret) { - isc_mem_attach(mctx, &actx->mctx); - ISC_LIST_INIT(actx->named_acl_cache); - -+#ifdef HAVE_GEOIP -+ actx->geoip = NULL; -+#endif -+ - *ret = actx; - return (ISC_R_SUCCESS); - -@@ -230,11 +239,15 @@ count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx, - elt = cfg_list_next(elt)) { - const cfg_obj_t *ce = cfg_listelt_value(elt); - -- /* negated element; just get the value. */ -+ /* might be a negated element, in which case get the value. */ - if (cfg_obj_istuple(ce)) { -- ce = cfg_tuple_get(ce, "value"); -- if (has_negative != NULL) -- *has_negative = ISC_TRUE; -+ const cfg_obj_t *negated = -+ cfg_tuple_get(ce, "negated"); -+ if (! cfg_obj_isvoid(negated)) { -+ ce = negated; -+ if (has_negative != NULL) -+ *has_negative = ISC_TRUE; -+ } - } - - if (cfg_obj_istype(ce, &cfg_type_keyref)) { -@@ -244,6 +257,12 @@ count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx, - n += count_acl_elements(ce, cctx, &negative); - if (negative) - n++; -+#ifdef HAVE_GEOIP -+ } else if (cfg_obj_istuple(ce) && -+ cfg_obj_isvoid(cfg_tuple_get(ce, "negated"))) -+ { -+ n++; -+#endif /* HAVE_GEOIP */ - } else if (cfg_obj_isstring(ce)) { - const char *name = cfg_obj_asstring(ce); - if (strcasecmp(name, "localhost") == 0 || -@@ -262,6 +281,313 @@ count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx, - return n; - } - -+#ifdef HAVE_GEOIP -+static dns_geoip_subtype_t -+get_subtype(const cfg_obj_t *obj, isc_log_t *lctx, -+ dns_geoip_subtype_t subtype, const char *dbname) -+{ -+ if (dbname == NULL) -+ return (subtype); -+ -+ switch (subtype) { -+ case dns_geoip_countrycode: -+ if (strcasecmp(dbname, "city") == 0) -+ return (dns_geoip_city_countrycode); -+ else if (strcasecmp(dbname, "region") == 0) -+ return (dns_geoip_region_countrycode); -+ else if (strcasecmp(dbname, "country") == 0) -+ return (dns_geoip_country_code); -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "invalid GeoIP DB specified for " -+ "country search: ignored"); -+ return (subtype); -+ case dns_geoip_countrycode3: -+ if (strcasecmp(dbname, "city") == 0) -+ return (dns_geoip_city_countrycode3); -+ else if (strcasecmp(dbname, "country") == 0) -+ return (dns_geoip_country_code3); -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "invalid GeoIP DB specified for " -+ "country search: ignored"); -+ return (subtype); -+ case dns_geoip_countryname: -+ if (strcasecmp(dbname, "city") == 0) -+ return (dns_geoip_city_countryname); -+ else if (strcasecmp(dbname, "country") == 0) -+ return (dns_geoip_country_name); -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "invalid GeoIP DB specified for " -+ "country search: ignored"); -+ return (subtype); -+ case dns_geoip_region: -+ if (strcasecmp(dbname, "city") == 0) -+ return (dns_geoip_city_region); -+ else if (strcasecmp(dbname, "region") == 0) -+ return (dns_geoip_region_code); -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "invalid GeoIP DB specified for " -+ "region search: ignored"); -+ return (subtype); -+ case dns_geoip_regionname: -+ if (strcasecmp(dbname, "city") == 0) -+ return (dns_geoip_city_region); -+ else if (strcasecmp(dbname, "region") == 0) -+ return (dns_geoip_region_name); -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "invalid GeoIP DB specified for " -+ "region search: ignored"); -+ return (subtype); -+ -+ /* -+ * Log a warning if the wrong database was specified -+ * on an unambiguous query -+ */ -+ case dns_geoip_city_name: -+ case dns_geoip_city_postalcode: -+ case dns_geoip_city_metrocode: -+ case dns_geoip_city_areacode: -+ case dns_geoip_city_continentcode: -+ case dns_geoip_city_timezonecode: -+ if (strcasecmp(dbname, "city") != 0) -+ cfg_obj_log(obj, lctx, ISC_LOG_WARNING, -+ "invalid GeoIP DB specified for " -+ "a 'city'-only search type: ignoring"); -+ return (subtype); -+ case dns_geoip_isp_name: -+ if (strcasecmp(dbname, "isp") != 0) -+ cfg_obj_log(obj, lctx, ISC_LOG_WARNING, -+ "invalid GeoIP DB specified for " -+ "an 'isp' search: ignoring"); -+ return (subtype); -+ case dns_geoip_org_name: -+ if (strcasecmp(dbname, "org") != 0) -+ cfg_obj_log(obj, lctx, ISC_LOG_WARNING, -+ "invalid GeoIP DB specified for " -+ "an 'org' search: ignoring"); -+ return (subtype); -+ case dns_geoip_as_asnum: -+ if (strcasecmp(dbname, "asnum") != 0) -+ cfg_obj_log(obj, lctx, ISC_LOG_WARNING, -+ "invalid GeoIP DB specified for " -+ "an 'asnum' search: ignoring"); -+ return (subtype); -+ case dns_geoip_domain_name: -+ if (strcasecmp(dbname, "domain") != 0) -+ cfg_obj_log(obj, lctx, ISC_LOG_WARNING, -+ "invalid GeoIP DB specified for " -+ "a 'domain' search: ignoring"); -+ return (subtype); -+ case dns_geoip_netspeed_id: -+ if (strcasecmp(dbname, "netspeed") != 0) -+ cfg_obj_log(obj, lctx, ISC_LOG_WARNING, -+ "invalid GeoIP DB specified for " -+ "a 'netspeed' search: ignoring"); -+ return (subtype); -+ default: -+ INSIST(0); -+ } -+} -+ -+static isc_boolean_t -+geoip_can_answer(dns_aclelement_t *elt, cfg_aclconfctx_t *ctx) { -+ if (ctx->geoip == NULL) -+ return (ISC_TRUE); -+ -+ switch (elt->geoip_elem.subtype) { -+ case dns_geoip_countrycode: -+ case dns_geoip_countrycode3: -+ case dns_geoip_countryname: -+ if (ctx->geoip->city_v4 != NULL || -+ ctx->geoip->city_v6 != NULL || -+ ctx->geoip->country_v4 != NULL || -+ ctx->geoip->country_v6 != NULL || -+ ctx->geoip->region != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_region: -+ case dns_geoip_regionname: -+ if (ctx->geoip->city_v4 != NULL || -+ ctx->geoip->city_v6 != NULL || -+ ctx->geoip->region != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_country_code: -+ case dns_geoip_country_code3: -+ case dns_geoip_country_name: -+ if (ctx->geoip->country_v4 != NULL || -+ ctx->geoip->country_v6 != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_region_countrycode: -+ case dns_geoip_region_code: -+ case dns_geoip_region_name: -+ if (ctx->geoip->region != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_city_countrycode: -+ case dns_geoip_city_countrycode3: -+ case dns_geoip_city_countryname: -+ case dns_geoip_city_region: -+ case dns_geoip_city_regionname: -+ case dns_geoip_city_name: -+ case dns_geoip_city_postalcode: -+ case dns_geoip_city_metrocode: -+ case dns_geoip_city_areacode: -+ case dns_geoip_city_continentcode: -+ case dns_geoip_city_timezonecode: -+ if (ctx->geoip->city_v4 != NULL || -+ ctx->geoip->city_v6 != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_isp_name: -+ if (ctx->geoip->isp != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_org_name: -+ if (ctx->geoip->org != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_as_asnum: -+ if (ctx->geoip->as != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_domain_name: -+ if (ctx->geoip->domain != NULL) -+ return (ISC_TRUE); -+ case dns_geoip_netspeed_id: -+ if (ctx->geoip->netspeed != NULL) -+ return (ISC_TRUE); -+ } -+ -+ return (ISC_FALSE); -+} -+ -+static isc_result_t -+parse_geoip_element(const cfg_obj_t *obj, isc_log_t *lctx, -+ cfg_aclconfctx_t *ctx, dns_aclelement_t *dep) -+{ -+ const cfg_obj_t *ge; -+ const char *dbname = NULL; -+ const char *stype, *search; -+ dns_geoip_subtype_t subtype; -+ dns_aclelement_t de; -+ size_t len; -+ -+ REQUIRE(dep != NULL); -+ -+ de = *dep; -+ -+ ge = cfg_tuple_get(obj, "db"); -+ if (!cfg_obj_isvoid(ge)) -+ dbname = cfg_obj_asstring(ge); -+ -+ stype = cfg_obj_asstring(cfg_tuple_get(obj, "subtype")); -+ search = cfg_obj_asstring(cfg_tuple_get(obj, "search")); -+ len = strlen(search); -+ -+ if (len == 0) { -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "zero-length geoip search field"); -+ return (ISC_R_FAILURE); -+ } -+ -+ if (strcasecmp(stype, "country") == 0 && len == 2) { -+ /* Two-letter country code */ -+ subtype = dns_geoip_countrycode; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "country") == 0 && len == 3) { -+ /* Three-letter country code */ -+ subtype = dns_geoip_countrycode3; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "country") == 0) { -+ /* Country name */ -+ subtype = dns_geoip_countryname; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "region") == 0 && len == 2) { -+ /* Two-letter region code */ -+ subtype = dns_geoip_region; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "region") == 0) { -+ /* Region name */ -+ subtype = dns_geoip_regionname; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "city") == 0) { -+ /* City name */ -+ subtype = dns_geoip_city_name; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "postal") == 0 || -+ strcasecmp(stype, "postalcode") == 0) -+ { -+ if (len < 7) { -+ subtype = dns_geoip_city_postalcode; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else { -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "geoiop postal code (%s) too long", -+ search); -+ return (ISC_R_FAILURE); -+ } -+ } else if (strcasecmp(stype, "metro") == 0 || -+ strcasecmp(stype, "metrocode") == 0) -+ { -+ subtype = dns_geoip_city_metrocode; -+ de.geoip_elem.as_int = atoi(search); -+ } else if (strcasecmp(stype, "area") == 0 || -+ strcasecmp(stype, "areacode") == 0) -+ { -+ subtype = dns_geoip_city_areacode; -+ de.geoip_elem.as_int = atoi(search); -+ } else if (strcasecmp(stype, "tz") == 0 || -+ strcasecmp(stype, "timezone") == 0) -+ { -+ subtype = dns_geoip_city_timezonecode; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "continent") == 0 && len == 2) { -+ /* Two-letter continent code */ -+ subtype = dns_geoip_city_continentcode; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "continent") == 0) { -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "geoiop continent code (%s) too long", search); -+ return (ISC_R_FAILURE); -+ } else if (strcasecmp(stype, "isp") == 0) { -+ subtype = dns_geoip_isp_name; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "asnum") == 0) { -+ subtype = dns_geoip_as_asnum; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "org") == 0) { -+ subtype = dns_geoip_org_name; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "domain") == 0) { -+ subtype = dns_geoip_domain_name; -+ strlcpy(de.geoip_elem.as_string, search, -+ sizeof(de.geoip_elem.as_string)); -+ } else if (strcasecmp(stype, "netspeed") == 0) { -+ subtype = dns_geoip_netspeed_id; -+ de.geoip_elem.as_int = atoi(search); -+ } else -+ INSIST(0); -+ -+ de.geoip_elem.subtype = get_subtype(obj, lctx, subtype, dbname); -+ -+ if (! geoip_can_answer(&de, ctx)) { -+ cfg_obj_log(obj, lctx, ISC_LOG_ERROR, -+ "no GeoIP database installed which can answer " -+ "queries of type '%s'", stype); -+ return (ISC_R_FAILURE); -+ } -+ -+ *dep = de; -+ -+ return (ISC_R_SUCCESS); -+} -+#endif -+ - isc_result_t - cfg_acl_fromconfig(const cfg_obj_t *caml, - const cfg_obj_t *cctx, -@@ -317,15 +643,18 @@ cfg_acl_fromconfig(const cfg_obj_t *caml, - elt != NULL; - elt = cfg_list_next(elt)) { - const cfg_obj_t *ce = cfg_listelt_value(elt); -- isc_boolean_t neg; -+ isc_boolean_t neg = ISC_FALSE; - - if (cfg_obj_istuple(ce)) { -- /* This must be a negated element. */ -- ce = cfg_tuple_get(ce, "value"); -- neg = ISC_TRUE; -- dacl->has_negatives = ISC_TRUE; -- } else -- neg = ISC_FALSE; -+ /* Might be a negated element */ -+ const cfg_obj_t *negated = -+ cfg_tuple_get(ce, "negated"); -+ if (! cfg_obj_isvoid(negated)) { -+ neg = ISC_TRUE; -+ dacl->has_negatives = ISC_TRUE; -+ ce = negated; -+ } -+ } - - /* - * If nest_level is nonzero, then every element is -@@ -405,6 +734,16 @@ nested_acl: - &de->keyname); - if (result != ISC_R_SUCCESS) - goto cleanup; -+#ifdef HAVE_GEOIP -+ } else if (cfg_obj_istuple(ce) && -+ cfg_obj_isvoid(cfg_tuple_get(ce, "negated"))) -+ { -+ result = parse_geoip_element(ce, lctx, ctx, de); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup; -+ de->type = dns_aclelementtype_geoip; -+ de->negative = neg; -+#endif /* HAVE_GEOIP */ - } else if (cfg_obj_isstring(ce)) { - /* ACL name. */ - const char *name = cfg_obj_asstring(ce); -diff --git a/lib/isccfg/include/isccfg/aclconf.h b/lib/isccfg/include/isccfg/aclconf.h -index 38ab9f6..3fb66f9 100644 ---- a/lib/isccfg/include/isccfg/aclconf.h -+++ b/lib/isccfg/include/isccfg/aclconf.h -@@ -24,11 +24,17 @@ - - #include - -+#ifdef HAVE_GEOIP -+#include -+#endif - #include - - typedef struct cfg_aclconfctx { - ISC_LIST(dns_acl_t) named_acl_cache; - isc_mem_t *mctx; -+#ifdef HAVE_GEOIP -+ dns_geoip_databases_t *geoip; -+#endif - isc_refcount_t references; - } cfg_aclconfctx_t; - -diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c -index 62fcc96..1867506 100644 ---- a/lib/isccfg/namedconf.c -+++ b/lib/isccfg/namedconf.c -@@ -82,6 +82,17 @@ doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type); - static void - doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type); - -+#ifdef HAVE_GEOIP -+static isc_result_t -+parse_geoip(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); -+ -+static void -+print_geoip(cfg_printer_t *pctx, const cfg_obj_t *obj); -+ -+static void -+doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type); -+#endif /* HAVE_GEOIP */ -+ - static cfg_type_t cfg_type_acl; - static cfg_type_t cfg_type_addrmatchelt; - static cfg_type_t cfg_type_bracketed_aml; -@@ -935,6 +946,9 @@ options_clauses[] = { - { "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, - { "files", &cfg_type_size, 0 }, - { "flush-zones-on-shutdown", &cfg_type_boolean, 0 }, -+#ifdef HAVE_GEOIP -+ { "geoip-directory", &cfg_type_qstringornone, 0 }, -+#endif /* HAVE_GEOIP */ - { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE }, - { "heartbeat-interval", &cfg_type_uint32, 0 }, - { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP }, -@@ -2108,6 +2122,102 @@ static cfg_type_t cfg_type_optional_keyref = { - doc_optional_keyvalue, &cfg_rep_string, &key_kw - }; - -+#ifdef HAVE_GEOIP -+/* -+ * "geoip" ACL element: -+ * geoip [ db ] search-type -+ */ -+static const char *geoiptype_enums[] = { -+ "country", "country3", "countryname", "region", "regionname", -+ "city", "postalcode", "postal", "metrocode", "metro", -+ "areacode", "area", "timezone", "tz", "continent", "isp", -+ "domain", "asnum", "org", "netspeed", NULL -+}; -+static cfg_type_t cfg_type_geoiptype = { -+ "geoiptype", cfg_parse_enum, cfg_print_ustring, -+ cfg_doc_enum, &cfg_rep_string, &geoiptype_enums -+}; -+ -+static const char *geoipdb_enums[] = { -+ "country", "region", "city", -+ "isp", "domain", "asnum", "org", "netspeed", NULL -+}; -+static cfg_type_t cfg_type_geoipdb = { -+ "geoipdb", cfg_parse_enum, cfg_print_ustring, -+ cfg_doc_enum, &cfg_rep_string, &geoipdb_enums -+}; -+ -+static cfg_tuplefielddef_t geoip_fields[] = { -+ { "negated", &cfg_type_void, 0}, -+ { "db", &cfg_type_geoipdb, 0}, -+ { "subtype", &cfg_type_geoiptype, 0 }, -+ { "search", &cfg_type_astring, 0 }, -+ { NULL, NULL, 0 } -+}; -+ -+static cfg_type_t cfg_type_geoip = { -+ "geoip", parse_geoip, print_geoip, doc_geoip, -+ &cfg_rep_tuple, geoip_fields -+}; -+ -+static isc_result_t -+parse_geoip(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { -+ isc_result_t result; -+ cfg_obj_t *obj = NULL; -+ const cfg_tuplefielddef_t *fields = type->of; -+ -+ CHECK(cfg_create_tuple(pctx, type, &obj)); -+ CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[0])); -+ -+ /* Parse the optional "db" field. */ -+ CHECK(cfg_peektoken(pctx, 0)); -+ if (pctx->token.type == isc_tokentype_string) { -+ CHECK(cfg_gettoken(pctx, 0)); -+ if (strcasecmp(TOKEN_STRING(pctx), "db") == 0 && -+ obj->value.tuple[1] == NULL) { -+ CHECK(cfg_parse_obj(pctx, fields[1].type, -+ &obj->value.tuple[1])); -+ } else { -+ CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1])); -+ cfg_ungettoken(pctx); -+ } -+ } -+ -+ CHECK(cfg_parse_obj(pctx, fields[2].type, &obj->value.tuple[2])); -+ CHECK(cfg_parse_obj(pctx, fields[3].type, &obj->value.tuple[3])); -+ -+ *ret = obj; -+ return (ISC_R_SUCCESS); -+ -+ cleanup: -+ CLEANUP_OBJ(obj); -+ return (result); -+} -+ -+static void -+print_geoip(cfg_printer_t *pctx, const cfg_obj_t *obj) { -+ if (obj->value.tuple[1]->type->print != cfg_print_void) { -+ cfg_print_cstr(pctx, " db "); -+ cfg_print_obj(pctx, obj->value.tuple[1]); -+ } -+ cfg_print_obj(pctx, obj->value.tuple[2]); -+ cfg_print_obj(pctx, obj->value.tuple[3]); -+} -+ -+ -+static void -+doc_geoip(cfg_printer_t *pctx, const cfg_type_t *type) { -+ UNUSED(type); -+ cfg_print_cstr(pctx, "[ db "); -+ cfg_doc_enum(pctx, &cfg_type_geoipdb); -+ cfg_print_cstr(pctx, " ]"); -+ cfg_print_chars(pctx, " ", 1); -+ cfg_doc_enum(pctx, &cfg_type_geoiptype); -+ cfg_print_chars(pctx, " ", 1); -+ cfg_print_cstr(pctx, ""); -+} -+#endif /* HAVE_GEOIP */ -+ - /*% - * A "controls" statement is represented as a map with the multivalued - * "inet" and "unix" clauses. -@@ -2251,7 +2361,9 @@ static cfg_type_t cfg_type_statschannels = { - * An optional class, as used in view and zone statements. - */ - static isc_result_t --parse_optional_class(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { -+parse_optional_class(cfg_parser_t *pctx, const cfg_type_t *type, -+ cfg_obj_t **ret) -+{ - isc_result_t result; - UNUSED(type); - CHECK(cfg_peektoken(pctx, 0)); -@@ -2374,6 +2486,16 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) - if (pctx->token.type == isc_tokentype_string && - (strcasecmp(TOKEN_STRING(pctx), "key") == 0)) { - CHECK(cfg_parse_obj(pctx, &cfg_type_keyref, ret)); -+ } else if (pctx->token.type == isc_tokentype_string && -+ (strcasecmp(TOKEN_STRING(pctx), "geoip") == 0)) { -+#ifdef HAVE_GEOIP -+ CHECK(cfg_gettoken(pctx, 0)); -+ CHECK(cfg_parse_obj(pctx, &cfg_type_geoip, ret)); -+#else -+ cfg_parser_error(pctx, CFG_LOG_NEAR, -+ "'geoip' not supported in this build"); -+ return (ISC_R_UNEXPECTEDTOKEN); -+#endif - } else { - if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | - CFG_ADDR_V4PREFIXOK | -@@ -2387,7 +2509,8 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) - } else if (pctx->token.type == isc_tokentype_special) { - if (pctx->token.value.as_char == '{') { - /* Nested match list. */ -- CHECK(cfg_parse_obj(pctx, &cfg_type_bracketed_aml, ret)); -+ CHECK(cfg_parse_obj(pctx, -+ &cfg_type_bracketed_aml, ret)); - } else if (pctx->token.value.as_char == '!') { - CHECK(cfg_gettoken(pctx, 0)); /* read "!" */ - CHECK(cfg_parse_obj(pctx, &cfg_type_negated, ret)); -@@ -2411,7 +2534,7 @@ parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) - */ - - static cfg_tuplefielddef_t negated_fields[] = { -- { "value", &cfg_type_addrmatchelt, 0 }, -+ { "negated", &cfg_type_addrmatchelt, 0 }, - { NULL, NULL, 0 } - }; - --- -2.9.3 - diff --git a/SOURCES/bind99-rh1259514.patch b/SOURCES/bind99-rh1259514.patch deleted file mode 100644 index 3b268d0..0000000 --- a/SOURCES/bind99-rh1259514.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/bin/tests/system/tkey/ns1/named.conf.in b/bin/tests/system/tkey/ns1/named.conf.in -index 50600b7..b0f1700 100644 ---- a/bin/tests/system/tkey/ns1/named.conf.in -+++ b/bin/tests/system/tkey/ns1/named.conf.in -@@ -32,6 +32,7 @@ options { - tkey-domain "server"; - tkey-dhkey "server" KEYID; - allow-query-cache { any; }; -+ random-device "/dev/urandom"; - }; - - key rndc_key { diff --git a/SOURCES/bind99-rh1291185.patch b/SOURCES/bind99-rh1291185.patch deleted file mode 100644 index 9f7c936..0000000 --- a/SOURCES/bind99-rh1291185.patch +++ /dev/null @@ -1,58 +0,0 @@ -diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c -index 8696b15..5ef2dd6 100644 ---- a/lib/dns/resolver.c -+++ b/lib/dns/resolver.c -@@ -7373,9 +7373,12 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - * NXDOMAIN, NXRDATASET, or referral. - */ - result = noanswer_response(fctx, NULL, 0); -- if (result == DNS_R_CHASEDSSERVERS) { -- } else if (result == DNS_R_DELEGATION) { -- force_referral: -+ switch (result) { -+ case ISC_R_SUCCESS: -+ case DNS_R_CHASEDSSERVERS: -+ break; -+ case DNS_R_DELEGATION: -+ force_referral: - /* - * We don't have the answer, but we know a better - * place to look. -@@ -7400,7 +7403,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) { - fctx->adberr = 0; - - result = ISC_R_SUCCESS; -- } else if (result != ISC_R_SUCCESS) { -+ break; -+ default: - /* - * Something has gone wrong. - */ -diff --git a/lib/dns/view.c b/lib/dns/view.c -index 142b09e..35900b3 100644 ---- a/lib/dns/view.c -+++ b/lib/dns/view.c -@@ -1216,6 +1216,7 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, - dns_name_t *zfname; - dns_rdataset_t zrdataset, zsigrdataset; - dns_fixedname_t zfixedname; -+ unsigned int ztoptions = 0; - - #ifndef BIND9 - UNUSED(zone); -@@ -1242,9 +1243,12 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, - #ifdef BIND9 - zone = NULL; - LOCK(&view->lock); -- if (view->zonetable != NULL) -- result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); -- else -+ if (view->zonetable != NULL) { -+ if ((options & DNS_DBFIND_NOEXACT) != 0) -+ ztoptions |= DNS_ZTFIND_NOEXACT; -+ result = dns_zt_find(view->zonetable, name, ztoptions, -+ NULL, &zone); -+ } else - result = ISC_R_NOTFOUND; - if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) - result = dns_zone_getdb(zone, &db); diff --git a/SOURCES/bind99-rh1306610.patch b/SOURCES/bind99-rh1306610.patch deleted file mode 100644 index cf5c8cc..0000000 --- a/SOURCES/bind99-rh1306610.patch +++ /dev/null @@ -1,1847 +0,0 @@ -From 620b1c9d90d0a59a0d892fef089ce4f5f6f61742 Mon Sep 17 00:00:00 2001 -From: Tomas Hozza -Date: Fri, 1 Apr 2016 15:20:27 +0200 -Subject: [PATCH] Added support for CAA records - -Signed-off-by: Tomas Hozza ---- - bin/tests/rdata_test.c | 17 +- - doc/rfc/rfc6844.txt | 1011 ++++++++++++++++++++++++++++++++++++++ - lib/dns/rdata.c | 95 ++-- - lib/dns/rdata/generic/caa_257.c | 370 ++++++++++++++ - lib/dns/rdata/generic/caa_257.h | 32 ++ - lib/dns/rdata/generic/gpos_27.c | 2 +- - lib/dns/rdata/generic/hinfo_13.c | 4 +- - lib/dns/rdata/generic/isdn_20.c | 4 +- - lib/dns/rdata/generic/naptr_35.c | 6 +- - lib/dns/rdata/generic/spf_99.c | 2 +- - lib/dns/rdata/generic/txt_16.c | 2 +- - lib/dns/rdata/generic/uri_256.c | 23 +- - lib/dns/rdata/generic/x25_19.c | 2 +- - 13 files changed, 1478 insertions(+), 92 deletions(-) - create mode 100644 doc/rfc/rfc6844.txt - create mode 100644 lib/dns/rdata/generic/caa_257.c - create mode 100644 lib/dns/rdata/generic/caa_257.h - -diff --git a/bin/tests/rdata_test.c b/bin/tests/rdata_test.c -index 51cc406..0f25364 100644 ---- a/bin/tests/rdata_test.c -+++ b/bin/tests/rdata_test.c -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id: rdata_test.c,v 1.52 2011/08/28 09:10:41 marka Exp $ */ -- - #include - - #include -@@ -284,6 +282,11 @@ viastruct(dns_rdata_t *rdata, isc_mem_t *mctx, - result = dns_rdata_tostruct(rdata, sp = &uri, NULL); - break; - } -+ case dns_rdatatype_caa: { -+ static dns_rdata_caa_t caa; -+ result = dns_rdata_tostruct(rdata, sp = &caa, NULL); -+ break; -+ } - case dns_rdatatype_wks: { - static dns_rdata_in_wks_t in_wks; - result = dns_rdata_tostruct(rdata, sp = &in_wks, NULL); -@@ -551,6 +554,11 @@ viastruct(dns_rdata_t *rdata, isc_mem_t *mctx, - result = dns_rdata_tostruct(rdata, sp = &uri, mctx); - break; - } -+ case dns_rdatatype_caa: { -+ static dns_rdata_caa_t caa; -+ result = dns_rdata_tostruct(rdata, sp = &caa, mctx); -+ break; -+ } - case dns_rdatatype_wks: { - static dns_rdata_in_wks_t in_wks; - result = dns_rdata_tostruct(rdata, sp = &in_wks, mctx); -@@ -848,6 +856,11 @@ viastruct(dns_rdata_t *rdata, isc_mem_t *mctx, - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &uri, b); - break; - } -+ case dns_rdatatype_caa: { -+ dns_rdata_caa_t caa; -+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &caa, b); -+ break; -+ } - case dns_rdatatype_wks: { - dns_rdata_in_wks_t in_wks; - result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_wks, b); -diff --git a/doc/rfc/rfc6844.txt b/doc/rfc/rfc6844.txt -new file mode 100644 -index 0000000..d923649 ---- /dev/null -+++ b/doc/rfc/rfc6844.txt -@@ -0,0 +1,1011 @@ -+ -+ -+ -+ -+ -+ -+Internet Engineering Task Force (IETF) P. Hallam-Baker -+Request for Comments: 6844 Comodo Group, Inc. -+Category: Standards Track R. Stradling -+ISSN: 2070-1721 Comodo CA, Ltd. -+ January 2013 -+ -+ -+ DNS Certification Authority Authorization (CAA) Resource Record -+ -+Abstract -+ -+ The Certification Authority Authorization (CAA) DNS Resource Record -+ allows a DNS domain name holder to specify one or more Certification -+ Authorities (CAs) authorized to issue certificates for that domain. -+ CAA Resource Records allow a public Certification Authority to -+ implement additional controls to reduce the risk of unintended -+ certificate mis-issue. This document defines the syntax of the CAA -+ record and rules for processing CAA records by certificate issuers. -+ -+Status of This Memo -+ -+ This is an Internet Standards Track document. -+ -+ This document is a product of the Internet Engineering Task Force -+ (IETF). It represents the consensus of the IETF community. It has -+ received public review and has been approved for publication by the -+ Internet Engineering Steering Group (IESG). Further information on -+ Internet Standards is available in Section 2 of RFC 5741. -+ -+ Information about the current status of this document, any errata, -+ and how to provide feedback on it may be obtained at -+ http://www.rfc-editor.org/info/rfc6844. -+ -+Copyright Notice -+ -+ Copyright (c) 2013 IETF Trust and the persons identified as the -+ document authors. All rights reserved. -+ -+ This document is subject to BCP 78 and the IETF Trust's Legal -+ Provisions Relating to IETF Documents -+ (http://trustee.ietf.org/license-info) in effect on the date of -+ publication of this document. Please review these documents -+ carefully, as they describe your rights and restrictions with respect -+ to this document. Code Components extracted from this document must -+ include Simplified BSD License text as described in Section 4.e of -+ the Trust Legal Provisions and are provided without warranty as -+ described in the Simplified BSD License. -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 1] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+Table of Contents -+ -+ 1. Introduction ....................................................2 -+ 2. Definitions .....................................................3 -+ 2.1. Requirements Language ......................................3 -+ 2.2. Defined Terms ..............................................3 -+ 3. The CAA RR Type .................................................5 -+ 4. Certification Authority Processing ..............................7 -+ 4.1. Use of DNS Security ........................................8 -+ 5. Mechanism .......................................................8 -+ 5.1. Syntax .....................................................8 -+ 5.1.1. Canonical Presentation Format ......................10 -+ 5.2. CAA issue Property ........................................10 -+ 5.3. CAA issuewild Property ....................................12 -+ 5.4. CAA iodef Property ........................................12 -+ 6. Security Considerations ........................................13 -+ 6.1. Non-Compliance by Certification Authority .................13 -+ 6.2. Mis-Issue by Authorized Certification Authority ...........13 -+ 6.3. Suppression or Spoofing of CAA Records ....................13 -+ 6.4. Denial of Service .........................................14 -+ 6.5. Abuse of the Critical Flag ................................14 -+ 7. IANA Considerations ............................................14 -+ 7.1. Registration of the CAA Resource Record Type ..............14 -+ 7.2. Certification Authority Restriction Properties ............15 -+ 7.3. Certification Authority Restriction Flags .................15 -+ 8. Acknowledgements ...............................................16 -+ 9. References .....................................................16 -+ 9.1. Normative References ......................................16 -+ 9.2. Informative References ....................................17 -+ -+1. Introduction -+ -+ The Certification Authority Authorization (CAA) DNS Resource Record -+ allows a DNS domain name holder to specify the Certification -+ Authorities (CAs) authorized to issue certificates for that domain. -+ Publication of CAA Resource Records allows a public Certification -+ Authority to implement additional controls to reduce the risk of -+ unintended certificate mis-issue. -+ -+ Like the TLSA record defined in DNS-Based Authentication of Named -+ Entities (DANE) [RFC6698], CAA records are used as a part of a -+ mechanism for checking PKIX certificate data. The distinction -+ between the two specifications is that CAA records specify an -+ authorization control to be performed by a certificate issuer before -+ issue of a certificate and TLSA records specify a verification -+ control to be performed by a relying party after the certificate is -+ issued. -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 2] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ Conformance with a published CAA record is a necessary but not -+ sufficient condition for issuance of a certificate. Before issuing a -+ certificate, a PKIX CA is required to validate the request according -+ to the policies set out in its Certificate Policy. In the case of a -+ public CA that validates certificate requests as a third party, the -+ certificate will typically be issued under a public trust anchor -+ certificate embedded in one or more relevant Relying Applications. -+ -+ Criteria for inclusion of embedded trust anchor certificates in -+ applications are outside the scope of this document. Typically, such -+ criteria require the CA to publish a Certificate Practices Statement -+ (CPS) that specifies how the requirements of the Certificate Policy -+ (CP) are achieved. It is also common for a CA to engage an -+ independent third-party auditor to prepare an annual audit statement -+ of its performance against its CPS. -+ -+ A set of CAA records describes only current grants of authority to -+ issue certificates for the corresponding DNS domain. Since a -+ certificate is typically valid for at least a year, it is possible -+ that a certificate that is not conformant with the CAA records -+ currently published was conformant with the CAA records published at -+ the time that the certificate was issued. Relying Applications MUST -+ NOT use CAA records as part of certificate validation. -+ -+ CAA records MAY be used by Certificate Evaluators as a possible -+ indicator of a security policy violation. Such use SHOULD take -+ account of the possibility that published CAA records changed between -+ the time a certificate was issued and the time at which the -+ certificate was observed by the Certificate Evaluator. -+ -+2. Definitions -+ -+2.1. Requirements Language -+ -+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", -+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this -+ document are to be interpreted as described in [RFC2119]. -+ -+2.2. Defined Terms -+ -+ The following terms are used in this document: -+ -+ Authorization Entry: An authorization assertion that grants or -+ denies a specific set of permissions to a specific group of -+ entities. -+ -+ Certificate: An X.509 Certificate, as specified in [RFC5280]. -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 3] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ Certificate Evaluator: A party other than a relying party that -+ evaluates the trustworthiness of certificates issued by -+ Certification Authorities. -+ -+ Certification Authority (CA): An issuer that issues certificates in -+ accordance with a specified Certificate Policy. -+ -+ Certificate Policy (CP): Specifies the criteria that a Certification -+ Authority undertakes to meet in its issue of certificates. See -+ [RFC3647]. -+ -+ Certification Practices Statement (CPS): Specifies the means by -+ which the criteria of the Certificate Policy are met. In most -+ cases, this will be the document against which the operations of -+ the Certification Authority are audited. See [RFC3647]. -+ -+ Domain: A DNS Domain Name. -+ -+ Domain Name: A DNS Domain Name as specified in [STD13]. -+ -+ Domain Name System (DNS): The Internet naming system specified in -+ [STD13]. -+ -+ DNS Security (DNSSEC): Extensions to the DNS that provide -+ authentication services as specified in [RFC4033], [RFC4034], -+ [RFC4035], [RFC5155], and revisions. -+ -+ Issuer: An entity that issues certificates. See [RFC5280]. -+ -+ Property: The tag-value portion of a CAA Resource Record. -+ -+ Property Tag: The tag portion of a CAA Resource Record. -+ -+ Property Value: The value portion of a CAA Resource Record. -+ -+ Public Key Infrastructure X.509 (PKIX): Standards and specifications -+ issued by the IETF that apply the [X.509] certificate standards -+ specified by the ITU to Internet applications as specified in -+ [RFC5280] and related documents. -+ -+ Resource Record (RR): A particular entry in the DNS including the -+ owner name, class, type, time to live, and data, as defined in -+ [STD13] and [RFC2181]. -+ -+ Resource Record Set (RRSet): A set of Resource Records or a -+ particular owner name, class, and type. The time to live on all -+ RRs with an RRSet is always the same, but the data may be -+ different among RRs in the RRSet. -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 4] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ Relying Party: A party that makes use of an application whose -+ operation depends on use of a certificate for making a security -+ decision. See [RFC5280]. -+ -+ Relying Application: An application whose operation depends on use -+ of a certificate for making a security decision. -+ -+3. The CAA RR Type -+ -+ A CAA RR consists of a flags byte and a tag-value pair referred to as -+ a property. Multiple properties MAY be associated with the same -+ domain name by publishing multiple CAA RRs at that domain name. The -+ following flag is defined: -+ -+ Issuer Critical: If set to '1', indicates that the corresponding -+ property tag MUST be understood if the semantics of the CAA record -+ are to be correctly interpreted by an issuer. -+ -+ Issuers MUST NOT issue certificates for a domain if the relevant -+ CAA Resource Record set contains unknown property tags that have -+ the Critical bit set. -+ -+ The following property tags are defined: -+ -+ issue [; = ]* : The issue property -+ entry authorizes the holder of the domain name or a party acting under the explicit authority of the holder -+ of that domain name to issue certificates for the domain in which -+ the property is published. -+ -+ issuewild [; = ]* : The issuewild -+ property entry authorizes the holder of the domain name or a party acting under the explicit authority of the -+ holder of that domain name to issue wildcard certificates for the -+ domain in which the property is published. -+ -+ iodef : Specifies a URL to which an issuer MAY report -+ certificate issue requests that are inconsistent with the issuer's -+ Certification Practices or Certificate Policy, or that a -+ Certificate Evaluator may use to report observation of a possible -+ policy violation. The Incident Object Description Exchange Format -+ (IODEF) format is used [RFC5070]. -+ -+ The following example is a DNS zone file (see [RFC1035]) that informs -+ CAs that certificates are not to be issued except by the holder of -+ the domain name 'ca.example.net' or an authorized agent thereof. -+ This policy applies to all subordinate domains under example.com. -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 5] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ $ORIGIN example.com -+ . CAA 0 issue "ca.example.net" -+ -+ If the domain name holder specifies one or more iodef properties, a -+ certificate issuer MAY report invalid certificate requests to that -+ address. In the following example, the domain name holder specifies -+ that reports may be made by means of email with the IODEF data as an -+ attachment, a Web service [RFC6546], or both: -+ -+ $ORIGIN example.com -+ . CAA 0 issue "ca.example.net" -+ . CAA 0 iodef "mailto:security@example.com" -+ . CAA 0 iodef "http://iodef.example.com/" -+ -+ A certificate issuer MAY specify additional parameters that allow -+ customers to specify additional parameters governing certificate -+ issuance. This might be the Certificate Policy under which the -+ certificate is to be issued, the authentication process to be used -+ might be specified, or an account number specified by the CA to -+ enable these parameters to be retrieved. -+ -+ For example, the CA 'ca.example.net' has requested its customer -+ 'example.com' to specify the CA's account number '230123' in each of -+ the customer's CAA records. -+ -+ $ORIGIN example.com -+ . CAA 0 issue "ca.example.net; account=230123" -+ -+ The syntax of additional parameters is a sequence of name-value pairs -+ as defined in Section 5.2. The semantics of such parameters is left -+ to site policy and is outside the scope of this document. -+ -+ The critical flag is intended to permit future versions CAA to -+ introduce new semantics that MUST be understood for correct -+ processing of the record, preventing conforming CAs that do not -+ recognize the new semantics from issuing certificates for the -+ indicated domains. -+ -+ In the following example, the property 'tbs' is flagged as critical. -+ Neither the example.net CA nor any other issuer is authorized to -+ issue under either policy unless the processing rules for the 'tbs' -+ property tag are understood. -+ -+ $ORIGIN example.com -+ . CAA 0 issue "ca.example.net; policy=ev" -+ . CAA 128 tbs "Unknown" -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 6] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ Note that the above restrictions only apply at certificate issue. -+ Since the validity of an end entity certificate is typically a year -+ or more, it is quite possible that the CAA records published at a -+ domain will change between the time a certificate was issued and -+ validation by a relying party. -+ -+4. Certification Authority Processing -+ -+ Before issuing a certificate, a compliant CA MUST check for -+ publication of a relevant CAA Resource Record set. If such a record -+ set exists, a CA MUST NOT issue a certificate unless the CA -+ determines that either (1) the certificate request is consistent with -+ the applicable CAA Resource Record set or (2) an exception specified -+ in the relevant Certificate Policy or Certification Practices -+ Statement applies. -+ -+ A certificate request MAY specify more than one domain name and MAY -+ specify wildcard domains. Issuers MUST verify authorization for all -+ the domains and wildcard domains specified in the request. -+ -+ The search for a CAA record climbs the DNS name tree from the -+ specified label up to but not including the DNS root '.'. -+ -+ Given a request for a specific domain X, or a request for a wildcard -+ domain *.X, the relevant record set R(X) is determined as follows: -+ -+ Let CAA(X) be the record set returned in response to performing a CAA -+ record query on the label X, P(X) be the DNS label immediately above -+ X in the DNS hierarchy, and A(X) be the target of a CNAME or DNAME -+ alias record specified at the label X. -+ -+ o If CAA(X) is not empty, R(X) = CAA (X), otherwise -+ -+ o If A(X) is not null, and R(A(X)) is not empty, then R(X) = -+ R(A(X)), otherwise -+ -+ o If X is not a top-level domain, then R(X) = R(P(X)), otherwise -+ -+ o R(X) is empty. -+ -+ For example, if a certificate is requested for X.Y.Z the issuer will -+ search for the relevant CAA record set in the following order: -+ -+ X.Y.Z -+ -+ Alias (X.Y.Z) -+ -+ Y.Z -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 7] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ Alias (Y.Z) -+ -+ Z -+ -+ Alias (Z) -+ -+ Return Empty -+ -+4.1. Use of DNS Security -+ -+ Use of DNSSEC to authenticate CAA RRs is strongly RECOMMENDED but not -+ required. An issuer MUST NOT issue certificates if doing so would -+ conflict with the relevant CAA Resource Record set, irrespective of -+ whether the corresponding DNS records are signed. -+ -+ DNSSEC provides a proof of non-existence for both DNS domains and RR -+ set within domains. DNSSEC verification thus enables an issuer to -+ determine if the answer to a CAA record query is empty because the RR -+ set is empty or if it is non-empty but the response has been -+ suppressed. -+ -+ Use of DNSSEC allows an issuer to acquire and archive a proof that -+ they were authorized to issue certificates for the domain. -+ Verification of such archives MAY be an audit requirement to verify -+ CAA record processing compliance. Publication of such archives MAY -+ be a transparency requirement to verify CAA record processing -+ compliance. -+ -+5. Mechanism -+ -+5.1. Syntax -+ -+ A CAA RR contains a single property entry consisting of a tag-value -+ pair. Each tag represents a property of the CAA record. The value -+ of a CAA property is that specified in the corresponding value field. -+ -+ A domain name MAY have multiple CAA RRs associated with it and a -+ given property MAY be specified more than once. -+ -+ The CAA data field contains one property entry. A property entry -+ consists of the following data fields: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 8] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ +0-1-2-3-4-5-6-7-|0-1-2-3-4-5-6-7-| -+ | Flags | Tag Length = n | -+ +----------------+----------------+...+---------------+ -+ | Tag char 0 | Tag char 1 |...| Tag char n-1 | -+ +----------------+----------------+...+---------------+ -+ +----------------+----------------+.....+----------------+ -+ | Value byte 0 | Value byte 1 |.....| Value byte m-1 | -+ +----------------+----------------+.....+----------------+ -+ -+ Where n is the length specified in the Tag length field and m is the -+ remaining octets in the Value field (m = d - n - 2) where d is the -+ length of the RDATA section. -+ -+ The data fields are defined as follows: -+ -+ Flags: One octet containing the following fields: -+ -+ Bit 0, Issuer Critical Flag: If the value is set to '1', the -+ critical flag is asserted and the property MUST be understood -+ if the CAA record is to be correctly processed by a certificate -+ issuer. -+ -+ A Certification Authority MUST NOT issue certificates for any -+ Domain that contains a CAA critical property for an unknown or -+ unsupported property tag that for which the issuer critical -+ flag is set. -+ -+ Note that according to the conventions set out in [RFC1035], bit 0 -+ is the Most Significant Bit and bit 7 is the Least Significant -+ Bit. Thus, the Flags value 1 means that bit 7 is set while a value -+ of 128 means that bit 0 is set according to this convention. -+ -+ All other bit positions are reserved for future use. -+ -+ To ensure compatibility with future extensions to CAA, DNS records -+ compliant with this version of the CAA specification MUST clear -+ (set to "0") all reserved flags bits. Applications that interpret -+ CAA records MUST ignore the value of all reserved flag bits. -+ -+ Tag Length: A single octet containing an unsigned integer specifying -+ the tag length in octets. The tag length MUST be at least 1 and -+ SHOULD be no more than 15. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 9] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ Tag: The property identifier, a sequence of US-ASCII characters. -+ -+ Tag values MAY contain US-ASCII characters 'a' through 'z', 'A' -+ through 'Z', and the numbers 0 through 9. Tag values SHOULD NOT -+ contain any other characters. Matching of tag values is case -+ insensitive. -+ -+ Tag values submitted for registration by IANA MUST NOT contain any -+ characters other than the (lowercase) US-ASCII characters 'a' -+ through 'z' and the numbers 0 through 9. -+ -+ Value: A sequence of octets representing the property value. -+ Property values are encoded as binary values and MAY employ sub- -+ formats. -+ -+ The length of the value field is specified implicitly as the -+ remaining length of the enclosing Resource Record data field. -+ -+5.1.1. Canonical Presentation Format -+ -+ The canonical presentation format of the CAA record is: -+ -+ CAA -+ -+ Where: -+ -+ Flags: Is an unsigned integer between 0 and 255. -+ -+ Tag: Is a non-zero sequence of US-ASCII letters and numbers in lower -+ case. -+ -+ Value: Is the encoding of the value field as -+ specified in [RFC1035], Section 5.1. -+ -+5.2. CAA issue Property -+ -+ The issue property tag is used to request that certificate issuers -+ perform CAA issue restriction processing for the domain and to grant -+ authorization to specific certificate issuers. -+ -+ The CAA issue property value has the following sub-syntax (specified -+ in ABNF as per [RFC5234]). -+ -+ -+ -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 10] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ issuevalue = space [domain] space [";" *(space parameter) space] -+ -+ domain = label *("." label) -+ label = (ALPHA / DIGIT) *( *("-") (ALPHA / DIGIT)) -+ -+ space = *(SP / HTAB) -+ -+ parameter = tag "=" value -+ -+ tag = 1*(ALPHA / DIGIT) -+ -+ value = *VCHAR -+ -+ For consistency with other aspects of DNS administration, domain name -+ values are specified in letter-digit-hyphen Label (LDH-Label) form. -+ -+ A CAA record with an issue parameter tag that does not specify a -+ domain name is a request that certificate issuers perform CAA issue -+ restriction processing for the corresponding domain without granting -+ authorization to any certificate issuer. -+ -+ This form of issue restriction would be appropriate to specify that -+ no certificates are to be issued for the domain in question. -+ -+ For example, the following CAA record set requests that no -+ certificates be issued for the domain 'nocerts.example.com' by any -+ certificate issuer. -+ -+ nocerts.example.com CAA 0 issue ";" -+ -+ A CAA record with an issue parameter tag that specifies a domain name -+ is a request that certificate issuers perform CAA issue restriction -+ processing for the corresponding domain and grants authorization to -+ the certificate issuer specified by the domain name. -+ -+ For example, the following CAA record set requests that no -+ certificates be issued for the domain 'certs.example.com' by any -+ certificate issuer other than the example.net certificate issuer. -+ -+ certs.example.com CAA 0 issue "example.net" -+ -+ CAA authorizations are additive; thus, the result of specifying both -+ the empty issuer and a specified issuer is the same as specifying -+ just the specified issuer alone. -+ -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 11] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ An issuer MAY choose to specify issuer-parameters that further -+ constrain the issue of certificates by that issuer, for example, -+ specifying that certificates are to be subject to specific validation -+ polices, billed to certain accounts, or issued under specific trust -+ anchors. -+ -+ The semantics of issuer-parameters are determined by the issuer -+ alone. -+ -+5.3. CAA issuewild Property -+ -+ The issuewild property has the same syntax and semantics as the issue -+ property except that issuewild properties only grant authorization to -+ issue certificates that specify a wildcard domain and issuewild -+ properties take precedence over issue properties when specified. -+ Specifically: -+ -+ issuewild properties MUST be ignored when processing a request for -+ a domain that is not a wildcard domain. -+ -+ If at least one issuewild property is specified in the relevant -+ CAA record set, all issue properties MUST be ignored when -+ processing a request for a domain that is a wildcard domain. -+ -+5.4. CAA iodef Property -+ -+ The iodef property specifies a means of reporting certificate issue -+ requests or cases of certificate issue for the corresponding domain -+ that violate the security policy of the issuer or the domain name -+ holder. -+ -+ The Incident Object Description Exchange Format (IODEF) [RFC5070] is -+ used to present the incident report in machine-readable form. -+ -+ The iodef property takes a URL as its parameter. The URL scheme type -+ determines the method used for reporting: -+ -+ mailto: The IODEF incident report is reported as a MIME email -+ attachment to an SMTP email that is submitted to the mail address -+ specified. The mail message sent SHOULD contain a brief text -+ message to alert the recipient to the nature of the attachment. -+ -+ http or https: The IODEF report is submitted as a Web service -+ request to the HTTP address specified using the protocol specified -+ in [RFC6546]. -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 12] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+6. Security Considerations -+ -+ CAA records assert a security policy that the holder of a domain name -+ wishes to be observed by certificate issuers. The effectiveness of -+ CAA records as an access control mechanism is thus dependent on -+ observance of CAA constraints by issuers. -+ -+ The objective of the CAA record properties described in this document -+ is to reduce the risk of certificate mis-issue rather than avoid -+ reliance on a certificate that has been mis-issued. DANE [RFC6698] -+ describes a mechanism for avoiding reliance on mis-issued -+ certificates. -+ -+6.1. Non-Compliance by Certification Authority -+ -+ CAA records offer CAs a cost-effective means of mitigating the risk -+ of certificate mis-issue: the cost of implementing CAA checks is very -+ small and the potential costs of a mis-issue event include the -+ removal of an embedded trust anchor. -+ -+6.2. Mis-Issue by Authorized Certification Authority -+ -+ Use of CAA records does not prevent mis-issue by an authorized -+ Certification Authority, i.e., a CA that is authorized to issue -+ certificates for the domain in question by CAA records. -+ -+ Domain name holders SHOULD verify that the CAs they authorize to -+ issue certificates for their domains employ appropriate controls to -+ ensure that certificates are issued only to authorized parties within -+ their organization. -+ -+ Such controls are most appropriately determined by the domain name -+ holder and the authorized CA(s) directly and are thus out of scope of -+ this document. -+ -+6.3. Suppression or Spoofing of CAA Records -+ -+ Suppression of the CAA record or insertion of a bogus CAA record -+ could enable an attacker to obtain a certificate from an issuer that -+ was not authorized to issue for that domain name. -+ -+ Where possible, issuers SHOULD perform DNSSEC validation to detect -+ missing or modified CAA record sets. -+ -+ In cases where DNSSEC is not deployed in a corresponding domain, an -+ issuer SHOULD attempt to mitigate this risk by employing appropriate -+ DNS security controls. For example, all portions of the DNS lookup -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 13] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ process SHOULD be performed against the authoritative name server. -+ Data cached by third parties MUST NOT be relied on but MAY be used to -+ support additional anti-spoofing or anti-suppression controls. -+ -+6.4. Denial of Service -+ -+ Introduction of a malformed or malicious CAA RR could in theory -+ enable a Denial-of-Service (DoS) attack. -+ -+ This specific threat is not considered to add significantly to the -+ risk of running an insecure DNS service. -+ -+ An attacker could, in principle, perform a DoS attack against an -+ issuer by requesting a certificate with a maliciously long DNS name. -+ In practice, the DNS protocol imposes a maximum name length and CAA -+ processing does not exacerbate the existing need to mitigate DoS -+ attacks to any meaningful degree. -+ -+6.5. Abuse of the Critical Flag -+ -+ A Certification Authority could make use of the critical flag to -+ trick customers into publishing records that prevent competing -+ Certification Authorities from issuing certificates even though the -+ customer intends to authorize multiple providers. -+ -+ In practice, such an attack would be of minimal effect since any -+ competent competitor that found itself unable to issue certificates -+ due to lack of support for a property marked critical SHOULD -+ investigate the cause and report the reason to the customer. The -+ customer will thus discover that they had been deceived. -+ -+7. IANA Considerations -+ -+7.1. Registration of the CAA Resource Record Type -+ -+ IANA has assigned Resource Record Type 257 for the CAA Resource -+ Record Type and added the line depicted below to the registry named -+ "Resource Record (RR) TYPEs" and QTYPEs as defined in BCP 42 -+ [RFC6195] and located at -+ http://www.iana.org/assignments/dns-parameters. -+ -+ RR Name Value and meaning Reference -+ ----------- --------------------------------------------- --------- -+ CAA 257 Certification Authority Restriction [RFC6844] -+ -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 14] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+7.2. Certification Authority Restriction Properties -+ -+ IANA has created the "Certification Authority Restriction Properties" -+ registry with the following initial values: -+ -+ -+ Tag Meaning Reference -+ ----------- -------------------------------------- --------- -+ issue Authorization Entry by Domain [RFC6844] -+ issuewild Authorization Entry by Wildcard Domain [RFC6844] -+ iodef Report incident by IODEF report [RFC6844] -+ auth Reserved [HB2011] -+ path Reserved [HB2011] -+ policy Reserved [HB2011] -+ -+ -+ Although [HB2011] has expired, deployed clients implement the CAA -+ properties specified in the document and reuse of these property tags -+ for a different purpose could cause unexpected behavior. -+ -+ Addition of tag identifiers requires a public specification and -+ Expert Review as set out in [RFC6195], Section 3.1.1. -+ -+ The tag space is designed to be sufficiently large that exhausting -+ the possible tag space need not be a concern. The scope of Expert -+ Review SHOULD be limited to the question of whether the specification -+ provided is sufficiently clear to permit implementation and to avoid -+ unnecessary duplication of functionality. -+ -+7.3. Certification Authority Restriction Flags -+ -+ IANA has created the "Certification Authority Restriction Flags" -+ registry with the following initial values: -+ -+ -+ Flag Meaning Reference -+ ----------- ---------------------------------- --------- -+ 0 Issuer Critical Flag [RFC6844] -+ 1-7 Reserved> [RFC6844] -+ -+ Assignment of new flags follows the RFC Required policy set out in -+ [RFC5226], Section 4.1. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 15] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+8. Acknowledgements -+ -+ The authors would like to thank the following people who contributed -+ to the design and documentation of this work item: Chris Evans, -+ Stephen Farrell, Jeff Hodges, Paul Hoffman, Stephen Kent, Adam -+ Langley, Ben Laurie, James Manager, Chris Palmer, Scott Schmit, Sean -+ Turner, and Ben Wilson. -+ -+9. References -+ -+9.1. Normative References -+ -+ [RFC1035] Mockapetris, P., "Domain names - implementation and -+ specification", STD 13, RFC 1035, November 1987. -+ -+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate -+ Requirement Levels", BCP 14, RFC 2119, March 1997. -+ -+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS -+ Specification", RFC 2181, July 1997. -+ -+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S. -+ Rose, "DNS Security Introduction and Requirements", -+ RFC 4033, March 2005. -+ -+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S. -+ Rose, "Resource Records for the DNS Security Extensions", -+ RFC 4034, March 2005. -+ -+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S. -+ Rose, "Protocol Modifications for the DNS Security -+ Extensions", RFC 4035, March 2005. -+ -+ [RFC5070] Danyliw, R., Meijer, J., and Y. Demchenko, "The Incident -+ Object Description Exchange Format", RFC 5070, -+ December 2007. -+ -+ [RFC5155] Laurie, B., Sisson, G., Arends, R., and D. Blacka, "DNS -+ Security (DNSSEC) Hashed Authenticated Denial of -+ Existence", RFC 5155, March 2008. -+ -+ [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an -+ IANA Considerations Section in RFCs", BCP 26, RFC 5226, -+ May 2008. -+ -+ [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax -+ Specifications: ABNF", STD 68, RFC 5234, January 2008. -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 16] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+ [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., -+ Housley, R., and W. Polk, "Internet X.509 Public Key -+ Infrastructure Certificate and Certificate Revocation List -+ (CRL) Profile", RFC 5280, May 2008. -+ -+ [RFC6195] Eastlake, D., "Domain Name System (DNS) IANA -+ Considerations", BCP 42, RFC 6195, March 2011. -+ -+ [RFC6546] Trammell, B., "Transport of Real-time Inter-network -+ Defense (RID) Messages over HTTP/TLS", RFC 6546, -+ April 2012. -+ -+ [RFC6698] Hoffman, P. and J. Schlyter, "The DNS-Based Authentication -+ of Named Entities (DANE) Transport Layer Security (TLS) -+ Protocol: TLSA", RFC 6698, August 2012. -+ -+ [STD13] Mockapetris, P., "Domain names - concepts and facilities", -+ STD 13, RFC 1034, November 1987. -+ -+ Mockapetris, P., "Domain names - implementation and -+ specification", STD 13, RFC 1035, November 1987. -+ -+ [X.509] International Telecommunication Union, "ITU-T -+ Recommendation X.509 (11/2008): Information technology - -+ Open systems interconnection - The Directory: Public-key -+ and attribute certificate frameworks", ITU-T -+ Recommendation X.509, November 2008. -+ -+9.2. Informative References -+ -+ [HB2011] Hallam-Baker, P., Stradling, R., and B. Laurie, "DNS -+ Certification Authority Authorization (CAA) Resource -+ Record", Work in Progress, May 2011. -+ -+ [RFC3647] Chokhani, S., Ford, W., Sabett, R., Merrill, C., and S. -+ Wu, "Internet X.509 Public Key Infrastructure Certificate -+ Policy and Certification Practices Framework", RFC 3647, -+ November 2003. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 17] -+ -+RFC 6844 Certification Authority Authorization January 2013 -+ -+ -+Authors' Addresses -+ -+ Phillip Hallam-Baker -+ Comodo Group, Inc. -+ -+ EMail: philliph@comodo.com -+ -+ -+ Rob Stradling -+ Comodo CA, Ltd. -+ -+ EMail: rob.stradling@comodo.com -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+Hallam-Baker & Stradling Standards Track [Page 18] -+ -diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c -index a83dab4..9bf83a4 100644 ---- a/lib/dns/rdata.c -+++ b/lib/dns/rdata.c -@@ -116,7 +116,7 @@ typedef struct dns_rdata_textctx { - } dns_rdata_textctx_t; - - static isc_result_t --txt_totext(isc_region_t *source, isc_buffer_t *target); -+txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target); - - static isc_result_t - txt_fromtext(isc_textregion_t *source, isc_buffer_t *target); -@@ -130,9 +130,6 @@ multitxt_totext(isc_region_t *source, isc_buffer_t *target); - static isc_result_t - multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target); - --static isc_result_t --multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target); -- - static isc_boolean_t - name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target); - -@@ -1131,7 +1128,7 @@ name_length(dns_name_t *name) { - } - - static isc_result_t --txt_totext(isc_region_t *source, isc_buffer_t *target) { -+txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target) { - unsigned int tl; - unsigned int n; - unsigned char *sp; -@@ -1146,13 +1143,20 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) { - n = *sp++; - - REQUIRE(n + 1 <= source->length); -+ if (n == 0U) -+ REQUIRE(quote == ISC_TRUE); - -- if (tl < 1) -- return (ISC_R_NOSPACE); -- *tp++ = '"'; -- tl--; -+ if (quote) { -+ if (tl < 1) -+ return (ISC_R_NOSPACE); -+ *tp++ = '"'; -+ tl--; -+ } - while (n--) { -- if (*sp < 0x20 || *sp >= 0x7f) { -+ /* -+ * \DDD space (0x20) if not quoting. -+ */ -+ if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) { - if (tl < 4) - return (ISC_R_NOSPACE); - *tp++ = 0x5c; -@@ -1163,8 +1167,13 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) { - tl -= 4; - continue; - } -- /* double quote, semi-colon, backslash */ -- if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) { -+ /* -+ * Escape double quote, semi-colon, backslash. -+ * If we are not enclosing the string in double -+ * quotes also escape at sign. -+ */ -+ if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c || -+ (!quote && *sp == 0x40)) { - if (tl < 2) - return (ISC_R_NOSPACE); - *tp++ = '\\'; -@@ -1175,10 +1184,12 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) { - *tp++ = *sp++; - tl--; - } -- if (tl < 1) -- return (ISC_R_NOSPACE); -- *tp++ = '"'; -- tl--; -+ if (quote) { -+ if (tl < 1) -+ return (ISC_R_NOSPACE); -+ *tp++ = '"'; -+ tl--; -+ } - isc_buffer_add(target, tp - (char *)region.base); - isc_region_consume(source, *source->base + 1); - return (ISC_R_SUCCESS); -@@ -1274,6 +1285,9 @@ txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { - return (ISC_R_SUCCESS); - } - -+/* -+ * Conversion of TXT-like rdata fields without length limits. -+ */ - static isc_result_t - multitxt_totext(isc_region_t *source, isc_buffer_t *target) { - unsigned int tl; -@@ -1292,9 +1306,8 @@ multitxt_totext(isc_region_t *source, isc_buffer_t *target) { - *tp++ = '"'; - tl--; - do { -- n0 = n = *sp++; -- -- REQUIRE(n0 + 1 <= source->length); -+ n = source->length; -+ n0 = source->length - 1; - - while (n--) { - if (*sp < 0x20 || *sp >= 0x7f) { -@@ -1346,17 +1359,11 @@ multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { - - do { - isc_buffer_availableregion(target, &tregion); -- t0 = tregion.base; -+ t0 = t = tregion.base; - nrem = tregion.length; - if (nrem < 1) - return (ISC_R_NOSPACE); -- /* length byte */ -- t = t0; -- nrem--; -- t++; -- /* 255 byte character-string slice */ -- if (nrem > 255) -- nrem = 255; -+ - while (n != 0) { - --n; - c = (*s++) & 0xff; -@@ -1390,39 +1397,9 @@ multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { - } - if (escape) - return (DNS_R_SYNTAX); -- *t0 = t - t0 - 1; -- isc_buffer_add(target, *t0 + 1); -- } while (n != 0); -- return (ISC_R_SUCCESS); --} -- --static isc_result_t --multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { -- unsigned int n; -- isc_region_t sregion; -- isc_region_t tregion; -- -- isc_buffer_activeregion(source, &sregion); -- if (sregion.length == 0) -- return(ISC_R_UNEXPECTEDEND); -- n = 256U; -- do { -- if (n != 256U) -- return (DNS_R_SYNTAX); -- n = *sregion.base + 1; -- if (n > sregion.length) -- return (ISC_R_UNEXPECTEDEND); - -- isc_buffer_availableregion(target, &tregion); -- if (n > tregion.length) -- return (ISC_R_NOSPACE); -- -- if (tregion.base != sregion.base) -- memcpy(tregion.base, sregion.base, n); -- isc_buffer_forward(source, n); -- isc_buffer_add(target, n); -- isc_buffer_activeregion(source, &sregion); -- } while (sregion.length != 0); -+ isc_buffer_add(target, t - t0); -+ } while (n != 0); - return (ISC_R_SUCCESS); - } - -diff --git a/lib/dns/rdata/generic/caa_257.c b/lib/dns/rdata/generic/caa_257.c -new file mode 100644 -index 0000000..671f332 ---- /dev/null -+++ b/lib/dns/rdata/generic/caa_257.c -@@ -0,0 +1,370 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef GENERIC_CAA_257_C -+#define GENERIC_CAA_257_C 1 -+ -+#define RRTYPE_CAA_ATTRIBUTES (0) -+ -+static unsigned char const alphanumeric[256] = { -+ /* 0x00-0x0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0x10-0x1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0x20-0x2f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0x30-0x3f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, -+ /* 0x40-0x4f */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -+ /* 0x50-0x5f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, -+ /* 0x60-0x6f */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -+ /* 0x70-0x7f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, -+ /* 0x80-0x8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0x90-0x9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0xa0-0xaf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0xb0-0xbf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0xc0-0xcf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0xd0-0xdf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0xe0-0xef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ /* 0xf0-0xff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+}; -+ -+static inline isc_result_t -+fromtext_caa(ARGS_FROMTEXT) { -+ isc_token_t token; -+ isc_textregion_t tr; -+ isc_uint8_t flags; -+ unsigned int i; -+ -+ REQUIRE(type == 257); -+ -+ UNUSED(type); -+ UNUSED(rdclass); -+ UNUSED(origin); -+ UNUSED(options); -+ UNUSED(callbacks); -+ -+ /* Flags. */ -+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, -+ ISC_FALSE)); -+ if (token.value.as_ulong > 255U) -+ RETTOK(ISC_R_RANGE); -+ flags = token.value.as_ulong & 255U; -+ RETERR(uint8_tobuffer(flags, target)); -+ -+ /* -+ * Tag -+ */ -+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, -+ ISC_FALSE)); -+ tr = token.value.as_textregion; -+ for (i = 0; i < tr.length; i++) -+ if (!alphanumeric[(unsigned char) tr.base[i]]) -+ RETTOK(DNS_R_SYNTAX); -+ RETERR(uint8_tobuffer(tr.length, target)); -+ RETERR(mem_tobuffer(target, tr.base, tr.length)); -+ -+ /* -+ * Value -+ */ -+ RETERR(isc_lex_getmastertoken(lexer, &token, -+ isc_tokentype_qstring, ISC_FALSE)); -+ if (token.type != isc_tokentype_qstring && -+ token.type != isc_tokentype_string) -+ RETERR(DNS_R_SYNTAX); -+ RETERR(multitxt_fromtext(&token.value.as_textregion, target)); -+ return (ISC_R_SUCCESS); -+} -+ -+static inline isc_result_t -+totext_caa(ARGS_TOTEXT) { -+ isc_region_t region; -+ isc_uint8_t flags; -+ char buf[256]; -+ -+ UNUSED(tctx); -+ -+ REQUIRE(rdata->type == 257); -+ REQUIRE(rdata->length >= 3U); -+ REQUIRE(rdata->data != NULL); -+ -+ dns_rdata_toregion(rdata, ®ion); -+ -+ /* -+ * Flags -+ */ -+ flags = uint8_consume_fromregion(®ion); -+ sprintf(buf, "%u ", flags); -+ RETERR(str_totext(buf, target)); -+ -+ /* -+ * Tag -+ */ -+ RETERR(txt_totext(®ion, ISC_FALSE, target)); -+ RETERR(str_totext(" ", target)); -+ -+ /* -+ * Value -+ */ -+ RETERR(multitxt_totext(®ion, target)); -+ return (ISC_R_SUCCESS); -+} -+ -+static inline isc_result_t -+fromwire_caa(ARGS_FROMWIRE) { -+ isc_region_t sr; -+ unsigned int len, i; -+ -+ REQUIRE(type == 257); -+ -+ UNUSED(type); -+ UNUSED(rdclass); -+ UNUSED(dctx); -+ UNUSED(options); -+ -+ /* -+ * Flags -+ */ -+ isc_buffer_activeregion(source, &sr); -+ if (sr.length < 2) -+ return (ISC_R_UNEXPECTEDEND); -+ -+ /* -+ * Flags, tag length -+ */ -+ RETERR(mem_tobuffer(target, sr.base, 2)); -+ len = sr.base[1]; -+ isc_region_consume(&sr, 2); -+ isc_buffer_forward(source, 2); -+ -+ /* -+ * Zero length tag fields are illegal. -+ */ -+ if (sr.length < len || len == 0) -+ RETERR(DNS_R_FORMERR); -+ -+ /* Check the Tag's value */ -+ for (i = 0; i < len; i++) -+ if (!alphanumeric[sr.base[i]]) -+ RETERR(DNS_R_FORMERR); -+ /* -+ * Tag + Value -+ */ -+ isc_buffer_forward(source, sr.length); -+ return (mem_tobuffer(target, sr.base, sr.length)); -+} -+ -+static inline isc_result_t -+towire_caa(ARGS_TOWIRE) { -+ isc_region_t region; -+ -+ REQUIRE(rdata->type == 257); -+ REQUIRE(rdata->length >= 3U); -+ REQUIRE(rdata->data != NULL); -+ -+ UNUSED(cctx); -+ -+ dns_rdata_toregion(rdata, ®ion); -+ return (mem_tobuffer(target, region.base, region.length)); -+} -+ -+static inline int -+compare_caa(ARGS_COMPARE) { -+ isc_region_t r1, r2; -+ -+ REQUIRE(rdata1->type == rdata2->type); -+ REQUIRE(rdata1->rdclass == rdata2->rdclass); -+ REQUIRE(rdata1->type == 257); -+ REQUIRE(rdata1->length >= 3U); -+ REQUIRE(rdata2->length >= 3U); -+ REQUIRE(rdata1->data != NULL); -+ REQUIRE(rdata2->data != NULL); -+ -+ dns_rdata_toregion(rdata1, &r1); -+ dns_rdata_toregion(rdata2, &r2); -+ return (isc_region_compare(&r1, &r2)); -+} -+ -+static inline isc_result_t -+fromstruct_caa(ARGS_FROMSTRUCT) { -+ dns_rdata_caa_t *caa = source; -+ isc_region_t region; -+ unsigned int i; -+ -+ REQUIRE(type == 257); -+ REQUIRE(source != NULL); -+ REQUIRE(caa->common.rdtype == type); -+ REQUIRE(caa->common.rdclass == rdclass); -+ REQUIRE(caa->tag != NULL && caa->tag_len != 0); -+ REQUIRE(caa->value != NULL); -+ -+ UNUSED(type); -+ UNUSED(rdclass); -+ -+ /* -+ * Flags -+ */ -+ RETERR(uint8_tobuffer(caa->flags, target)); -+ -+ /* -+ * Tag length -+ */ -+ RETERR(uint8_tobuffer(caa->tag_len, target)); -+ -+ /* -+ * Tag -+ */ -+ region.base = caa->tag; -+ region.length = caa->tag_len; -+ for (i = 0; i < region.length; i++) -+ if (!alphanumeric[region.base[i]]) -+ RETERR(DNS_R_SYNTAX); -+ RETERR(isc_buffer_copyregion(target, ®ion)); -+ -+ /* -+ * Value -+ */ -+ region.base = caa->value; -+ region.length = caa->value_len; -+ return (isc_buffer_copyregion(target, ®ion)); -+} -+ -+static inline isc_result_t -+tostruct_caa(ARGS_TOSTRUCT) { -+ dns_rdata_caa_t *caa = target; -+ isc_region_t sr; -+ -+ REQUIRE(rdata->type == 257); -+ REQUIRE(target != NULL); -+ REQUIRE(rdata->length >= 3U); -+ REQUIRE(rdata->data != NULL); -+ -+ caa->common.rdclass = rdata->rdclass; -+ caa->common.rdtype = rdata->type; -+ ISC_LINK_INIT(&caa->common, link); -+ -+ dns_rdata_toregion(rdata, &sr); -+ -+ /* -+ * Flags -+ */ -+ if (sr.length < 1) -+ return (ISC_R_UNEXPECTEDEND); -+ caa->flags = uint8_fromregion(&sr); -+ isc_region_consume(&sr, 1); -+ -+ /* -+ * Tag length -+ */ -+ if (sr.length < 1) -+ return (ISC_R_UNEXPECTEDEND); -+ caa->tag_len = uint8_fromregion(&sr); -+ isc_region_consume(&sr, 1); -+ -+ /* -+ * Tag -+ */ -+ if (sr.length < caa->tag_len) -+ return (ISC_R_UNEXPECTEDEND); -+ caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len); -+ if (caa->tag == NULL) -+ return (ISC_R_NOMEMORY); -+ isc_region_consume(&sr, caa->tag_len); -+ -+ /* -+ * Value -+ */ -+ caa->value_len = sr.length; -+ caa->value = mem_maybedup(mctx, sr.base, sr.length); -+ if (caa->value == NULL) -+ return (ISC_R_NOMEMORY); -+ -+ caa->mctx = mctx; -+ return (ISC_R_SUCCESS); -+} -+ -+static inline void -+freestruct_caa(ARGS_FREESTRUCT) { -+ dns_rdata_caa_t *caa = (dns_rdata_caa_t *) source; -+ -+ REQUIRE(source != NULL); -+ REQUIRE(caa->common.rdtype == 257); -+ -+ if (caa->mctx == NULL) -+ return; -+ -+ if (caa->tag != NULL) -+ isc_mem_free(caa->mctx, caa->tag); -+ if (caa->value != NULL) -+ isc_mem_free(caa->mctx, caa->value); -+ caa->mctx = NULL; -+} -+ -+static inline isc_result_t -+additionaldata_caa(ARGS_ADDLDATA) { -+ REQUIRE(rdata->type == 257); -+ REQUIRE(rdata->data != NULL); -+ REQUIRE(rdata->length >= 3U); -+ -+ UNUSED(rdata); -+ UNUSED(add); -+ UNUSED(arg); -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static inline isc_result_t -+digest_caa(ARGS_DIGEST) { -+ isc_region_t r; -+ -+ REQUIRE(rdata->type == 257); -+ REQUIRE(rdata->data != NULL); -+ REQUIRE(rdata->length >= 3U); -+ -+ dns_rdata_toregion(rdata, &r); -+ -+ return ((digest)(arg, &r)); -+} -+ -+static inline isc_boolean_t -+checkowner_caa(ARGS_CHECKOWNER) { -+ -+ REQUIRE(type == 257); -+ -+ UNUSED(name); -+ UNUSED(type); -+ UNUSED(rdclass); -+ UNUSED(wildcard); -+ -+ return (ISC_TRUE); -+} -+ -+static inline isc_boolean_t -+checknames_caa(ARGS_CHECKNAMES) { -+ -+ REQUIRE(rdata->type == 257); -+ REQUIRE(rdata->data != NULL); -+ REQUIRE(rdata->length >= 3U); -+ -+ UNUSED(rdata); -+ UNUSED(owner); -+ UNUSED(bad); -+ -+ return (ISC_TRUE); -+} -+ -+static inline int -+casecompare_caa(ARGS_COMPARE) { -+ return (compare_caa(rdata1, rdata2)); -+} -+ -+#endif /* GENERIC_CAA_257_C */ -diff --git a/lib/dns/rdata/generic/caa_257.h b/lib/dns/rdata/generic/caa_257.h -new file mode 100644 -index 0000000..79866a5 ---- /dev/null -+++ b/lib/dns/rdata/generic/caa_257.h -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+ * PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#ifndef GENERIC_CAA_257_H -+#define GENERIC_CAA_257_H 1 -+ -+/* $Id$ */ -+ -+typedef struct dns_rdata_caa { -+ dns_rdatacommon_t common; -+ isc_mem_t * mctx; -+ isc_uint8_t flags; -+ unsigned char * tag; -+ isc_uint8_t tag_len; -+ unsigned char *value; -+ isc_uint8_t value_len; -+} dns_rdata_caa_t; -+ -+#endif /* GENERIC_CAA_257_H */ -diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c -index ce71822..5a90216 100644 ---- a/lib/dns/rdata/generic/gpos_27.c -+++ b/lib/dns/rdata/generic/gpos_27.c -@@ -61,7 +61,7 @@ totext_gpos(ARGS_TOTEXT) { - dns_rdata_toregion(rdata, ®ion); - - for (i = 0; i < 3; i++) { -- RETERR(txt_totext(®ion, target)); -+ RETERR(txt_totext(®ion, ISC_TRUE, target)); - if (i != 2) - RETERR(str_totext(" ", target)); - } -diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c -index 10b4fec..92038b7 100644 ---- a/lib/dns/rdata/generic/hinfo_13.c -+++ b/lib/dns/rdata/generic/hinfo_13.c -@@ -58,9 +58,9 @@ totext_hinfo(ARGS_TOTEXT) { - REQUIRE(rdata->length != 0); - - dns_rdata_toregion(rdata, ®ion); -- RETERR(txt_totext(®ion, target)); -+ RETERR(txt_totext(®ion, ISC_TRUE, target)); - RETERR(str_totext(" ", target)); -- return (txt_totext(®ion, target)); -+ return (txt_totext(®ion, ISC_TRUE, target)); - } - - static inline isc_result_t -diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c -index 5aac73f..059c247 100644 ---- a/lib/dns/rdata/generic/isdn_20.c -+++ b/lib/dns/rdata/generic/isdn_20.c -@@ -65,11 +65,11 @@ totext_isdn(ARGS_TOTEXT) { - UNUSED(tctx); - - dns_rdata_toregion(rdata, ®ion); -- RETERR(txt_totext(®ion, target)); -+ RETERR(txt_totext(®ion, ISC_TRUE, target)); - if (region.length == 0) - return (ISC_R_SUCCESS); - RETERR(str_totext(" ", target)); -- return (txt_totext(®ion, target)); -+ return (txt_totext(®ion, ISC_TRUE, target)); - } - - static inline isc_result_t -diff --git a/lib/dns/rdata/generic/naptr_35.c b/lib/dns/rdata/generic/naptr_35.c -index 83439a5..be7d403 100644 ---- a/lib/dns/rdata/generic/naptr_35.c -+++ b/lib/dns/rdata/generic/naptr_35.c -@@ -224,19 +224,19 @@ totext_naptr(ARGS_TOTEXT) { - /* - * Flags. - */ -- RETERR(txt_totext(®ion, target)); -+ RETERR(txt_totext(®ion, ISC_TRUE, target)); - RETERR(str_totext(" ", target)); - - /* - * Service. - */ -- RETERR(txt_totext(®ion, target)); -+ RETERR(txt_totext(®ion, ISC_TRUE, target)); - RETERR(str_totext(" ", target)); - - /* - * Regexp. - */ -- RETERR(txt_totext(®ion, target)); -+ RETERR(txt_totext(®ion, ISC_TRUE, target)); - RETERR(str_totext(" ", target)); - - /* -diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c -index 492e315..85594fd 100644 ---- a/lib/dns/rdata/generic/spf_99.c -+++ b/lib/dns/rdata/generic/spf_99.c -@@ -64,7 +64,7 @@ totext_spf(ARGS_TOTEXT) { - dns_rdata_toregion(rdata, ®ion); - - while (region.length > 0) { -- RETERR(txt_totext(®ion, target)); -+ RETERR(txt_totext(®ion, ISC_TRUE, target)); - if (region.length > 0) - RETERR(str_totext(" ", target)); - } -diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c -index e1bce6a..e0e8ea5 100644 ---- a/lib/dns/rdata/generic/txt_16.c -+++ b/lib/dns/rdata/generic/txt_16.c -@@ -71,7 +71,7 @@ totext_txt(ARGS_TOTEXT) { - dns_rdata_toregion(rdata, ®ion); - - while (region.length > 0) { -- RETERR(txt_totext(®ion, target)); -+ RETERR(txt_totext(®ion, ISC_TRUE, target)); - if (region.length > 0) - RETERR(str_totext(" ", target)); - } -diff --git a/lib/dns/rdata/generic/uri_256.c b/lib/dns/rdata/generic/uri_256.c -index 799eb69..62bdd25 100644 ---- a/lib/dns/rdata/generic/uri_256.c -+++ b/lib/dns/rdata/generic/uri_256.c -@@ -115,15 +115,12 @@ fromwire_uri(ARGS_FROMWIRE) { - isc_buffer_activeregion(source, ®ion); - if (region.length < 4) - return (ISC_R_UNEXPECTEDEND); -- RETERR(mem_tobuffer(target, region.base, 4)); -- isc_buffer_forward(source, 4); - - /* -- * Target URI -+ * Priority, weight and target URI - */ -- RETERR(multitxt_fromwire(source, target)); -- -- return (ISC_R_SUCCESS); -+ isc_buffer_forward(source, region.length); -+ return (mem_tobuffer(target, region.base, region.length)); - } - - static inline isc_result_t -@@ -178,8 +175,6 @@ compare_uri(ARGS_COMPARE) { - static inline isc_result_t - fromstruct_uri(ARGS_FROMSTRUCT) { - dns_rdata_uri_t *uri = source; -- isc_region_t region; -- isc_uint8_t len; - - REQUIRE(type == 256); - REQUIRE(source != NULL); -@@ -203,18 +198,6 @@ fromstruct_uri(ARGS_FROMSTRUCT) { - /* - * Target URI - */ -- len = 255U; -- region.base = uri->target; -- region.length = uri->tgt_len; -- while (region.length > 0) { -- REQUIRE(len == 255U); -- len = uint8_fromregion(®ion); -- isc_region_consume(®ion, 1); -- if (region.length < len) -- return (ISC_R_UNEXPECTEDEND); -- isc_region_consume(®ion, len); -- } -- - return (mem_tobuffer(target, uri->target, uri->tgt_len)); - } - -diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c -index 6867fec..f9dfb8a 100644 ---- a/lib/dns/rdata/generic/x25_19.c -+++ b/lib/dns/rdata/generic/x25_19.c -@@ -60,7 +60,7 @@ totext_x25(ARGS_TOTEXT) { - REQUIRE(rdata->length != 0); - - dns_rdata_toregion(rdata, ®ion); -- return (txt_totext(®ion, target)); -+ return (txt_totext(®ion, ISC_TRUE, target)); - } - - static inline isc_result_t --- -2.4.3 - diff --git a/SOURCES/bind99-rh1392362.patch b/SOURCES/bind99-rh1392362.patch deleted file mode 100644 index a936c1f..0000000 --- a/SOURCES/bind99-rh1392362.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 3acf8e092f95233bc3d854e161569487dce83ba2 Mon Sep 17 00:00:00 2001 -From: Mark Andrews -Date: Fri, 3 Feb 2017 14:22:03 +1100 -Subject: [PATCH] 4567. [port] Call getprotobyname and getservbyname prior to - calling chroot so that shared libraries get loaded. [RT #44537] - ---- - lib/isc/unix/dir.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/lib/isc/unix/dir.c b/lib/isc/unix/dir.c -index 0d64778..ee80f41 100644 ---- a/lib/isc/unix/dir.c -+++ b/lib/isc/unix/dir.c -@@ -31,6 +31,7 @@ - - #include - #include -+#include - #include - #include - -@@ -172,6 +173,15 @@ isc_dir_chroot(const char *dirname) { - REQUIRE(dirname != NULL); - - #ifdef HAVE_CHROOT -+ /* -+ * Try to use getservbyname and getprotobyname before chroot. -+ * If WKS records are used in a zone under chroot, Name Service Switch -+ * may fail to load library in chroot. -+ * Do not report errors if it fails, we do not need any result now. -+ */ -+ if (getprotobyname("udp")) -+ (void)getservbyname("domain", "udp"); -+ - if (chroot(dirname) < 0 || chdir("/") < 0) - return (isc__errno2result(errno)); - --- -2.9.3 - diff --git a/SOURCES/bind99-rh1416304.patch b/SOURCES/bind99-rh1416304.patch deleted file mode 100644 index 34a9c23..0000000 --- a/SOURCES/bind99-rh1416304.patch +++ /dev/null @@ -1,139 +0,0 @@ -From e7a2611c555e03314ac4f7960044b05cce040364 Mon Sep 17 00:00:00 2001 -From: Mark Andrews -Date: Thu, 31 Jul 2014 11:38:11 +1000 -Subject: [PATCH] 3905. [bug] Address deadlock between view.c and adb.c. [RT - #36341] -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Original-commit: 5e746ab61ed8158f784b86111fef95581a08b7dd -Signed-off-by: Petr Menšík ---- - lib/dns/adb.c | 57 +++++++++++++++++++++++++++++++++++++++++---------------- - 1 file changed, 41 insertions(+), 16 deletions(-) - -diff --git a/lib/dns/adb.c b/lib/dns/adb.c -index a6da94d..ac89e66 100644 ---- a/lib/dns/adb.c -+++ b/lib/dns/adb.c -@@ -15,8 +15,6 @@ - * PERFORMANCE OF THIS SOFTWARE. - */ - --/* $Id: adb.c,v 1.264 2011/12/05 17:10:51 each Exp $ */ -- - /*! \file - * - * \note -@@ -157,7 +155,7 @@ struct dns_adb { - unsigned int *entry_refcnt; - - isc_event_t cevent; -- isc_boolean_t cevent_sent; -+ isc_boolean_t cevent_out; - isc_boolean_t shutting_down; - isc_eventlist_t whenshutdown; - isc_event_t growentries; -@@ -322,6 +320,7 @@ static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *); - static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t); - static void water(void *, int); - static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t); -+static void shutdown_task(isc_task_t *task, isc_event_t *ev); - - /* - * MUST NOT overlap DNS_ADBFIND_* flags! -@@ -1499,10 +1498,13 @@ check_exit(dns_adb_t *adb) { - * If there aren't any external references either, we're - * done. Send the control event to initiate shutdown. - */ -- INSIST(!adb->cevent_sent); /* Sanity check. */ -+ INSIST(!adb->cevent_out); /* Sanity check. */ -+ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, -+ DNS_EVENT_ADBCONTROL, shutdown_task, adb, -+ adb, NULL, NULL); - event = &adb->cevent; - isc_task_send(adb->task, &event); -- adb->cevent_sent = ISC_TRUE; -+ adb->cevent_out = ISC_TRUE; - } - } - -@@ -2431,10 +2433,9 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, - adb->view = view; - adb->taskmgr = taskmgr; - adb->next_cleanbucket = 0; -- ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, -- DNS_EVENT_ADBCONTROL, shutdown_task, adb, -- adb, NULL, NULL); -- adb->cevent_sent = ISC_FALSE; -+ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), -+ 0, NULL, 0, NULL, NULL, NULL, NULL, NULL); -+ adb->cevent_out = ISC_FALSE; - adb->shutting_down = ISC_FALSE; - ISC_LIST_INIT(adb->whenshutdown); - -@@ -2468,7 +2469,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, - "intializing table sizes to %u\n", - nbuckets[11]); - adb->nentries = nbuckets[11]; -- adb->nnames= nbuckets[11]; -+ adb->nnames = nbuckets[11]; - - } - -@@ -2741,9 +2742,28 @@ dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) { - UNLOCK(&adb->lock); - } - -+static void -+shutdown_stage2(isc_task_t *task, isc_event_t *event) { -+ dns_adb_t *adb; -+ -+ UNUSED(task); -+ -+ adb = event->ev_arg; -+ INSIST(DNS_ADB_VALID(adb)); -+ -+ LOCK(&adb->lock); -+ INSIST(adb->shutting_down); -+ adb->cevent_out = ISC_FALSE; -+ (void)shutdown_names(adb); -+ (void)shutdown_entries(adb); -+ if (dec_adb_irefcnt(adb)) -+ check_exit(adb); -+ UNLOCK(&adb->lock); -+} -+ - void - dns_adb_shutdown(dns_adb_t *adb) { -- isc_boolean_t need_check_exit; -+ isc_event_t *event; - - /* - * Shutdown 'adb'. -@@ -2754,11 +2774,16 @@ dns_adb_shutdown(dns_adb_t *adb) { - if (!adb->shutting_down) { - adb->shutting_down = ISC_TRUE; - isc_mem_setwater(adb->mctx, water, adb, 0, 0); -- need_check_exit = shutdown_names(adb); -- if (!need_check_exit) -- need_check_exit = shutdown_entries(adb); -- if (need_check_exit) -- check_exit(adb); -+ /* -+ * Isolate shutdown_names and shutdown_entries calls. -+ */ -+ inc_adb_irefcnt(adb); -+ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, -+ DNS_EVENT_ADBCONTROL, shutdown_stage2, adb, -+ adb, NULL, NULL); -+ adb->cevent_out = ISC_TRUE; -+ event = &adb->cevent; -+ isc_task_send(adb->task, &event); - } - - UNLOCK(&adb->lock); --- -2.9.3 - diff --git a/SOURCES/bind99-rh1464850-2.patch b/SOURCES/bind99-rh1464850-2.patch deleted file mode 100644 index 6c4d07c..0000000 --- a/SOURCES/bind99-rh1464850-2.patch +++ /dev/null @@ -1,102 +0,0 @@ -From a58f31659a924c59f6342d79d2c19ee956453d82 Mon Sep 17 00:00:00 2001 -From: Mark Andrews -Date: Sat, 18 Oct 2014 12:40:13 +1100 -Subject: [PATCH 2/2] 3980. [bug] Improve --with-tuning=large by - self tuning of SO_RCVBUF size. [RT #37187] - -(cherry picked from commit 871f3c8beeb2134b17414ec167b90a57adb8e122) ---- - lib/isc/unix/socket.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 61 insertions(+), 5 deletions(-) - -diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c -index af0c3bc..90953ff 100644 ---- a/lib/isc/unix/socket.c -+++ b/lib/isc/unix/socket.c -@@ -2245,6 +2245,62 @@ free_socket(isc__socket_t **socketp) { - *socketp = NULL; - } - -+#ifdef SO_RCVBUF -+static isc_once_t rcvbuf_once = ISC_ONCE_INIT; -+static int rcvbuf = RCVBUFSIZE; -+ -+static void -+set_rcvbuf(void) { -+ int fd; -+ int max = rcvbuf, min; -+ ISC_SOCKADDR_LEN_T len; -+ -+ fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); -+#if defined(ISC_PLATFORM_HAVEIPV6) -+ if (fd == -1) { -+ switch (errno) { -+ case EPROTONOSUPPORT: -+ case EPFNOSUPPORT: -+ case EAFNOSUPPORT: -+ /* -+ * Linux 2.2 (and maybe others) return EINVAL instead of -+ * EAFNOSUPPORT. -+ */ -+ case EINVAL: -+ fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); -+ break; -+ } -+ } -+#endif -+ if (fd == -1) -+ return; -+ -+ len = sizeof(min); -+ if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&min, &len) >= 0 && -+ min < rcvbuf) { -+ again: -+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, -+ sizeof(rcvbuf)) == -1) { -+ if (errno == ENOBUFS && rcvbuf > min) { -+ max = rcvbuf - 1; -+ rcvbuf = (rcvbuf + min) / 2; -+ goto again; -+ } else { -+ rcvbuf = min; -+ goto cleanup; -+ } -+ } else -+ min = rcvbuf; -+ if (min != max) { -+ rcvbuf = max; -+ goto again; -+ } -+ } -+ cleanup: -+ close (fd); -+} -+#endif -+ - #ifdef SO_BSDCOMPAT - /* - * This really should not be necessary to do. Having to workout -@@ -2609,15 +2665,15 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock, - #if defined(SO_RCVBUF) - optlen = sizeof(size); - if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, -- (void *)&size, &optlen) >= 0 && -- size < RCVBUFSIZE) { -- size = RCVBUFSIZE; -+ (void *)&size, &optlen) >= 0 && size < rcvbuf) { -+ RUNTIME_CHECK(isc_once_do(&rcvbuf_once, -+ set_rcvbuf) == ISC_R_SUCCESS); - if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, -- (void *)&size, sizeof(size)) == -1) { -+ (void *)&rcvbuf, sizeof(rcvbuf)) == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, SO_RCVBUF, %d) %s: %s", -- sock->fd, size, -+ sock->fd, rcvbuf, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, --- -2.9.5 - diff --git a/SOURCES/bind99-rh1464850.patch b/SOURCES/bind99-rh1464850.patch deleted file mode 100644 index f96db9a..0000000 --- a/SOURCES/bind99-rh1464850.patch +++ /dev/null @@ -1,1849 +0,0 @@ -From b154e9fd7a4acc87435f858d43b8c234885a8763 Mon Sep 17 00:00:00 2001 -From: Evan Hunt -Date: Tue, 18 Feb 2014 22:36:14 -0800 -Subject: [PATCH 1/2] add "--with-tuning=large" option - -3745. [func] "configure --with-tuning=large" adjusts various - compiled-in constants and default settings to - values suited to large servers with abundant - memory. [RT #29538] - -(cherry picked from commit 6a3fa181d1253db5191139e20231512eebaddeeb) ---- - README | 8 + - bin/named/bind9.ver3.xsl.h | 6 +- - bin/named/interfacemgr.c | 9 +- - bin/named/named.docbook | 3 + - bin/named/server.c | 21 +- - bin/named/update.c | 2 +- - config.h.in | 3 + - configure | 1064 ++++++++++++++++++++++++++++++++++++-------- - configure.in | 25 ++ - lib/dns/client.c | 8 +- - lib/isc/unix/socket.c | 12 + - 11 files changed, 975 insertions(+), 186 deletions(-) - -diff --git a/README b/README -index b22e9ce..7451acb 100644 ---- a/README -+++ b/README -@@ -221,6 +221,14 @@ Building - To build shared libraries, specify "--with-libtool" on the - configure command line. - -+ Certain compiled-in constants and default settings can be -+ increased to values better suited to large servers with abundant -+ memory resources (e.g, 64-bit servers with 12G or more of memory) -+ by specifying "--with-tuning=large" on the configure command -+ line. This can improve performance on big servers, but will -+ consume more memory and may degrade performance on smaller -+ systems. -+ - For the server to support DNSSEC, you need to build it - with crypto support. You must have OpenSSL 0.9.5a - or newer installed and specify "--with-openssl" on the -diff --git a/bin/named/bind9.ver3.xsl.h b/bin/named/bind9.ver3.xsl.h -index c55714a..8c0a4a9 100644 ---- a/bin/named/bind9.ver3.xsl.h -+++ b/bin/named/bind9.ver3.xsl.h -@@ -210,7 +210,7 @@ static char xslmsg[] = - "

Incoming Requests

\n" - " \n" - " \n" -- "
[graph incoming requests]
\n" -+ "
[no incoming requests]
\n" - "
\n" - " \n" - " \n" -@@ -235,7 +235,7 @@ static char xslmsg[] = - "

Incoming Queries by Type

\n" - " \n" - " \n" -- "
[graph incoming qtypes]
\n" -+ "
[no incoming queries]
\n" - "
\n" - "
\n" - " \n" -@@ -307,7 +307,7 @@ static char xslmsg[] = - " \n" - "