diff --git a/acx_nlnetlabs.m4 b/acx_nlnetlabs.m4 index 5bcd8212b..9648ecd61 100644 --- a/acx_nlnetlabs.m4 +++ b/acx_nlnetlabs.m4 @@ -2,9 +2,8 @@ # Copyright 2009, Wouter Wijngaards, NLnet Labs. # BSD licensed. # -# Version 5 +# Version 4 # Changelog -# 2009-08-07 Added openssl/conf.h header detection. # 2009-07-14 U_CHAR detection improved for windows crosscompile. # added ACX_FUNC_MALLOC # fixup some #if to #ifdef @@ -652,7 +651,6 @@ AC_DEFUN([ACX_SSL_CHECKS], [ AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT]) ])dnl End of ACX_SSL_CHECKS dnl Check for SSL, where SSL is mandatory diff --git a/config.guess b/config.guess index 7b24a8728..da8331460 100755 --- a/config.guess +++ b/config.guess @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. -timestamp='2008-11-15' +timestamp='2009-04-27' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -324,6 +324,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; @@ -337,7 +340,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if echo '\n#ifdef __amd64\nIS_64BIT_ARCH\n#endif' | \ + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then @@ -1115,8 +1118,11 @@ EOF pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 @@ -1154,6 +1160,16 @@ EOF 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; @@ -1340,6 +1356,9 @@ EOF i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 diff --git a/config.h.in b/config.h.in index deb9768d1..aa9d13fb0 100644 --- a/config.h.in +++ b/config.h.in @@ -152,6 +152,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_CONF_H +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ENGINE_H + /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_ERR_H @@ -641,6 +644,10 @@ #include #endif +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif + #ifdef HAVE_ATTR_FORMAT diff --git a/config.sub b/config.sub index 053e7381f..a39437d01 100755 --- a/config.sub +++ b/config.sub @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. -timestamp='2008-09-08' +timestamp='2009-04-17' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -122,6 +122,7 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` @@ -249,6 +250,7 @@ case $basic_machine in | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ + | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ @@ -270,6 +272,7 @@ case $basic_machine in | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | moxie \ | mt \ | msp430 \ | nios | nios2 \ @@ -279,7 +282,7 @@ case $basic_machine in | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | score \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -331,6 +334,7 @@ case $basic_machine in | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ + | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ @@ -362,7 +366,7 @@ case $basic_machine in | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ @@ -443,6 +447,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; aux) basic_machine=m68k-apple os=-aux @@ -1182,7 +1190,7 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) @@ -1254,8 +1262,9 @@ case $os in -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ diff --git a/configure b/configure index 3c8ace48d..ca10b3cee 100755 --- a/configure +++ b/configure @@ -17412,68 +17412,6 @@ fi done -for ac_header in openssl/conf.h -do -as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 -$as_echo_n "checking for $ac_header... " >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - $as_echo_n "(cached) " >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - eval "$as_ac_Header=yes" -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_Header=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -ac_res=`eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` - { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -as_val=`eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` - if test "x$as_val" = x""yes; then - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - # check if libssl needs libdl @@ -17631,6 +17569,130 @@ rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext +for ac_header in openssl/conf.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in openssl/engine.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + diff --git a/configure.ac b/configure.ac index 2fe4871df..c2af68562 100644 --- a/configure.ac +++ b/configure.ac @@ -351,6 +351,8 @@ fi # Checks for libraries. ACX_WITH_SSL ACX_LIB_SSL +AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512]) AC_ARG_ENABLE(sha2, AC_HELP_STRING([--enable-sha2], [Enable SHA256 and SHA512 RRSIG support, experimental])) @@ -654,6 +656,10 @@ dnl includes #ifdef HAVE_OPENSSL_CONF_H #include #endif + +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif ] AHX_CONFIG_FORMAT_ATTRIBUTE diff --git a/daemon/daemon.c b/daemon/daemon.c index f07556987..3b1889909 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -501,7 +501,7 @@ daemon_delete(struct daemon* daemon) /* libcrypto cleanup */ #ifdef HAVE_OPENSSL_CONFIG EVP_cleanup(); - /*ENGINE_cleanup();*/ + ENGINE_cleanup(); CONF_modules_free(); #endif CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */ diff --git a/doc/Changelog b/doc/Changelog index 2c252093a..7824ce0db 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +24 August 2009: Wouter + - cleaner memory allocation on exit. autotrust test routines. + 21 August 2009: Wouter - autotrust: debug routines. Read,write and conversions work. diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 118fd0e8a..f465efe3c 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -51,6 +51,7 @@ #include "util/data/msgparse.h" #include "util/data/msgreply.h" #include "util/data/msgencode.h" +#include "util/config_file.h" #include "services/listen_dnsport.h" #include "services/outside_network.h" #include "testcode/replay.h" @@ -76,6 +77,18 @@ timeval_add(struct timeval* d, const struct timeval* add) #endif } +void +fake_temp_file(const char* adj, const char* id, char* buf, size_t len) +{ +#ifdef USE_WINSOCK + snprintf(buf, len, "testbound_%u%s%s.tmp", + (unsigned)getpid(), adj, id); +#else + snprintf(buf, len, "/tmp/testbound_%u%s%s.tmp", + (unsigned)getpid(), adj, id); +#endif +} + void fake_event_init(struct replay_scenario* scen) { @@ -116,6 +129,7 @@ repevt_string(enum replay_event_type t) case repevt_time_passes: return "TIME_PASSES"; case repevt_back_reply: return "REPLY"; case repevt_back_query: return "CHECK_OUT_QUERY"; + case repevt_autotrust_check: return "CHECK_AUTOTRUST"; case repevt_error: return "ERROR"; default: return "UNKNOWN"; } @@ -437,6 +451,51 @@ time_passes(struct replay_runtime* runtime, struct replay_moment* mom) #endif } +/** check autotrust file contents */ +static void +autotrust_check(struct replay_moment* mom) +{ + char name[1024], line[1024]; + FILE *in; + int lineno = 0, oke=1; + struct config_strlist* p; + line[sizeof(line)-1] = 0; + log_assert(mom->autotrust_id); + fake_temp_file("_auto_", mom->autotrust_id, name, sizeof(name)); + in = fopen(name, "r"); + if(!in) fatal_exit("could not open %s: %s", name, strerror(errno)); + for(p=mom->file_content; p; p=p->next) { + lineno++; + if(!fgets(line, (int)sizeof(line)-1, in)) { + log_err("autotrust check failed, could not read line"); + log_err("file %s, line %d", name, lineno); + log_err("should be: %s", p->str); + fatal_exit("autotrust_check failed"); + } + if(line[0]) line[strlen(line)-1] = 0; /* remove newline */ + if(strcmp(p->str, line) != 0) { + log_err("mismatch in file %s, line %d", name, lineno); + log_err("file has : %s", line); + log_err("should be: %s", p->str); + oke = 0; + continue; + } + fprintf(stderr, "%s:%2d ok : %s\n", name, lineno, line); + } + if(fgets(line, (int)sizeof(line)-1, in)) { + log_err("autotrust check failed, extra lines in %s after %d", + name, lineno); + do { + fprintf(stderr, "file has: %s", line); + } while(fgets(line, (int)sizeof(line)-1, in)); + oke = 0; + } + fclose(in); + if(!oke) + fatal_exit("autotrust_check STEP %d failed", mom->time_step); + log_info("autotrust %s is OK", mom->autotrust_id); +} + /** * Advance to the next moment. */ @@ -504,6 +563,10 @@ do_moment_and_advance(struct replay_runtime* runtime) time_passes(runtime, runtime->now); advance_moment(runtime); break; + case repevt_autotrust_check: + autotrust_check(runtime->now); + advance_moment(runtime); + break; default: fatal_exit("testbound: unknown event type %d", runtime->now->evt_type); diff --git a/testcode/fake_event.h b/testcode/fake_event.h index 7d90527a2..236be03b6 100644 --- a/testcode/fake_event.h +++ b/testcode/fake_event.h @@ -63,4 +63,13 @@ void fake_event_init(struct replay_scenario* scen); */ void fake_event_cleanup(); +/** + * Get filename to store temporary config stuff. The pid is added. in /tmp. + * @param adj: adjective, like "_cfg_", "_auto_" + * @param id: identifier, like "example.com". + * @param buf: where to store. + * @param len: length of buf. + */ +void fake_temp_file(const char* adj, const char* id, char* buf, size_t len); + #endif /* TESTCODE_FAKE_EVENT_H */ diff --git a/testcode/replay.c b/testcode/replay.c index 22b8908b3..e97017b50 100644 --- a/testcode/replay.c +++ b/testcode/replay.c @@ -42,6 +42,7 @@ #include "config.h" #include "util/log.h" #include "util/net_help.h" +#include "util/config_file.h" #include "testcode/replay.h" #include "testcode/ldns-testpkts.h" @@ -73,6 +74,8 @@ replay_moment_delete(struct replay_moment* mom) if(mom->match) { delete_entry(mom->match); } + free(mom->autotrust_id); + config_delstrlist(mom->file_content); free(mom); } @@ -173,6 +176,31 @@ replay_range_read(char* remain, FILE* in, const char* name, int* lineno, return NULL; } +/** Read FILE match content */ +static void +read_file_content(FILE* in, int* lineno, struct replay_moment* mom) +{ + char line[MAX_LINE_LEN]; + char* remain = line; + struct config_strlist** last = &mom->file_content; + line[MAX_LINE_LEN-1]=0; + if(!fgets(line, MAX_LINE_LEN-1, in)) + fatal_exit("FILE_BEGIN expected at line %d", *lineno); + if(!parse_keyword(&remain, "FILE_BEGIN")) + fatal_exit("FILE_BEGIN expected at line %d", *lineno); + while(fgets(line, MAX_LINE_LEN-1, in)) { + (*lineno)++; + if(strncmp(line, "FILE_END", 8) == 0) { + return; + } + if(line[0]) line[strlen(line)-1] = 0; /* remove newline */ + if(!cfg_strlist_insert(last, strdup(line))) + fatal_exit("malloc failure"); + last = &( (*last)->next ); + } + fatal_exit("no FILE_END in input file"); +} + /** * Read a replay moment 'STEP' from file. * @param remain: Rest of line (after STEP keyword). @@ -223,6 +251,14 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno, mom->evt_type = repevt_timeout; } else if(parse_keyword(&remain, "TIME_PASSES")) { mom->evt_type = repevt_time_passes; + } else if(parse_keyword(&remain, "CHECK_AUTOTRUST")) { + mom->evt_type = repevt_autotrust_check; + while(isspace((int)*remain)) + remain++; + if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n') + remain[strlen(remain)-1] = 0; + mom->autotrust_id = strdup(remain); + read_file_content(in, lineno, mom); } else if(parse_keyword(&remain, "ERROR")) { mom->evt_type = repevt_error; } else { diff --git a/testcode/replay.h b/testcode/replay.h index 4562ca847..09e42b0cc 100644 --- a/testcode/replay.h +++ b/testcode/replay.h @@ -41,6 +41,15 @@ *
  * File format for replay files.
  *
