Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > ccd6d20295ff28f0d90115b0394355f1 > files > 24

libdnssec-tools-devel-1.5-2mdv2010.0.i586.rpm

diff -U 5 -r libspf2-1.0.4.orig/config.h.in libspf2-1.0.4/config.h.in
--- libspf2-1.0.4.orig/config.h.in	2004-07-08 13:18:43.000000000 -0400
+++ libspf2-1.0.4/config.h.in	2008-04-25 13:49:03.000000000 -0400
@@ -35,25 +35,37 @@
 #undef HAVE_GETOPT_LONG_ONLY
 
 /* 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
 
 /* Define to 1 if you have the `nsl' library (-lnsl). */
 #undef HAVE_LIBNSL
 
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#undef HAVE_LIBPTHREAD
+
 /* Define to 1 if you have the `resolv' library (-lresolv). */
 #undef HAVE_LIBRESOLV
 
 /* 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 your system has a GNU libc compatible `malloc' function, and
    to 0 otherwise. */
 #undef HAVE_MALLOC
 
 /* Define to 1 if you have the <malloc.h> header file. */
@@ -175,10 +187,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
@@ -226,10 +241,13 @@
 #undef SETPGRP_VOID
 
 /* 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.0.4.orig/configure.ac libspf2-1.0.4/configure.ac
--- libspf2-1.0.4.orig/configure.ac	2004-07-07 07:55:34.000000000 -0400
+++ libspf2-1.0.4/configure.ac	2008-04-25 13:49:03.000000000 -0400
@@ -1,13 +1,13 @@
 #                                               -*- Autoconf -*-
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.59)
 AC_INIT(libspf2, 1.0.4, wayne@midwestcs.com)
-AM_INIT_AUTOMAKE(libspf2, $PACKAGE_VERSION)
 AC_CONFIG_SRCDIR([src/libspf2/spf.c])
 AC_CONFIG_AUX_DIR(config)
+AM_INIT_AUTOMAKE(libspf2, $PACKAGE_VERSION)
 AM_CONFIG_HEADER(config.h)
 
 # remember the version info for later
 
 major=`echo $PACKAGE_VERSION | sed 's/^\([[0-9]]*\)\.[[0-9]]*\.[[0-9]]*/\1/'`
@@ -81,33 +81,111 @@
      ]])
 AC_CHECK_HEADERS([fcntl.h malloc.h nmemory.h stddef.h inttypes.h stdlib.h string.h syslog.h unistd.h stdarg.h])
 AC_CHECK_HEADERS([libintl.h ])
 AC_CHECK_HEADERS([getopt.h ])
 
-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;])
-                ])
-        ], [AC_CHECK_LIB(resolv, res_query)])
+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 pthread library
+   AC_CHECK_LIB(pthread, pthread_rwlock_rdlock, , [
+	echo "the pthread library is required to build this program."
+	exit 1;
+   ])
+
+   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,
+	[  --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;])
+                   ])
+           ], [AC_CHECK_LIB(resolv, res_query)])
+
+fi
 
 # Checks for libraries.
 AC_CHECK_LIB(nsl, inet_pton)
 AC_CHECK_LIB(socket, socket)
 AC_CHECK_LIB(intl, gettext)
 
-
-
-
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
 AC_C_INLINE
 AC_TYPE_PID_T
 AC_TYPE_SIZE_T
diff -U 5 -r libspf2-1.0.4.orig/src/include/spf.h libspf2-1.0.4/src/include/spf.h
--- libspf2-1.0.4.orig/src/include/spf.h	2004-04-09 14:56:18.000000000 -0400
+++ libspf2-1.0.4/src/include/spf.h	2008-04-25 13:49:03.000000000 -0400
@@ -87,11 +87,13 @@
 #define SPF_E_NOT_CONFIG	25	/* Not configured		*/
 #define SPF_E_DNS_ERROR		26	/* DNS lookup failure		*/
 #define SPF_E_BAD_HOST_IP	27	/* Invalid hostname (possibly an IP address?) */
 #define SPF_E_BAD_HOST_TLD	28	/* Hostname has a missing or invalid TLD */
 #define SPF_E_MECH_AFTER_ALL	29	/* Mechanisms found after the \"all:\" mechanism will be ignored */
-
+#ifdef SUPPORT_DNSSEC
+#define SPF_E_DNSSEC_FAILURE    30      /* DNSSEC validation failed.    */
+#endif
 
 
 /* ********************************************************************* */
 
 /*
@@ -751,10 +753,24 @@
  * is a shared library and may differ from when the application was compiled.
  */
 void SPF_get_lib_version( int *major, int *minor, int *patch );
 
 
+#ifdef SUPPORT_DNSSEC
+/*
+ * Add an error message to list of error messages in the SPF_output_t struct.
+ */
+void SPF_add_output_err( SPF_output_t *output, const char *msg );
+
+
+/*
+ * Append the list of error messages from old_output to new_output.
+ */
+void SPF_copy_output_errs( SPF_output_t *old_output, SPF_output_t *new_output );
+#endif
+
+
 /*
  * Error messages and warnings generated internally by the library call
  * these routines.  By default, the messages go to stderr, but you can
  * define your own routines to deal with the messages instead.
  */
