diff -U 5 -r libspf2-1.2.5.orig/config.h.in libspf2-1.2.5/config.h.in --- libspf2-1.2.5.orig/config.h.in 2005-02-23 21:15:21.000000000 -0500 +++ libspf2-1.2.5/config.h.in 2008-04-25 14:14:38.000000000 -0400 @@ -44,10 +44,13 @@ #undef HAVE_INET_NTOA /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + /* Define to 1 if you have the `intl' library (-lintl). */ #undef HAVE_LIBINTL /* Define to 1 if you have the <libintl.h> header file. */ #undef HAVE_LIBINTL_H @@ -59,10 +62,16 @@ #undef HAVE_LIBPTHREAD /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET +/* Define to 1 if you have the `sres' library (-lsres). */ +#undef HAVE_LIBSRES + +/* Define to 1 if you have the `val-threads' library (-lval-threads). */ +#undef HAVE_LIBVAL_THREADS + /* Define to 1 if you have the <limits.h> header file. */ #undef HAVE_LIMITS_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ @@ -211,10 +220,13 @@ #undef HAVE_U_INT32_T /* Define to 1 if the system has the type `u_int8_t'. */ #undef HAVE_U_INT8_T +/* Define to 1 if you have the <validator/validator.h> header file. */ +#undef HAVE_VALIDATOR_VALIDATOR_H + /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the <vfork.h> header file. */ #undef HAVE_VFORK_H @@ -274,10 +286,13 @@ #undef SIZEOF_INT /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS +/* Support DNSSEC validation */ +#undef SUPPORT_DNSSEC + /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ #undef TIME_WITH_SYS_TIME /* Version number of package */ #undef VERSION diff -U 5 -r libspf2-1.2.5.orig/configure.ac libspf2-1.2.5/configure.ac --- libspf2-1.2.5.orig/configure.ac 2005-02-23 21:09:34.000000000 -0500 +++ libspf2-1.2.5/configure.ac 2008-04-25 14:14:38.000000000 -0400 @@ -90,39 +90,112 @@ AC_CHECK_HEADER(pthread.h, , [ echo "pthread.h is required to build this program." exit 1; ]) -dnl Moved to after header checks by Shevek -AC_ARG_WITH(bind, - [ --with-bind=DIR Find BIND resolver in DIR], - [AC_CHECK_FILE([$withval/include/bind/resolv.h], - [CFLAGS="$CFLAGS -I$withval/include/bind"], - [CFLAGS="$CFLAGS -I$withval/include"]) - LDFLAGS="$LDFLAGS -L$withval/lib -Wl,$rpath$withval/lib" - AC_CHECK_LIB([bind], [res_query], [LIBS="$LIBS -lbind"], - [AC_CHECK_LIB([resolv], - [res_query], - [LIBS="$LIBS -lresolv"], - [echo "cannot find resolver library"; exit 1;]) - ]) - ], - [dnl Have to include resolv.h as res_query is sometimes defined as a macro - AC_MSG_CHECKING([for res_query in -lresolv (with resolv.h if present)]) - saved_libs="$LIBS" - LIBS="-lresolv $LIBS" - AC_TRY_LINK([ - #ifdef HAVE_RESOLV_H - #include <resolv.h> - #endif], - [res_query(0,0,0,0,0)], - [AC_MSG_RESULT(yes) - have_res_query=yes], - [AC_MSG_RESULT(no) - LIBS="$saved_libs"]) - ]) - +AC_MSG_CHECKING(whether we need to support DNSSEC validation) +AC_ARG_ENABLE(dnssec-support, +[ --enable-dnssec-support Support DNSSEC validation.], + support_dnssec=yes) + +if test "x$support_dnssec" = "xyes"; then + + AC_MSG_RESULT(yes) + + dnl Check DNSSEC Validator library header + AC_CHECK_HEADERS([validator/validator.h]) + + dnl Check the openssl crypto library + AC_ARG_WITH(openssl, + [ --with-openssl=PATH Look for openssl in PATH/{lib,include}.], + if test "x$withval" != "xyes"; then + if test "x$withval" != x -a -d $withval/lib; then + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + if test "x$withval" != x -a -d $withval/include; then + CPPFLAGS="-I$withval/include $CPPFLAGS" + fi + fi + ) + AC_CHECK_LIB(crypto, RSA_verify, , [ + echo "the openssl crypto library is required to build this program." + exit 1; + ]) + + dnl Check libsres + AC_ARG_WITH(libsres, + [ --with-libsres=PATH Look for the libsres library in PATH], + if test "x$withval" != "xyes"; then + if test "x$withval" != x -a -d $withval; then + LDFLAGS="-L$withval $LDFLAGS" + AC_MSG_CHECKING(libsres) + AC_MSG_RESULT("$withval") + fi + fi + ) + + dnl Check Secure Resolver Library libsres + AC_CHECK_LIB(sres, query_send, , [ + echo "the secure resolver library is required to build this program." + echo "see http://dnssec-tools.sourceforge.net" + exit 1; + ], -L/usr/local/lib) + + dnl Check libval + AC_ARG_WITH(libval-threads, + [ --with-libval=PATH Look for the libval library in PATH], + if test "x$withval" != "xyes"; then + if test "x$withval" != x -a -d $withval; then + LDFLAGS="-L$withval $LDFLAGS" + AC_MSG_CHECKING(libval) + AC_MSG_RESULT("$withval") + fi + fi + ) + + dnl Check DNSSEC Validator library + AC_CHECK_LIB(val-threads, val_resolve_and_check, , [ + echo "the validator library is required to build this program." + echo "see http://dnssec-tools.sourceforge.net" + exit 1; + ], -lsres -lcrypto -lpthread -L/usr/local/lib) + + AC_DEFINE([SUPPORT_DNSSEC], [], [Support DNSSEC validation]) + +else + AC_MSG_RESULT(no) + + dnl Moved to after header checks by Shevek + AC_ARG_WITH(bind, + [ --with-bind=DIR Find BIND resolver in DIR], + [AC_CHECK_FILE([$withval/include/bind/resolv.h], + [CFLAGS="$CFLAGS -I$withval/include/bind"], + [CFLAGS="$CFLAGS -I$withval/include"]) + LDFLAGS="$LDFLAGS -L$withval/lib -Wl,$rpath$withval/lib" + AC_CHECK_LIB([bind], [res_query], [LIBS="$LIBS -lbind"], + [AC_CHECK_LIB([resolv], + [res_query], + [LIBS="$LIBS -lresolv"], + [echo "cannot find resolver library"; exit 1;]) + ]) + ], + [dnl Have to include resolv.h as res_query is sometimes defined as a macro + AC_MSG_CHECKING([for res_query in -lresolv (with resolv.h if present)]) + saved_libs="$LIBS" + LIBS="-lresolv $LIBS" + AC_TRY_LINK([ + #ifdef HAVE_RESOLV_H + #include <resolv.h> + #endif], + [res_query(0,0,0,0,0)], + [AC_MSG_RESULT(yes) + have_res_query=yes], + [AC_MSG_RESULT(no) + LIBS="$saved_libs"]) + ]) + +fi dnl [AC_CHECK_LIB(resolv, res_query)]) # Checks for libraries. diff -U 5 -r libspf2-1.2.5.orig/src/include/spf_dns.h libspf2-1.2.5/src/include/spf_dns.h --- libspf2-1.2.5.orig/src/include/spf_dns.h 2004-08-29 10:59:33.000000000 -0400 +++ libspf2-1.2.5/src/include/spf_dns.h 2008-04-25 14:14:38.000000000 -0400 @@ -96,10 +96,19 @@ #define HOST_NOT_FOUND 1 /* NXDOMAIN (authoritative answer)*/ #define TRY_AGAIN 2 /* SERVFAIL (no authoritative answer)*/ #define NO_RECOVERY 3 /* invalid/unimplmeneted query */ #define NO_DATA 4 /* host found, but no RR of req type*/ #endif + +#ifdef SUPPORT_DNSSEC +/* + * Additional Error code for DNSSEC validation + */ +#define DNSSEC_FAILURE 5 /* DNSSEC validation failed. */ +#include <netinet/in.h> +#endif + typedef int SPF_dns_stat_t; typedef struct SPF_dns_server_struct SPF_dns_server_t; #include "spf_request.h" diff -U 5 -r libspf2-1.2.5.orig/src/include/spf_response.h libspf2-1.2.5/src/include/spf_response.h --- libspf2-1.2.5.orig/src/include/spf_response.h 2005-02-21 21:33:02.000000000 -0500 +++ libspf2-1.2.5/src/include/spf_response.h 2008-04-25 14:14:38.000000000 -0400 @@ -147,10 +147,14 @@ , SPF_E_BAD_HOST_TLD /* Hostname has a missing or invalid TLD */ , SPF_E_MECH_AFTER_ALL /* Mechanisms found after the \"all:\" mechanism will be ignored */ , SPF_E_INCLUDE_RETURNED_NONE /* If an include recursive query returns none it's a perm error */ , SPF_E_RECURSIVE /* Recursive include */ + +#ifdef SUPPORT_DNSSEC +, SPF_E_DNSSEC_FAILURE /* DNSSEC validation failure */ +#endif } SPF_errcode_t; typedef struct SPF_error_struct { diff -U 5 -r libspf2-1.2.5.orig/src/libspf2/spf_dns_resolv.c libspf2-1.2.5/src/libspf2/spf_dns_resolv.c --- libspf2-1.2.5.orig/src/libspf2/spf_dns_resolv.c 2005-02-18 21:38:12.000000000 -0500 +++ libspf2-1.2.5/src/libspf2/spf_dns_resolv.c 2008-04-25 15:02:11.000000000 -0400 @@ -43,10 +43,14 @@ #ifdef HAVE_PTHREAD_H # include <pthread.h> #endif +#ifdef SUPPORT_DNSSEC +#include <validator/validator.h> +#endif + #include "spf.h" #include "spf_dns.h" #include "spf_internal.h" #include "spf_dns_internal.h" #include "spf_dns_resolv.h" @@ -59,20 +63,25 @@ struct __res_state res_state; #endif } SPF_dns_resolv_config_t; #endif +#ifdef SUPPORT_DNSSEC +# define SPF_h_errno h_errno +#else #if HAVE_DECL_RES_NINIT # if 0 # define SPF_h_errno spfhook->res_state.res_h_errno # else # define SPF_h_errno res_state->res_h_errno # endif #else # define SPF_h_errno h_errno #endif +#endif +#ifndef SUPPORT_DNSSEC static pthread_once_t res_state_control = PTHREAD_ONCE_INIT; static pthread_key_t res_state_key; static void SPF_dns_resolv_thread_term(void *arg) @@ -84,11 +93,11 @@ static void SPF_dns_resolv_init_key() { pthread_key_create(&res_state_key, SPF_dns_resolv_thread_term); } - +#endif #if 0 static inline SPF_dns_resolv_config_t *SPF_voidp2spfhook(void *hook) { return (SPF_dns_resolv_config_t *)hook; } static inline void *SPF_spfhook2voidp(SPF_dns_resolv_config_t *spfhook) @@ -99,11 +108,11 @@ static SPF_dns_rr_t * SPF_dns_resolv_lookup(SPF_dns_server_t *spf_dns_server, const char *domain, ns_type rr_type, int should_cache) { #if 0 - SPF_dns_resolv_config_t *spfhook; + SPF_dns_resolv_config_t *spfhook; #endif SPF_dns_rr_t *spfrr; int err; int i; @@ -128,20 +137,26 @@ int prio; int rdlen; const u_char *rdata, *rdata_end; +#ifndef SUPPORT_DNSSEC void *res_spec; struct __res_state *res_state; +#endif SPF_ASSERT_NOTNULL(spf_dns_server); #if 0 - spfhook = SPF_voidp2spfhook(spf_dns_server->hook); + spfhook = SPF_voidp2spfhook(spf_dns_server->hook); SPF_ASSERT_NOTNULL(spfhook); #endif +#ifdef SUPPORT_DNSSEC + val_status_t dnssec_status = VAL_INTERNAL_ERROR; +#endif +#ifndef SUPPORT_DNSSEC res_spec = pthread_getspecific(res_state_key); if (res_spec == NULL) { res_state = (struct __res_state *) malloc(sizeof(struct __res_state)); if (res_ninit(res_state) != 0) { @@ -150,21 +165,32 @@ pthread_setspecific(res_state_key, (void *)res_state); } else { res_state = (struct __res_state *)res_spec; } +#endif /* * try resolving the name */ +#ifdef SUPPORT_DNSSEC + + dns_len = val_res_query( NULL, domain, ns_c_in, rr_type, + response, sizeof(response), &dnssec_status ); + if (dns_len >= 0) { + SPF_debugf( "val_res_query() returned dnssec_status = %s\n", + p_val_status( dnssec_status ) ); + } +#else #if HAVE_DECL_RES_NINIT dns_len = res_nquery(res_state, domain, ns_c_in, rr_type, response, sizeof(response)); #else dns_len = res_query(domain, ns_c_in, rr_type, response, sizeof(response)); #endif +#endif if ( dns_len < 0 ) { /* This block returns unconditionally. */ if ( spf_dns_server->debug ) SPF_debugf( "query failed: err = %d %s (%d): %s", @@ -173,17 +199,37 @@ if ((SPF_h_errno == HOST_NOT_FOUND) && (spf_dns_server->layer_below != NULL)) { return SPF_dns_lookup(spf_dns_server->layer_below, domain, rr_type, should_cache); } +#ifdef SUPPORT_DNSSEC + if ( !val_istrusted(dnssec_status) ) { + if ( h_errno == NETDB_SUCCESS ) { + h_errno = DNSSEC_FAILURE; + } + return SPF_dns_rr_new_init( spf_dns_server, + domain, rr_type, 0, h_errno ); + } + else +#endif return SPF_dns_rr_new_init(spf_dns_server, domain, rr_type, 0, SPF_h_errno); } /* * initialize stuff */ +#ifdef SUPPORT_DNSSEC + if ( !val_istrusted(dnssec_status) ) { + if ( h_errno == NETDB_SUCCESS ) { + h_errno = DNSSEC_FAILURE; + } + spfrr = SPF_dns_rr_new_init( spf_dns_server, + domain, rr_type, 0, h_errno ); + } + else +#endif spfrr = SPF_dns_rr_new_init(spf_dns_server, domain, rr_type, 0, NETDB_SUCCESS); err = ns_initparse( response, dns_len, &ns_handle ); @@ -445,19 +491,27 @@ } if ( spfrr->num_rr == 0 ) spfrr->herrno = NO_DATA; +#ifdef SUPPORT_DNSSEC + if ( !val_istrusted(dnssec_status) ) { + if ( spfrr->herrno == NETDB_SUCCESS ) { + spfrr->herrno = DNSSEC_FAILURE; + } + } +#endif + return spfrr; } static void SPF_dns_resolv_free(SPF_dns_server_t *spf_dns_server) { #if 0 - SPF_dns_resolv_config_t *spfhook; + SPF_dns_resolv_config_t *spfhook; #endif SPF_ASSERT_NOTNULL(spf_dns_server); #if 0 @@ -481,14 +535,16 @@ SPF_dns_resolv_new(SPF_dns_server_t *layer_below, const char *name, int debug) { SPF_dns_server_t *spf_dns_server; #if 0 - SPF_dns_resolv_config_t *spfhook; + SPF_dns_resolv_config_t *spfhook; #endif +#ifndef SUPPORT_DNSSEC pthread_once(&res_state_control, SPF_dns_resolv_init_key); +#endif spf_dns_server = malloc(sizeof(SPF_dns_server_t)); if ( spf_dns_server == NULL ) return NULL; memset(spf_dns_server, 0, sizeof(SPF_dns_server_t)); diff -U 5 -r libspf2-1.2.5.orig/src/libspf2/spf_dns_rr.c libspf2-1.2.5/src/libspf2/spf_dns_rr.c --- libspf2-1.2.5.orig/src/libspf2/spf_dns_rr.c 2005-02-21 20:42:34.000000000 -0500 +++ libspf2-1.2.5/src/libspf2/spf_dns_rr.c 2008-04-25 14:14:38.000000000 -0400 @@ -43,11 +43,11 @@ SPF_dns_rr_t * SPF_dns_rr_new_nxdomain(SPF_dns_server_t *spf_dns_server, const char *domain) { return SPF_dns_rr_new_init(spf_dns_server, - domain, ns_t_any, 0, NXDOMAIN); + domain, ns_t_any, 0, HOST_NOT_FOUND); } SPF_dns_rr_t * SPF_dns_rr_new_init(SPF_dns_server_t *spf_dns_server, const char *domain, diff -U 5 -r libspf2-1.2.5.orig/src/libspf2/spf_get_exp.c libspf2-1.2.5/src/libspf2/spf_get_exp.c --- libspf2-1.2.5.orig/src/libspf2/spf_get_exp.c 2004-10-19 10:20:17.000000000 -0400 +++ libspf2-1.2.5/src/libspf2/spf_get_exp.c 2008-04-25 14:14:38.000000000 -0400 @@ -162,10 +162,17 @@ case TRY_AGAIN: RETURN_DEFAULT_EXP(); break; +#ifdef SUPPORT_DNSSEC + case DNSSEC_FAILURE: + SPF_response_add_warn(spf_response, SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the SPF (TXT) record of '%s'.", + *bufp); + break; +#endif case NETDB_SUCCESS: break; default: SPF_warning("unknown DNS lookup error code"); diff -U 5 -r libspf2-1.2.5.orig/src/libspf2/spf_interpret.c libspf2-1.2.5/src/libspf2/spf_interpret.c --- libspf2-1.2.5.orig/src/libspf2/spf_interpret.c 2005-02-21 22:41:27.000000000 -0500 +++ libspf2-1.2.5/src/libspf2/spf_interpret.c 2008-04-25 14:17:52.000000000 -0400 @@ -252,10 +252,18 @@ size_t buflen = SPF_RECEIVED_SPF_SIZE; char *buf_value; char *p, *p_end; +#ifdef SUPPORT_DNSSEC + int firstdnssecerr; + int i; + int num_errs; + SPF_error_t *err; + SPF_errcode_t errcode; + const char *errmsg = ""; +#endif SPF_ASSERT_NOTNULL(spf_response); spf_request = spf_response->spf_request; SPF_ASSERT_NOTNULL(spf_request); spf_server = spf_request->spf_server; SPF_ASSERT_NOTNULL(spf_server); @@ -326,10 +334,61 @@ p += snprintf( p, p_end - p, " problem=%s;", c_results.err_msg ); if ( p_end - p <= 0 ) break; } #endif +#ifdef SUPPORT_DNSSEC + /* add in the DNSSEC validation status */ + firstdnssecerr = 1; + num_errs = SPF_response_warnings( spf_response ); + for ( i = 0; i < num_errs; i++ ) + { + err = SPF_response_message( spf_response, i ); + if ( err ) + { + errcode = SPF_error_code ( err ); + if ( errcode == SPF_E_DNSSEC_FAILURE ) + { + errmsg = SPF_error_message( err ); + if ( errmsg == NULL ) errmsg = ""; + + if ( firstdnssecerr ) + { + p += snprintf( p, p_end - p, + " x-dnssec=\"fail (%s", + errmsg ); + firstdnssecerr = 0; + } + else + { + p += snprintf( p, p_end - p, ", %s", errmsg ); + } + } + if ( p_end - p <= 0 ) break; + } + } + + if ( p_end - p <= 0 ) break; + + if ( firstdnssecerr ) + { + if ( spf_response->result != SPF_RESULT_NONE ) + { + p += snprintf( p, p_end - p, " x-dnssec=\"pass\";" ); + } + else + { + p += snprintf( p, p_end - p, " x-dnssec=\"none\";" ); + } + } + else + { + p += snprintf( p, p_end - p, ")\";" ); + } + + if ( p_end - p <= 0 ) break; +#endif /* FIXME should the explanation string be included in the header? */ /* FIXME should the header be reformated to include line breaks? */ } while(0); @@ -745,10 +804,19 @@ SPF_dns_rr_free(rr_a); SPF_FREE_LOOKUP_DATA(); return DONE_TEMPERR(SPF_E_DNS_ERROR); /* REASON_MECH */ } +#ifdef SUPPORT_DNSSEC + if ( rr_a->herrno == DNSSEC_FAILURE ) + { + SPF_response_add_warn( spf_response, + SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the A record of '%s'.", + lookup ); + } +#endif for (i = 0; i < rr_a->num_rr; i++) { if ( rr_a->rr_type != fetch_ns_type ) continue; if (spf_request->client_ver == AF_INET) { @@ -785,10 +853,18 @@ SPF_dns_rr_free(rr_mx); SPF_FREE_LOOKUP_DATA(); return DONE_TEMPERR(SPF_E_DNS_ERROR); } +#ifdef SUPPORT_DNSSEC + if ( rr_mx->herrno == DNSSEC_FAILURE ) { + SPF_response_add_warn( spf_response, + SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the MX record of '%s'.", + lookup ); + } +#endif max_mx = rr_mx->num_rr; if ( max_mx > spf_server->max_dns_mx ) max_mx = spf_server->max_dns_mx; if ( max_mx > SPF_MAX_DNS_MX ) max_mx = SPF_MAX_DNS_MX; @@ -813,10 +889,24 @@ SPF_dns_rr_free(rr_a); SPF_FREE_LOOKUP_DATA(); return DONE_TEMPERR( SPF_E_DNS_ERROR ); } +#ifdef SUPPORT_DNSSEC + if ( rr_a->herrno == DNSSEC_FAILURE ) { + if ( spf_request->client_ver == AF_INET ) { + SPF_response_add_warn( spf_response, SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the A record of '%s'.", + rr_mx->rr[j]->mx ); + } + else { + SPF_response_add_warn( spf_response, SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the AAAA record of '%s'.", + rr_mx->rr[j]->mx ); + } + } +#endif for( i = 0; i < rr_a->num_rr; i++ ) { if ( rr_a->rr_type != fetch_ns_type ) continue; if ( spf_request->client_ver == AF_INET ) @@ -888,10 +978,17 @@ SPF_dns_rr_free(rr_a); SPF_FREE_LOOKUP_DATA(); return DONE_TEMPERR( SPF_E_DNS_ERROR ); } +#ifdef SUPPORT_DNSSEC + if( rr_a->herrno == DNSSEC_FAILURE ) { + SPF_response_add_warn( spf_response, SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the A record of '%s'.", + rr_ptr->rr[i]->ptr ); + } +#endif for( j = 0; j < rr_a->num_rr; j++ ) { if ( spf_server->debug ) { INET_NTOP( AF_INET, &rr_a->rr[j]->a.s_addr, ip4_buf, sizeof(ip4_buf)); SPF_debugf( "%d: %d: found %s", @@ -949,10 +1046,17 @@ SPF_dns_rr_free(rr_aaaa); SPF_FREE_LOOKUP_DATA(); return DONE_TEMPERR( SPF_E_DNS_ERROR ); } +#ifdef SUPPORT_DNSSEC + if( rr_aaaa->herrno == DNSSEC_FAILURE ) { + SPF_response_add_warn( spf_response, SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the AAAA record of '%s'.", + rr_ptr->rr[i]->ptr ); + } +#endif for( j = 0; j < rr_aaaa->num_rr; j++ ) { if ( spf_server->debug ) { INET_NTOP(AF_INET6, &rr_aaaa->rr[j]->aaaa.s6_addr, ip6_buf, sizeof(ip6_buf)); SPF_debugf( "%d: %d: found %s", @@ -1067,10 +1171,36 @@ /* Set everything up properly again. */ spf_response_subr = spf_response; spf_response = save_spf_response; save_spf_response = NULL; +#ifdef SUPPORT_DNSSEC + /* Copy any DNSSEC validation warnings from + * spf_response_subr to spf_response + */ + do { + int num_errs; + int i; + SPF_error_t *err; + SPF_errcode_t errcode; + char *errmsg; + + num_errs = SPF_response_warnings( spf_response_subr ); + for ( i = 0; i < num_errs; i++ ) { + err = SPF_response_message( spf_response_subr, i ); + if ( err ) { + errcode = SPF_error_code( err ); + if ( errcode == SPF_E_DNSSEC_FAILURE ) { + errmsg = ( char * ) SPF_error_message( err ); + SPF_response_add_warn( spf_response, + SPF_E_DNSSEC_FAILURE, + errmsg ); + } + } + } + } while (0); +#endif /* Rewrite according to prefix of include */ switch (SPF_response_result(spf_response_subr)) { case SPF_RESULT_PASS: /* Pass */ SPF_FREE_LOOKUP_DATA(); @@ -1150,10 +1280,17 @@ if( rr_a->herrno == TRY_AGAIN ) { SPF_FREE_LOOKUP_DATA(); return DONE_TEMPERR(SPF_E_DNS_ERROR); } +#ifdef SUPPORT_DNSSEC + if( rr_a->herrno == DNSSEC_FAILURE ) { + SPF_response_add_warn( spf_response, SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the A record of '%s'.", + lookup ); + } +#endif if ( rr_a->num_rr > 0 ) { SPF_FREE_LOOKUP_DATA(); return DONE_MECH(mech->prefix_type); } diff -U 5 -r libspf2-1.2.5.orig/src/libspf2/spf_server.c libspf2-1.2.5/src/libspf2/spf_server.c --- libspf2-1.2.5.orig/src/libspf2/spf_server.c 2005-02-18 22:52:58.000000000 -0500 +++ libspf2-1.2.5/src/libspf2/spf_server.c 2008-04-25 14:36:34.000000000 -0400 @@ -277,12 +277,11 @@ switch( rr_txt->herrno ) { case HOST_NOT_FOUND: SPF_dns_rr_free(rr_txt); spf_response->result = SPF_RESULT_NONE; spf_response->reason = SPF_REASON_FAILURE; - return SPF_response_add_error(spf_response, -SPF_E_NOT_SPF, + return SPF_response_add_error(spf_response, SPF_E_NOT_SPF, "Host '%s' not found.", domain); break; case NO_DATA: SPF_dns_rr_free(rr_txt); @@ -299,10 +298,17 @@ break; case NETDB_SUCCESS: break; +#ifdef SUPPORT_DNSSEC + case DNSSEC_FAILURE: + SPF_response_add_warn(spf_response, SPF_E_DNSSEC_FAILURE, + "DNSSEC validation failed for the SPF (TXT) record of '%s'.", + domain); + break; +#endif default: SPF_dns_rr_free(rr_txt); return SPF_response_add_error(spf_response, SPF_E_DNS_ERROR, "Unknown DNS failure for '%s': %d.", domain, rr_txt->herrno); diff -U 5 -r libspf2-1.2.5.orig/src/libspf2/spf_strerror.c libspf2-1.2.5/src/libspf2/spf_strerror.c --- libspf2-1.2.5.orig/src/libspf2/spf_strerror.c 2005-02-21 21:34:21.000000000 -0500 +++ libspf2-1.2.5/src/libspf2/spf_strerror.c 2008-04-25 14:14:38.000000000 -0400 @@ -160,10 +160,15 @@ case SPF_E_RECURSIVE: return "include: or redirect= caused unlimited recursion"; break; +#ifdef SUPPORT_DNSSEC + case SPF_E_DNSSEC_FAILURE: + return "DNSSEC Validation of SPF record failed"; + break; +#endif default: return "Unknown SPF error code"; break; }