+ * ; unbound.conf options.
+ * ; ...
+ * ; additional commandline options to pass to unbound
+ * COMMANDLINE cmdline_option
+ * ; autotrust key file contents, also adds auto-trust-anchor-file: "x" to cfg
+ * AUTOTRUST_FILE id
+ * ; contents of that file
+ * AUTOTRUST_END
+ * CONFIG_END
  * ; comment line.
  * SCENARIO_BEGIN name_of_scenario
  * RANGE_BEGIN start_time end_time
@@ -60,6 +69,7 @@
  *      o TIMEOUT
  *      o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be 
  *      			a floating point number.
+ *      o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
  *      o ERROR
  * ; following entry starts on the next line, ENTRY_BEGIN.
  * ; more STEP items
@@ -156,6 +166,8 @@ struct replay_moment {
 		repevt_back_reply,
 		/** test fails if query to the network does not match */
 		repevt_back_query,
+		/** check autotrust key file */
+		repevt_autotrust_check,
 		/** an error happens to outbound query */
 		repevt_error
 	} 
@@ -178,6 +190,11 @@ struct replay_moment {
 	 * Unused at this time.
 	 */
 	ldns_rr* qname;
+
+	/** the autotrust file id to check */
+	char* autotrust_id;
+	/** file contents to match, one string per line */
+	struct config_strlist* file_content;
 };
 
 /**
diff --git a/testcode/testbound.c b/testcode/testbound.c
index 1bb2b8690..106cd9870 100644
--- a/testcode/testbound.c
+++ b/testcode/testbound.c
@@ -43,6 +43,7 @@
 #include "testcode/replay.h"
 #include "testcode/fake_event.h"
 #include "daemon/remote.h"
+#include "util/config_file.h"
 
 /** 
  * include the main program from the unbound daemon.
@@ -54,8 +55,8 @@
 
 /** maximum line length for lines in the replay file. */
 #define MAX_LINE_LEN 1024