diff -U 5 -r libspf2-1.0.4.orig/src/include/spf_dns.h libspf2-1.0.4/src/include/spf_dns.h
--- libspf2-1.0.4.orig/src/include/spf_dns.h	2004-06-27 07:44:50.000000000 -0400
+++ libspf2-1.0.4/src/include/spf_dns.h	2008-04-25 13:49:03.000000000 -0400
@@ -98,12 +98,16 @@
 #define	NO_RECOVERY	3		/* invalid/unimplmeneted query	*/
 #define	NO_DATA		4		/* host found, but no RR of req type*/
 #endif
 typedef int SPF_dns_stat_t;
 
-
-
+#ifdef SUPPORT_DNSSEC
+/*
+ * Additional Error code(s) for DNSSEC validation
+ */
+#define DNSSEC_FAILURE  5               /* DNSSEC validation failed. */
+#endif
 
 /*
  * bundle up the info needed to use a dns method
  */
 
diff -U 5 -r libspf2-1.0.4.orig/src/include/spf_dns_resolv.h libspf2-1.0.4/src/include/spf_dns_resolv.h
--- libspf2-1.0.4.orig/src/include/spf_dns_resolv.h	2004-03-26 11:58:25.000000000 -0500
+++ libspf2-1.0.4/src/include/spf_dns_resolv.h	2008-04-25 14:02:51.000000000 -0400
@@ -38,10 +38,11 @@
 /*
  * if debugging is enabled, information about the results from
  * libresolv will be displayed.  This information is often not passed
  * on to (and not needed by) the higher level DNS layers.
  */
+
 SPF_dns_config_t SPF_dns_create_config_resolv( SPF_dns_config_t layer_below, int debug  );
 void SPF_dns_reset_config_resolv( SPF_dns_config_t spfdcid );
 void SPF_dns_destroy_config_resolv( SPF_dns_config_t spfdcid );
 
 
diff -U 5 -r libspf2-1.0.4.orig/src/libspf2/spf_dns_resolv.c libspf2-1.0.4/src/libspf2/spf_dns_resolv.c
--- libspf2-1.0.4.orig/src/libspf2/spf_dns_resolv.c	2004-06-27 07:44:50.000000000 -0400
+++ libspf2-1.0.4/src/libspf2/spf_dns_resolv.c	2008-04-25 14:07:34.000000000 -0400
@@ -39,10 +39,14 @@
 #endif
 #ifdef HAVE_NETDB_H
 # include <netdb.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"
@@ -55,11 +59,11 @@
 #if HAVE_DECL_RES_NINIT
     struct __res_state	res_state;
 #endif
 } SPF_dns_resolv_config_t; 
 
-#if HAVE_DECL_RES_NINIT
+#if HAVE_DECL_RES_NINIT && (! defined( SUPPORT_DNSSEC ))
 #define SPF_h_errno spfhook->res_state.res_h_errno
 #else
 #define SPF_h_errno h_errno
 #endif
 
@@ -99,11 +103,13 @@
     char	name_buf[ NS_MAXDNAME ];
     int		prio;
     
     int		rdlen;
     const u_char	*rdata, *rdata_end;
- 
+#ifdef SUPPORT_DNSSEC
+    val_status_t dnssec_status = VAL_INTERNAL_ERROR;
+#endif 
 
     /*
      * initialize stuff
      */
     spfrr = &spfhook->spfrr;
@@ -145,34 +151,67 @@
 
     
     /*
      * 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) 
+    {
+		if ( spfhook->debug )
+			SPF_debugf( "val_res_query returned dnssec_status = %s",
+				        p_val_status( dnssec_status ) );
+	}
+#else
 #if HAVE_DECL_RES_NINIT
     dns_len = res_nquery( &spfhook->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 )
     {
 	if ( spfhook->debug )
 	    SPF_debugf( "query failed: err = %d  %s (%d)",
 		    dns_len, hstrerror( SPF_h_errno ), SPF_h_errno );
 
+#ifdef SUPPORT_DNSSEC
+	if ( ( SPF_h_errno == NETDB_SUCCESS ) &&
+	    ( !val_istrusted(dnssec_status)) )
+	{
+	    SPF_h_errno = DNSSEC_FAILURE;
+	}
+
+	if ( spfrr->herrno == HOST_NOT_FOUND &&
+	     spfdic->layer_below )
+	{
+	    return SPF_dcid2spfdic( spfdic->layer_below )->lookup( spfdic->layer_below, domain, rr_type, should_cache );
+	}
+#else
 	if ( spfrr->herrno == HOST_NOT_FOUND && spfdic->layer_below )
 	    return SPF_dcid2spfdic( spfdic->layer_below )->lookup( spfdic->layer_below, domain, rr_type, should_cache );
 
+#endif
 	spfrr->herrno = SPF_h_errno;
 	return spfrr;
     }
-    else
+    else {
 	spfrr->herrno = NETDB_SUCCESS;
-	
     
+#ifdef SUPPORT_DNSSEC
+	if ( !val_istrusted(dnssec_status) )
+	{
+	    spfrr->herrno = DNSSEC_FAILURE;
+	}
+#endif
+    }
+
     err = ns_initparse( response, dns_len, &ns_handle );
 
     if ( err < 0 )			/* 0 or -1 */
     {
 	if ( spfhook->debug )
@@ -435,20 +474,29 @@
     }
 
     if ( spfrr->num_rr == 0 )
 	spfhook->spfrr.herrno = NO_DATA;
 
+#ifdef SUPPORT_DNSSEC
+    if ( !val_istrusted(dnssec_status) )
+    {
+	if ( spfrr->herrno == NETDB_SUCCESS )
+	{
+	    spfrr->herrno = DNSSEC_FAILURE;
+	}
+    }
+#endif
+
     return spfrr;
 }
 
 
 SPF_dns_config_t SPF_dns_create_config_resolv( SPF_dns_config_t layer_below, int debug )
 {
     SPF_dns_iconfig_t     *spfdic;
     SPF_dns_resolv_config_t *spfhook;
 
-    
     spfdic = malloc( sizeof( *spfdic ) );
     if ( spfdic == NULL )
 	return NULL;
 
     spfdic->hook = calloc( 1, sizeof( SPF_dns_resolv_config_t ) );
@@ -470,10 +518,11 @@
 
     spfhook->debug = debug;
     SPF_dns_reset_rr( &spfhook->spfrr );
     spfhook->spfrr.source = SPF_spfdic2dcid( spfdic );
 
+#ifndef SUPPORT_DNSSEC
 #if HAVE_DECL_RES_NINIT
     if ( res_ninit( &spfhook->res_state ) != 0 )
     {
 	free( spfdic );
 	return NULL;
@@ -483,10 +532,11 @@
     {
 	free( spfdic );
 	return NULL;
     }
 #endif
+#endif
 
     return SPF_spfdic2dcid( spfdic );
 }
 
 void SPF_dns_reset_config_resolv( SPF_dns_config_t spfdcid )
@@ -512,16 +562,17 @@
     {
 	SPF_dns_resolv_config_t	*spfhook = SPF_voidp2spfhook( spfdic->hook );
 
 	SPF_dns_destroy_rr_var( &spfhook->spfrr );
 
+#ifndef SUPPORT_DNSSEC
 #if HAVE_DECL_RES_NINIT
 	res_nclose( &spfhook->res_state );
 #else
 	res_close();
 #endif
-	
+#endif	
 	free( spfdic->hook );
     }
     
 
     if ( spfdic )
diff -U 5 -r libspf2-1.0.4.orig/src/libspf2/spf_eval_id.c libspf2-1.0.4/src/libspf2/spf_eval_id.c
--- libspf2-1.0.4.orig/src/libspf2/spf_eval_id.c	2004-07-08 13:24:55.000000000 -0400
+++ libspf2-1.0.4/src/libspf2/spf_eval_id.c	2008-04-25 13:49:03.000000000 -0400
@@ -202,10 +202,109 @@
     if ( buf ) free( buf );
     SPF_free_c_results( c_results );
     return *output;
 }
 
+#ifdef SUPPORT_DNSSEC
+/* Add a new error message to the end of the output->err_msgs list */
+void SPF_add_output_err( SPF_output_t *output,
+	 		 const char *msg )
+{
+    if ( ( output != NULL ) && ( msg != NULL ) )
+    {
+	char **new_err_msgs;
+	int i;
+
+	if ( output->num_errs < 0 )
+	{
+	    output->num_errs = 0;
+	}
+
+	(output->num_errs)++;
+
+	new_err_msgs = ( char ** ) malloc( output->num_errs * sizeof( char * ) );
+
+	if ( new_err_msgs == NULL )
+ 	{
+	    /* return E_NO_MEM? */
+	}
+
+	for ( i = 0; i < ( output->num_errs - 1 ); i++ )
+	{
+	    new_err_msgs[i] = output->err_msgs[i];
+	}
+
+	new_err_msgs[output->num_errs - 1] = strdup( msg );
+
+	if ( output->err_msgs ) free( output->err_msgs );
+	output->err_msgs = new_err_msgs;
+	
+	if ( output->err_msg ) free( output->err_msg );
+	output->err_msg = strdup( msg );
+	
+    }
+}
+
+/* Append the list of error messages from old_output to new_output */
+void SPF_copy_output_errs ( SPF_output_t *old_output, SPF_output_t *new_output )
+{
+    if ( ( old_output != NULL ) &&
+	 ( new_output != NULL ) &&
+	 ( old_output->num_errs > 0 ) ) {
+
+	char ** new_err_msgs;
+	int new_num_errs = old_output->num_errs;
+	int i;
+
+	if ( new_output->num_errs > 0 )
+	{
+	    new_num_errs += new_output->num_errs;
+	}
+	else
+	{
+	    new_output->num_errs = 0;
+	}
+
+	new_err_msgs = ( char ** ) malloc( new_num_errs * sizeof( char * ));
+	if ( new_err_msgs == NULL )
+	{
+	    /* return E_NO_MEM? */
+	}
+	
+	/* retain error messages in new_output */
+	for ( i = 0; i < new_output->num_errs; i++ )
+	{
+	    new_err_msgs[i] = new_output->err_msgs[i];
+	}
+
+	/* duplicate error messages in old_output */
+	for ( i = new_output->num_errs; i < new_num_errs; i++ )
+	{
+	    if ( old_output->err_msgs[i-new_output->num_errs] )
+	    {
+		new_err_msgs[i] =
+		    strdup( old_output->err_msgs[i-new_output->num_errs] );
+	    }
+	    else
+	    {
+		new_err_msgs[i] = strdup( "" );
+	    }
+	}
+
+	if ( new_output->err_msgs ) free( new_output->err_msgs );
+
+	new_output->err_msgs = new_err_msgs;
+	new_output->num_errs = new_num_errs;
+
+	if ( old_output->err_msg != NULL )
+	{
+	    if ( new_output->err_msg ) free( new_output->err_msg );
+	    new_output->err_msg = strdup( old_output->err_msg );
+	}
+    }
+}
+#endif
 
 SPF_output_t SPF_eval_id( SPF_config_t spfcid, SPF_id_t spfid,
 			    SPF_dns_config_t spfdcid,
 			  int use_local_policy, int use_helo,
 			  int *num_dns_mech )