-/** the config file (removed at exit) */
-static char cfgfile[MAX_LINE_LEN];
+/** config files (removed at exit) */
+static struct config_strlist* cfgfiles = NULL;
 
 /** give commandline usage for testbound. */
 static void
@@ -122,27 +123,60 @@ echo_cmdline(int argc, char* argv[])
 	fprintf(stderr, "\n");
 }
 
-/** process config elements */
+/** spool autotrust file */
 static void
-setup_config(FILE* in, char* configfile, int* lineno,
-	int* pass_argc, char* pass_argv[])
+spool_auto_file(FILE* in, int* lineno, FILE* cfg, char* id)
 {
+	char line[MAX_LINE_LEN];
+	char* parse;
+	FILE* spool;
+	/* find filename for new file */
+	while(isspace((int)*id))
+		id++;
+	if(strlen(id)==0) 
+		fatal_exit("AUTROTRUST_FILE must have id, line %d", *lineno);
+	id[strlen(id)-1]=0; /* remove newline */
+	fake_temp_file("_auto_", id, line, sizeof(line));
+	/* add option for the file */
+	fprintf(cfg, "server:	auto-trust-anchor-file: \"%s\"\n", line);
+	/* open file and spool to it */
+	spool = fopen(line, "w");
+	if(!spool) fatal_exit("could not open %s: %s", line, strerror(errno));
+	fprintf(stderr, "testbound is spooling key file: %s\n", line);
+	if(!cfg_strlist_insert(&cfgfiles, strdup(line))) 
+		fatal_exit("out of memory");
+	line[sizeof(line)-1] = 0;
+	while(fgets(line, MAX_LINE_LEN-1, in)) {
+		parse = line;
+		(*lineno)++;
+		while(isspace((int)*parse))
+			parse++;
+		if(strncmp(parse, "AUTOTRUST_END", 13) == 0) {
+			fclose(spool);
+			return;
+		}
+		fputs(line, spool);
+	}
+	fatal_exit("no AUTOTRUST_END in input file");
+}
+
+/** process config elements */
+static void
+setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
+{
+	char configfile[MAX_LINE_LEN];
 	char line[MAX_LINE_LEN];
 	char* parse;
 	FILE* cfg;
-#ifdef USE_WINSOCK
-	snprintf(configfile, MAX_LINE_LEN, "testbound_cfg_%u.tmp", 
-		(unsigned)getpid());
-#else
-	snprintf(configfile, MAX_LINE_LEN, "/tmp/testbound_cfg_%u.tmp", 
-		(unsigned)getpid());
-#endif
+	fake_temp_file("_cfg", "", configfile, sizeof(configfile));
 	add_opts("-c", pass_argc, pass_argv);
 	add_opts(configfile, pass_argc, pass_argv);
 	cfg = fopen(configfile, "w");
 	if(!cfg) fatal_exit("could not open %s: %s", 
 			configfile, strerror(errno));
-	line[MAX_LINE_LEN-1] = 0;
+	if(!cfg_strlist_insert(&cfgfiles, strdup(configfile))) 
+		fatal_exit("out of memory");
+	line[sizeof(line)-1] = 0;
 	/* some basic settings to not pollute the host system */
 	fprintf(cfg, "server:	use-syslog: no\n");
 	fprintf(cfg, "		directory: \"\"\n");
@@ -161,6 +195,10 @@ setup_config(FILE* in, char* configfile, int* lineno,
 			add_opts(parse+11, pass_argc, pass_argv);
 			continue;
 		}
+		if(strncmp(parse, "AUTOTRUST_FILE", 14) == 0) {
+			spool_auto_file(in, lineno, cfg, parse+14);
+			continue;
+		}
 		if(strncmp(parse, "CONFIG_END", 10) == 0) {
 			fclose(cfg);
 			return;
@@ -173,8 +211,7 @@ setup_config(FILE* in, char* configfile, int* lineno,
 
 /** read playback file */
 static struct replay_scenario* 
-setup_playback(const char* filename, char* configfile,
-	int* pass_argc, char* pass_argv[])
+setup_playback(const char* filename, int* pass_argc, char* pass_argv[])
 {
 	struct replay_scenario* scen = NULL;
 	int lineno = 0;
@@ -185,7 +222,7 @@ setup_playback(const char* filename, char* configfile,
 			perror(filename);
 			exit(1);
 		}
-		setup_config(in, configfile, &lineno, pass_argc, pass_argv);
+		setup_config(in, &lineno, pass_argc, pass_argv);
 		scen = replay_scenario_read(in, filename, &lineno);
 		fclose(in);
 		if(!scen)
@@ -199,9 +236,13 @@ setup_playback(const char* filename, char* configfile,
 /** remove config file at exit */
 void remove_configfile(void)
 {
-	unlink(cfgfile);
+	struct config_strlist* p;
+	for(p=cfgfiles; p; p=p->next)
+		unlink(p->str);
+	config_delstrlist(cfgfiles);
+	cfgfiles = NULL;
 }
-	
+
 /**
  * Main fake event test program. Setup, teardown and report errors.
  * @param argc: arg count.
@@ -221,7 +262,6 @@ main(int argc, char* argv[])
 	log_init(NULL, 0, NULL);
 	log_info("Start of %s testbound program.", PACKAGE_STRING);
 	/* determine commandline options for the daemon */
-	cfgfile[0] = 0;
 	pass_argc = 1;
 	pass_argv[0] = "unbound";
 	add_opts("-d", &pass_argc, pass_argv);
@@ -273,7 +313,7 @@ main(int argc, char* argv[])
 		fatal_exit("atexit() failed: %s", strerror(errno));
 
 	/* setup test environment */
-	scen = setup_playback(playback_file, cfgfile, &pass_argc, pass_argv);
+	scen = setup_playback(playback_file, &pass_argc, pass_argv);
 	/* init fake event backend */
 	fake_event_init(scen);
 
diff --git a/testdata/autotrust_init.rpl b/testdata/autotrust_init.rpl
new file mode 100644
index 000000000..53de376e7
--- /dev/null
+++ b/testdata/autotrust_init.rpl
@@ -0,0 +1,141 @@
+; config options
+server:
+	target-fetch-policy: "0 0 0 0 0"
+	log-time-ascii: yes
+stub-zone:
+	name: "."
+	stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+; initial content (say from dig example.com DNSKEY > example.com.key) 
+AUTOTRUST_FILE example.com
+example.com.	10800	IN	DNSKEY	257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b}
+example.com.	10800	IN	DNSKEY	256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+AUTOTRUST_END
+CONFIG_END
+
+SCENARIO_BEGIN Test autotrust with initial trust anchor
+
+; K-ROOT
+RANGE_BEGIN 0 100
+	ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id copy_query
+REPLY QR AA
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS k.root-servers.net.
+SECTION ADDITIONAL
+k.root-servers.net IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+	ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+	ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com.	3600	IN	A	10.20.30.40
+www.example.com.	3600	IN	RRSIG	A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899}
+SECTION AUTHORITY
+example.com.	3600	IN	NS	ns.example.com.
+example.com.	3600	IN	RRSIG	NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com.	3600	IN	A	1.2.3.4
+ns.example.com.	3600	IN	RRSIG	A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qname qtype
+ADJUST copy_id
+REPLY QR AA
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+; KSK 1
+example.com.	10800	IN	DNSKEY	257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b}
+; ZSK 1
+example.com.	10800	IN	DNSKEY	256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (ksk), size = 512b}
+; signatures
+example.com.	10800	IN	RRSIG	DNSKEY 5 2 10800 20090924111500 20090821111500 30899 example.com. b/HK231jIQLX8IhlZfup3r0yhpXaasbPE6LzxoEVVvWaTZWcLmeV8jDIcn0qO7Yvs7bIJN20lwVAV0GcHH3hWQ== ;{id = 30899}
+example.com.	10800	IN	RRSIG	DNSKEY 5 2 10800 20090924111500 20090821111500 55582 example.com. PCHme1QLoULxqjhg5tMlpR0qJlBfstEUVq18TtNoKQe9le1YhJ9caheXcTWoK+boLhXxg9u6Yyvq8FboQh0OjA== ;{id = 55582}
+
+ENTRY_END
+RANGE_END
+
+; set date/time to Aug 24 09:46:40  (2009).
+STEP 5 TIME_PASSES ELAPSE 1251100000
+
+STEP 10 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com.	3600	IN	A	10.20.30.40
+www.example.com.	3600	IN	RRSIG	A 5 3 3600 20090924111500 20090821111500 30899 example.com. pYGxVLsWUvOp1wSf0iwPap+JnECfC5GAm1lRqy3YEqecNGld7U7x/5Imo3CerbdZrVptUQs2oH0lcjwYJXMnsw== ;{id = 30899}
+SECTION AUTHORITY
+example.com.	3600	IN	NS	ns.example.com.
+example.com.	3600	IN	RRSIG	NS 5 2 3600 20090924111500 20090821111500 30899 example.com. J5wxRq0jgwQL6yy530kvo9cHqNAUHV8IF4dvaYZL0bNraO2Oe6dVXqlJl4+cxNHI2TMsstwFPr2Zz8tv6Az2mQ== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com.	3600	IN	A	1.2.3.4
+ns.example.com.	3600	IN	RRSIG	A 5 3 3600 20090924111500 20090821111500 30899 example.com. JsXbS18oyc0zkVaOWGSFdIQuOsZKflT0GraT9afDPoWLCgH4ApF7jNgfJV7Pqy1sTBRajME5IUAhpANwGBuW4A== ;{id = 30899}
+ENTRY_END
+
+; The autotrust anchor was probed due to the query.
+
+STEP 30 CHECK_AUTOTRUST example.com
+FILE_BEGIN
+; autotrust trust anchor file
+;;id: example.com. 1
+;;last_queried: 1251100000 ;;Mon Aug 24 09:46:40 2009
+;;last_success: 1251100000 ;;Mon Aug 24 09:46:40 2009
+;;next_probe_time: 0 ;;Thu Jan  1 01:00:00 1970
+;;query_failed: 0
+;;query_interval: 5400
+;;retry_time: 3600
+example.com.	10800	IN	DNSKEY	257 3 5 AwEAAc3Z5DQDJpH4oPdNtC4BUQHk50XMD+dHr4r8psHmivIa83hxR5CRgCtd9sENCW9Ae8OIO19xw9t/RPaEAqQa+OE= ;{id = 55582 (ksk), size = 512b} ;;state=2 [  VALID  ] ;;count=0 ;;lastchange=1251100000 ;;Mon Aug 24 09:46:40 2009
+FILE_END
+
+SCENARIO_END
diff --git a/validator/autotrust.c b/validator/autotrust.c
index 33e2671fd..7efbe49be 100644
--- a/validator/autotrust.c
+++ b/validator/autotrust.c
@@ -70,6 +70,7 @@ void autr_global_delete(struct autr_global_data* global)
 		return;
 	/* elements deleted by parent, nothing to do */
 	memset(global, 0, sizeof(*global));
+	free(global);
 }
 
 int probetree_cmp(const void* x, const void* y)