@@ -399,10 +498,27 @@
 			rr_a->num_rr, lookup, rr_a->herrno );
 	    
 	    if( rr_a->herrno == TRY_AGAIN )
 		return done( SPF_RESULT_ERROR, SPF_REASON_MECH,
 			     SPF_E_DNS_ERROR );
+
+#ifdef SUPPORT_DNSSEC
+	    if ( rr_a->herrno == DNSSEC_FAILURE )
+	    {
+		char errstr[1024];
+
+	        if ( spfic->debug > 1 )
+		{
+		    SPF_debugf( "SPF_eval_id: spf_dns_lookup returned DNSSEC_FAILURE" );
+		}
+
+		snprintf( errstr, sizeof( errstr ),
+			  "DNSSEC Validation failed for A record of %s.",
+			  lookup );
+	        SPF_add_output_err( &output, errstr );
+	    }
+#endif
 	    
 	    for( i = 0; i < rr_a->num_rr; i++ )
 	    {
 		if ( rr_a->rr_type != fetch_ns_type )
 		    continue;
@@ -455,10 +571,27 @@
 	    
 	    if( rr_mx->herrno == TRY_AGAIN )
 		return done( SPF_RESULT_ERROR, SPF_REASON_MECH,
 			     SPF_E_DNS_ERROR );
 	    
+#ifdef SUPPORT_DNSSEC
+	    if ( rr_mx->herrno == DNSSEC_FAILURE )
+	    {
+		char errstr[1024];
+
+	        if ( spfic->debug > 1 )
+		{
+		    SPF_debugf( "SPF_eval_id: spf_dns_lookup returned DNSSEC_FAILURE." );
+		}
+
+		snprintf( errstr, sizeof( errstr ),
+			  "DNSSEC Validation failed for MX record of %s.",
+		  	  lookup );
+	        SPF_add_output_err( &output, errstr );
+	    }
+#endif
+	    
 	    max_mx = rr_mx->num_rr;
 	    if ( max_mx > spfic->max_dns_mx )
 		max_mx = spfic->max_dns_mx;
 	    if ( max_mx > SPF_MAX_DNS_MX )
 		max_mx = SPF_MAX_DNS_MX;
@@ -481,10 +614,27 @@
 			    j, rr_a->num_rr, rr_mx->rr[j]->mx, rr_a->herrno );
 		if( rr_a->herrno == TRY_AGAIN )
 		    return done( SPF_RESULT_ERROR, SPF_REASON_MECH,
 				 SPF_E_DNS_ERROR );
 	    