@@ -235,14 +236,7 @@ parse_comments(char* str, struct autr_ta* ta)
                 timestamp = atoi(comments);
         }
         if (pos < 0 || !timestamp)
-        {
-		/* Should we warn about this? It happens for key priming.
-			verbose_key(ta, VERB_OPS, "has no timestamp, "
-					"considered NOW");
-		*/
-		/* cannot use event base timeptr, because not inited yet */
-		ta->last_change = (uint32_t)time(NULL);
-        }
+		ta->last_change = 0;
         else
                 ta->last_change = (uint32_t)timestamp;
 
@@ -354,7 +348,6 @@ autr_rrset_delete(struct ub_packed_rrset_key* r)
 
 void autr_point_delete(struct trust_anchor* tp)
 {
-	struct autr_ta* p, *np;
 	if(!tp)
 		return;
 	lock_unprotect(&tp->lock, tp);
@@ -362,14 +355,17 @@ void autr_point_delete(struct trust_anchor* tp)
 	lock_basic_destroy(&tp->lock);
 	autr_rrset_delete(tp->ds_rrset);
 	autr_rrset_delete(tp->dnskey_rrset);
-	p = tp->autr->keys;
-	while(p) {
-		np = p->next;
-		ldns_rr_free(p->rr);
-		free(p);
-		p = np;
+	if(tp->autr) {
+		struct autr_ta* p = tp->autr->keys, *np;
+		while(p) {
+			np = p->next;
+			ldns_rr_free(p->rr);
+			free(p);
+			p = np;
+		}
+		free(tp->autr->file);
+		free(tp->autr);
 	}
-	free(tp->autr);
 	free(tp->name);
 	free(tp);
 }
@@ -1290,6 +1286,10 @@ anchor_state_update(struct module_env* env, struct autr_ta* anchor, int* c)
 		/* KeyRem: MISSING */
 		else if (!anchor->fetched)
 			do_keyrem(env, anchor, c);
+		else if(!anchor->last_change) {
+			verbose_key(anchor, VERB_ALGO, "first prime");
+			reset_holddown(env, anchor, c);
+		}
 		break;
 	/* MISSING */
 	case AUTR_STATE_MISSING:
@@ -1380,7 +1380,8 @@ autr_cleanup_keys(struct trust_anchor* tp)
 	prevp = &tp->autr->keys;
 	while(p) {
 		/* do we want to remove this key? */
-		if(p->s == AUTR_STATE_START || p->s == AUTR_STATE_REMOVED) {
+		if(p->s == AUTR_STATE_START || p->s == AUTR_STATE_REMOVED ||
+			!rr_is_dnskey_sep(p->rr)) {
 			struct autr_ta* np = p->next;
 			/* remove */
 			ldns_rr_free(p->rr);
@@ -1390,6 +1391,9 @@ autr_cleanup_keys(struct trust_anchor* tp)
 			p = np;
 			continue;
 		}
+		/* remove pending counts if no longer pending */
+		if(p->s != AUTR_STATE_ADDPEND)
+			p->pending_count = 0;
 		prevp = &p->next;
 		p = p->next;
 	}
diff --git a/validator/autotrust.h b/validator/autotrust.h
index 8ebc2cf7e..4b12a3644 100644
--- a/validator/autotrust.h
+++ b/validator/autotrust.h
@@ -83,7 +83,7 @@ struct autr_ta {
  */
 struct autr_point_data {
 	/** file to store the trust point in. chrootdir already applied. */
-	const char* file;
+	char* file;
 	/** rbtree node for probe sort, key is struct trust_anchor */
 	rbnode_t pnode;