+#ifdef SUPPORT_DNSSEC
+		if ( rr_a->herrno == DNSSEC_FAILURE )
+		{
+		    char errstr[1024];
+		    
+		    if ( spfic->debug > 1 )
+		    {
+			SPF_debugf( "SPF_eval_id: spf_dns_lookup returned DNSSEC_FAILURE" );
+		    }
+		    
+		    snprintf( errstr, sizeof( errstr ),
+			      "DNSSEC Validation failed for A record of %s.",
+			      rr_mx->rr[j]->mx);
+		    SPF_add_output_err( &output, errstr );
+		}
+#endif
+	    
 		for( i = 0; i < rr_a->num_rr; i++ )
 		{
 		    if ( rr_a->rr_type != fetch_ns_type )
 			continue;
 
@@ -568,10 +718,27 @@
 			SPF_debugf( "%d:  found %d A records for %s  (herrno: %d)",
 				i, rr_a->num_rr, rr_ptr->rr[i]->ptr, rr_a->herrno );
 		    if( rr_a->herrno == TRY_AGAIN )
 			return done( SPF_RESULT_ERROR, SPF_REASON_MECH, SPF_E_DNS_ERROR );
 	    
+#ifdef SUPPORT_DNSSEC
+		    if ( rr_a->herrno == DNSSEC_FAILURE )
+		    {
+			char errstr[1024];
+			
+			if ( spfic->debug > 1 )
+			{
+			    SPF_debugf( "SPF_eval_id: spf_dns_lookup returned DNSSEC_FAILURE" );
+			}
+			
+			snprintf( errstr, sizeof( errstr ),
+				  "DNSSEC Validation failed for A record of %s.",
+				  rr_ptr->rr[i]->ptr );
+			SPF_add_output_err( &output, errstr );
+		    }
+#endif
+	    
 		    for( j = 0; j < rr_a->num_rr; j++ )
 		    {
 			if ( spfic->debug )
 			{
 			    char	ip4_buf[ INET_ADDRSTRLEN ];
@@ -652,10 +819,27 @@
 			SPF_debugf( "%d:  found %d AAAA records for %s  (herrno: %d)",
 				i, rr_aaaa->num_rr, rr_ptr->rr[i]->ptr, rr_aaaa->herrno );
 		    if( rr_aaaa->herrno == TRY_AGAIN )
 			return done( SPF_RESULT_ERROR, SPF_REASON_MECH, SPF_E_DNS_ERROR );
 	    
+#ifdef SUPPORT_DNSSEC
+		    if ( rr_aaaa->herrno == DNSSEC_FAILURE )
+		    {
+			char errstr[1024];
+			
+			if ( spfic->debug > 1 )
+			{
+			    SPF_debugf( "SPF_eval_id: spf_dns_lookup returned DNSSEC_FAILURE" );
+			}
+			
+			snprintf( errstr, sizeof( errstr ),
+			 	  "DNSSEC Validation failed for AAAA record of %s.",
+				  rr_ptr->rr[i]->ptr );
+			SPF_add_output_err( &output, errstr );
+		    }
+#endif
+	    
 		    for( j = 0; j < rr_aaaa->num_rr; j++ )
 		    {
 			if ( spfic->debug )
 			{
 			    char	ip6_buf[ INET6_ADDRSTRLEN ];
@@ -743,12 +927,27 @@
 		inc_out = SPF_eval_id( spfcid, c_results.spfid, spfdcid,
 				       FALSE, FALSE, num_dns_mech );
 
 		SPF_set_cur_dom( spfcid, save_cur_dom );
 		free( save_cur_dom );
+
+#ifdef SUPPORT_DNSSEC
+		if ( c_results.err == SPF_E_DNSSEC_FAILURE )
+		{
+		    SPF_add_output_err( &output, SPF_strerror( c_results.err ) );
+		}
+#endif
+
 		SPF_reset_c_results( &c_results );
 
+#ifdef SUPPORT_DNSSEC
+		if ( inc_out.num_errs > 0 )
+		{
+		    SPF_copy_output_errs( &inc_out, &output );
+		}
+#endif
+
 		if ( spfic->debug > 0 )
 		    SPF_debugf( "include:  executed SPF record:  %s  result: %s  reason: %s",
 			    SPF_strerror( inc_out.err ),
 			    SPF_strresult( inc_out.result ),
 			    SPF_strreason( inc_out.reason ) );
@@ -785,10 +984,29 @@
 		    break;
 		}
 	    }
 	    else if ( err == SPF_E_DNS_ERROR )
 		return done( SPF_RESULT_ERROR, SPF_REASON_NONE, err );
+
+#ifdef SUPPORT_DNSSEC
+	    else if ( err == SPF_E_DNSSEC_FAILURE )
+	    {
+		if ( c_results.err_msg )
+		{
+		    output.err_msg = strdup( c_results.err_msg );
+		    SPF_add_output_err( &output, c_results.err_msg );
+		}
+		else
+		{
+		    SPF_add_output_err( &output,
+ 					SPF_strerror( SPF_E_DNSSEC_FAILURE ) );
+		}
+		return done( SPF_RESULT_UNKNOWN, SPF_REASON_NONE,
+			     SPF_E_DNSSEC_FAILURE );
+	    }
+#endif
+
 	    else
 		return done( SPF_RESULT_UNKNOWN, SPF_REASON_NONE, err );
 	    
 
 	    
@@ -827,10 +1045,27 @@
 	    
 	    if( rr_a->herrno == TRY_AGAIN )
 		return done( SPF_RESULT_ERROR, SPF_REASON_MECH, SPF_E_DNS_ERROR );
 	    
 	    
+#ifdef SUPPORT_DNSSEC
+	    if ( rr_a->herrno == DNSSEC_FAILURE )
+	    {
+		char errstr[1024];
+
+	        if ( spfic->debug > 1 )
+		{
+		    SPF_debugf( "SPF_eval_id: spf_dns_lookup returned DNSSEC_FAILURE" );
+		}
+
+		snprintf( errstr, sizeof( errstr ),
+			  "DNSSEC Validation failed for A record of %s.",
+			  lookup);
+	        SPF_add_output_err( &output, errstr );
+	    }
+#endif
+	    
 	    if ( rr_a->num_rr > 0 )
 		return done( mech->prefix_type, SPF_REASON_MECH, SPF_E_SUCCESS );
 	    
 	    break;
 	    
@@ -874,12 +1109,27 @@
 		 */
 		
 		SPF_set_cur_dom( spfcid, lookup );
 		inc_out = SPF_eval_id( spfcid, c_results.spfid, spfdcid,
 				       TRUE, FALSE, num_dns_mech );
+
+#ifdef SUPPORT_DNSSEC
+		if ( c_results.err == SPF_E_DNSSEC_FAILURE )
+		{
+		    SPF_add_output_err( &output, SPF_strerror( c_results.err ) );
+		}
+#endif
+
 		SPF_reset_c_results( &c_results );
 
+#ifdef SUPPORT_DNSSEC
+		if ( inc_out.num_errs > 0 )
+		{
+		    SPF_copy_output_errs( &inc_out, &output );
+		}
+#endif
+
 		if ( spfic->debug > 0 )
 		    SPF_debugf( "redirect:  executed SPF record:  %s  result: %s  reason: %s",
 			    SPF_strerror( inc_out.err ),
 			    SPF_strresult( inc_out.result ),
 			    SPF_strreason( inc_out.reason ) );
@@ -889,10 +1139,29 @@
 		
 		return output;
 	    }
 	    else if ( err == SPF_E_DNS_ERROR )
 		return done( SPF_RESULT_ERROR, SPF_REASON_NONE, err );
+
+#ifdef SUPPORT_DNSSEC
+	    else if ( err == SPF_E_DNSSEC_FAILURE )
+	    {
+		if ( c_results.err_msg )
+		{
+		    output.err_msg = strdup( c_results.err_msg );
+		    SPF_add_output_err( &output, c_results.err_msg );
+		}
+		else
+		{
+		    SPF_add_output_err( &output,
+					SPF_strerror( SPF_E_DNSSEC_FAILURE ) );
+		}
+		return done( SPF_RESULT_UNKNOWN, SPF_REASON_NONE,
+			     SPF_E_DNSSEC_FAILURE );
+	    }
+#endif
+
 	    else
 		return done( mech->prefix_type, SPF_REASON_MECH, err );
 	    
 	    break;
 
diff -U 5 -r libspf2-1.0.4.orig/src/libspf2/spf_get_spf.c libspf2-1.0.4/src/libspf2/spf_get_spf.c
--- libspf2-1.0.4.orig/src/libspf2/spf_get_spf.c	2004-06-22 18:38:55.000000000 -0400
+++ libspf2-1.0.4/src/libspf2/spf_get_spf.c	2008-04-25 13:49:03.000000000 -0400
@@ -48,11 +48,14 @@
     SPF_dns_rr_t	*rr_txt;
     
     int		i;
     SPF_err_t	err;
     int		num_found;
-    
+
+#ifdef SUPPORT_DNSSEC
+    SPF_err_t   dnssec_err;
+#endif
 
     if ( spfcid == NULL )
 	SPF_error( "spfcid is null" );
 
     if ( spfdcid == NULL )
@@ -73,10 +76,14 @@
     if ( spfdic->get_spf )
 	return spfdic->get_spf( spfcid, spfdcid, domain, c_results );
 
     rr_txt = SPF_dns_lookup( spfdcid, domain, ns_t_txt, TRUE );
 
+#ifdef SUPPORT_DNSSEC
+    dnssec_err = SPF_E_SUCCESS;
+#endif
+
     switch( rr_txt->herrno )
     {
     case HOST_NOT_FOUND:
     case NO_DATA:
 	c_results->err = SPF_E_NOT_SPF;
@@ -89,10 +96,29 @@
 	break;
 
     case NETDB_SUCCESS:
 	break;
 
+#ifdef SUPPORT_DNSSEC
+    case DNSSEC_FAILURE:
+        if ( spfic->debug > 1 )
+	{
+	  SPF_debugf( "SPF_get_spf: spf_dns_lookup returned DNSSEC_FAILURE" );
+	}
+        dnssec_err = SPF_E_DNSSEC_FAILURE;
+        c_results->err = SPF_E_DNSSEC_FAILURE;
+	{
+	    char errmsgbuf[1024];
+	    bzero( errmsgbuf, 1024 );
+	    snprintf( errmsgbuf, 1023,
+		      "DNSSEC validation failed for the SPF (TXT) record of '%s'.",
+		     domain );
+	    c_results->err_msg = strdup( errmsgbuf );
+	}
+	break;
+#endif
+
     default:
 	c_results->err = SPF_E_DNS_ERROR;
 	return SPF_E_DNS_ERROR;
 	break;
     }
@@ -131,7 +157,34 @@
 
 	if ( err == SPF_E_SUCCESS )	/* FIXME:  support multiple versions */
 	    break;
     }
 
+#ifdef SUPPORT_DNSSEC
+    if ( dnssec_err == SPF_E_DNSSEC_FAILURE )
+    {
+        if ( c_results->err_msg != NULL )
+	{
+	    free( c_results->err_msg ); /* Should we retain old err_msg? Is there one? */
+	}
+
+	{
+	    char errmsgbuf[1024];
+	    bzero( errmsgbuf, 1024 );
+	    snprintf( errmsgbuf, 1023,
+	 	      "DNSSEC validation failed for the SPF (TXT) record of '%s'.",
+		     domain );
+	    c_results->err_msg = strdup( errmsgbuf );
+	}
+
+        if ( ( spfic->debug > 1 ) && ( c_results->err_msg != NULL ) )
+ 	{
+	    SPF_debugf( "SPF_get_spf: setting c_results->err_msg to '%s'",
+			c_results->err_msg );
+	}
+
+	c_results->err = dnssec_err;
+    }
+#endif
+
     return err;
 }
diff -U 5 -r libspf2-1.0.4.orig/src/libspf2/spf_result.c libspf2-1.0.4/src/libspf2/spf_result.c
--- libspf2-1.0.4.orig/src/libspf2/spf_result.c	2004-06-22 18:39:13.000000000 -0400
+++ libspf2-1.0.4/src/libspf2/spf_result.c	2008-04-25 13:49:03.000000000 -0400
@@ -68,14 +68,18 @@
 	{
 	    snprintf( p, p_end - p, " : Reason: %s",
 		      SPF_strreason( output.reason ) );
 	}
 	    
-    } else {
+    } else
+    {
 	if ( spfic->debug > 0 )
-	    printf( "Error formatting explanation string:  %s\n",
-		    SPF_strerror( err ) );
+	{
+	    SPF_print( "Error formatting explanation string: " );
+	    SPF_print( SPF_strerror( err ) );
+	    SPF_print( "\n" );
+	}
 
 	snprintf( p, p_end - p, " : %s", SPF_strerror( err ) );
     }
 
     return buf;
@@ -221,10 +225,14 @@
     char	*buf;
     size_t	buf_len = SPF_RECEIVED_SPF_SIZE;
     
     char	*p, *p_end;
 
+#ifdef SUPPORT_DNSSEC
+    int         dnssecerr;
+#endif
+
 
     buf = malloc( buf_len );
     if ( buf == NULL )
 	return buf;
     
@@ -275,20 +283,135 @@
 	if ( p_end - p <= 0 ) return buf;
     }
     
 
     /* add in the optional compiler error keyword */
+#ifdef SUPPORT_DNSSEC
+    if ( ( output.err_msg != NULL ) || ( output.num_errs > 0 ) )
+#else
     if ( output.err_msg != NULL )
+#endif
     {
+#ifdef SUPPORT_DNSSEC
+	int i;
+	int first=1;
+
+	if ( ( output.err_msg != NULL ) &&
+	     ( strstr( output.err_msg, "DNSSEC" ) == NULL ) )
+	{
+	    p += snprintf( p, p_end - p, " problem=%s", output.err_msg );
+	    first=0;
+
+	    if ( p_end - p <= 0 ) return buf;
+	}
+
+	/* Add other error messages */
+	for ( i = 0; i < output.num_errs; i++ ) {
+	    if ( ( output.err_msgs[i] != NULL ) &&
+                 ( strstr( output.err_msgs[i], "DNSSEC" ) == NULL ) &&
+                 ( ( output.err_msg == NULL) ||
+		   ( strcmp( output.err_msgs[i], output.err_msg ) != 0 ) ) )
+	    {
+		if ( first == 1 )
+		{
+		    p += snprintf( p, p_end - p, " problem=%s",
+				   output.err_msgs[i] );
+		    first = 0;
+		}
+		else
+		{
+		    p += snprintf( p, p_end - p, ", %s", output.err_msgs[i] );
+		}
+
+		if ( p_end - p <= 0 ) return buf;
+	    }
+	}
+
+	if ( !first )
+	{
+	    p += snprintf( p, p_end - p, ";" );
+	}
+#else
 	p += snprintf( p, p_end - p, " problem=%s;", output.err_msg );
+#endif
+	
 	if ( p_end - p <= 0 ) return buf;
     }
+#ifdef SUPPORT_DNSSEC
+    else if ( ( c_results.err_msg != NULL ) &&
+	      ( strstr( c_results.err_msg, "DNSSEC" ) == NULL ) )
+#else
     else if ( c_results.err_msg != NULL )
+#endif
     {
 	p += snprintf( p, p_end - p, " problem=%s;", c_results.err_msg );
 	if ( p_end - p <= 0 ) return buf;
     }
+
+#ifdef SUPPORT_DNSSEC
+    /* add in the x-dnssec keyword */
+    dnssecerr = 0;
+    if ( ( output.err_msg != NULL ) || ( output.num_errs > 0 ) )
+    {
+	int i;
+	int first=1;
+
+	if ( ( output.err_msg != NULL ) &&
+	     ( strstr( output.err_msg, "DNSSEC" ) != NULL ) )
+	{
+	    p += snprintf( p, p_end - p, " x-dnssec=\"fail (%s",
+			   output.err_msg );
+	    first=0;
+	    dnssecerr = 1;
+	    if ( p_end - p <= 0 ) return buf;
+	}
+
+	/* Add other error messages */
+	for ( i = 0; i < output.num_errs; i++ )
+	{
+	    if ( ( output.err_msgs[i] != NULL ) &&
+                 ( strstr( output.err_msgs[i], "DNSSEC" ) != NULL ) &&
+                 ( ( output.err_msg == NULL) ||
+		   ( strcmp( output.err_msgs[i], output.err_msg ) != 0 ) ) )
+	    {
+		dnssecerr = 1;
+		if ( first == 1 )
+		{
+		    p += snprintf( p, p_end - p, " x-dnssec=\"fail (%s",
+				   output.err_msgs[i] );
+		    first = 0;
+		}
+		else
+		{
+		    p += snprintf( p, p_end - p, ", %s", output.err_msgs[i] );
+		}
+
+		if ( p_end - p <= 0 ) return buf;
+	    }
+	}
+
+	if ( !first ) {
+	    p += snprintf( p, p_end - p, ")\";" );
+	}
+	
+	if ( p_end - p <= 0 ) return buf;
+    }
+    else if ( ( c_results.err_msg != NULL ) &&
+	      ( strstr( c_results.err_msg, "DNSSEC" ) != NULL ) )
+    {
+	p += snprintf( p, p_end - p, " x-dnssec=\"fail (%s)\";",
+		       c_results.err_msg );
+	if ( p_end - p <= 0 ) return buf;
+    }
+
+    if ( ( !dnssecerr ) && ( output.result != SPF_RESULT_NONE ) )
+    {
+	p += snprintf( p, p_end - p, " x-dnssec=\"pass\";" );
+
+	if ( p_end - p <= 0 ) return buf;
+    }
+#endif
     
     /* FIXME  should the explanation string be included in the header? */
 
     /* FIXME  should the header be reformated to include line breaks? */
 
@@ -377,11 +500,16 @@
 		output.result = SPF_RESULT_UNKNOWN;
 	    output.reason = SPF_REASON_NONE;
 	    output.err = err;
 	    if ( output.err_msg ) free( output.err_msg );
 	    if ( c_results.err_msg )
+            {
 		output.err_msg = strdup( c_results.err_msg );
+#ifdef SUPPORT_DNSSEC
+		SPF_add_output_err( &output, c_results.err_msg );
+#endif
+	    }
 	    else
 		output.err_msg = NULL;
 	
 	} else {
 	    
@@ -392,14 +520,38 @@
 	    output = SPF_eval_id( spfcid, c_results.spfid, spfdcid,
 				  TRUE, FALSE, NULL );
 	    if ( spfic->debug > 0 )
 		SPF_print( c_results.spfid );
 
+#ifdef SUPPORT_DNSSEC
+	    if ( c_results.err == SPF_E_DNSSEC_FAILURE )
+	    {
+		SPF_add_output_err( &output, SPF_strerror( c_results.err ) );
+	    }
+#endif
 	}
 	
     }
     
+#ifdef SUPPORT_DNSSEC
+    if ( spfic->debug > 1 )
+    {
+        if ( output.num_errs > 0 )
+	{
+	    int i;
+	    SPF_debugf( "SPF_result: err_msgs = " );
+	    for ( i = 0; i < output.num_errs; i++ )
+	    {
+		SPF_debugf( "%s;",output.err_msgs[i] );
+	    }
+        }
+        else
+	{
+	    SPF_debugf( "SPF_result: err_msgs = None" );
+        }
+    }
+#endif
 
     SPF_result_comments( spfcid, spfdcid, c_results, &output );
 
     SPF_free_c_results( &c_results );
     return output;
@@ -448,11 +600,17 @@
 		output.result = SPF_RESULT_UNKNOWN;
 	    output.reason = SPF_REASON_NONE;
 	    output.err = err;
 	    if ( output.err_msg ) free( output.err_msg );
 	    if ( c_results.err_msg )
+	    {
 		output.err_msg = strdup( c_results.err_msg );
+
+#ifdef SUPPORT_DNSSEC
+		SPF_add_output_err( &output, c_results.err_msg );
+#endif
+	    }
 	    else
 		output.err_msg = NULL;
 	
 	} else {
 	    
@@ -463,14 +621,38 @@
 	    output = SPF_eval_id( spfcid, c_results.spfid, spfdcid,
 				  TRUE, TRUE, NULL );
 	    if ( spfic->debug > 0 )
 		SPF_print( c_results.spfid );
 
+#ifdef SUPPORT_DNSSEC
+	    if ( c_results.err == SPF_E_DNSSEC_FAILURE )
+	    {
+		SPF_add_output_err( &output, SPF_strerror( c_results.err ) );
+	    }
+#endif
 	}
 	
     }
     
+#ifdef SUPPORT_DNSSEC
+    if ( spfic->debug > 1 )
+    {
+        if ( output.num_errs > 0 )
+	{
+	    int i;
+	    SPF_debugf( "SPF_result_helo: err_msgs = " );
+	    for ( i = 0; i < output.num_errs; i++ )
+	    {
+		SPF_debugf( "%s;", output.err_msgs[i] );
+	    }
+        }
+        else
+	{
+	    SPF_debugf( "SPF_result_helo: err_msgs = None" );
+        }
+    }
+#endif
 
     SPF_result_comments( spfcid, spfdcid, c_results, &output );
 
     SPF_free_c_results( &c_results );
     return output;
diff -U 5 -r libspf2-1.0.4.orig/src/libspf2/spf_strerror.c libspf2-1.0.4/src/libspf2/spf_strerror.c
--- libspf2-1.0.4.orig/src/libspf2/spf_strerror.c	2004-06-22 18:39:16.000000000 -0400
+++ libspf2-1.0.4/src/libspf2/spf_strerror.c	2008-04-25 13:49:03.000000000 -0400
@@ -150,11 +150,17 @@
 	break;
 	    
     case SPF_E_MECH_AFTER_ALL:
 	return "Mechanisms found after the \"all:\" mechanism will be ignored";
 	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;
     }