diff -U 5 -Nar sendmail-8.14.1.orig/devtools/Site/site.config.m4 sendmail-8.14.1/devtools/Site/site.config.m4
--- sendmail-8.14.1.orig/devtools/Site/site.config.m4	1969-12-31 19:00:00.000000000 -0500
+++ sendmail-8.14.1/devtools/Site/site.config.m4	2008-05-12 10:05:55.000000000 -0400
@@ -0,0 +1,3 @@
+APPENDDEF(`confENVDEF', `-DSUPPORT_DNSSEC=1 -DMILTER')
+define(`confLIBSEARCH', `db 44bsd')
+APPENDDEF(`confLIBS', `-lsres -lval-threads -lcrypto -lpthread')
diff -U 5 -Nar sendmail-8.14.1.orig/libmilter/sm_gethost.c sendmail-8.14.1/libmilter/sm_gethost.c
--- sendmail-8.14.1.orig/libmilter/sm_gethost.c	2004-08-20 17:12:37.000000000 -0400
+++ sendmail-8.14.1/libmilter/sm_gethost.c	2008-05-12 10:09:42.000000000 -0400
@@ -15,10 +15,49 @@
 #if NETINET || NETINET6
 # include <arpa/inet.h>
 #endif /* NETINET || NETINET6 */
 #include "libmilter.h"
 
+#if SUPPORT_DNSSEC
+# include <validator/validator.h>
+#endif /* SUPPORT_DNSSEC */
+
+/*
+**  MI_VAL_GETHOSTBYNAME -- wrapper for gethostbyname with support for
+**                          DNSSEC validation
+**
+**      Parameters:
+**              name -- a host name, or an IPv4 address in standard dot
+**                      notation, or an IPv6 address in colon (and possibly
+**                      dot) notation.
+**
+**      Returns:
+**              NULL, if there was an error
+**              A non-NULL value of type struct hostent*, if no error occurs
+**
+*/
+
+static struct hostent *
+mi_val_gethostbyname(name)
+        char *name;
+{
+	struct hostent *h;
+#if SUPPORT_DNSSEC
+	val_status_t dnssec_status = VAL_INTERNAL_ERROR;
+	h = val_gethostbyname(NULL, name, &dnssec_status);
+	if (h && !val_istrusted(dnssec_status)) {
+		h = NULL;
+		h_errno = NO_DATA; 
+        
+	}
+#else /* SUPPORT_DNSSEC */
+	h = gethostbyname(name);
+#endif /* SUPPORT_DNSSEC */
+
+	return h;
+}
+
 /*
 **  MI_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
 **
 **	Some operating systems have wierd problems with the gethostbyXXX
 **	routines.  For example, Solaris versions at least through 2.3
@@ -57,17 +96,19 @@
 		/* From RFC2133, section 6.1 */
 		resv6 = bitset(RES_USE_INET6, _res.options);
 		_res.options |= RES_USE_INET6;
 	}
 	SM_SET_H_ERRNO(0);
-	h = gethostbyname(name);
+	h = mi_val_gethostbyname(name);
 	if (family == AF_INET6 && !resv6)
 		_res.options &= ~RES_USE_INET6;
 	*err = h_errno;
 	return h;
 }
+#endif /* NEEDSGETIPNODE && NETINET6 */
 
+#if (NEEDSGETIPNODE && NETINET6) 
 void
 freehostent(h)
 	struct hostent *h;
 {
 	/*
@@ -75,11 +116,11 @@
 	**  they probably don't have the free routine either.
 	*/
 
 	return;
 }
-#endif /* NEEDSGETIPNODE && NETINET6 */
+#endif /* (NEEDSGETIPNODE && NETINET6) */
 
 struct hostent *
 mi_gethostbyname(name, family)
 	char *name;
 	int family;
@@ -108,11 +149,11 @@
 	flags &= ~AI_ADDRCONFIG;
 #  endif /* ADDRCONFIG_IS_BROKEN */
 	h = getipnodebyname(name, family, flags, &err);
 	SM_SET_H_ERRNO(err);
 # else /* NETINET6 */
-	h = gethostbyname(name);
+	h = mi_val_gethostbyname(name);
 # endif /* NETINET6 */
 
 #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
 	return h;
 }
diff -U 5 -Nar sendmail-8.14.1.orig/sendmail/conf.c sendmail-8.14.1/sendmail/conf.c
--- sendmail-8.14.1.orig/sendmail/conf.c	2007-04-03 17:32:29.000000000 -0400
+++ sendmail-8.14.1/sendmail/conf.c	2008-05-12 10:09:51.000000000 -0400
@@ -4165,10 +4165,51 @@
 	}
 	return NULL;
 }
 
 #endif /* NEEDSTRSTR */
+
+#if SUPPORT_DNSSEC
+# include <validator/validator.h>
+#endif /* SUPPORT_DNSSEC */
+
+/*
+**  SM_VAL_GETHOSTBYNAME -- wrapper for gethostbyname with support for
+**                          DNSSEC validation
+**
+**      Parameters:
+**              name -- a host name, or an IPv4 address in standard dot
+**                      notation, or an IPv6 address in colon (and possibly
+**                      dot) notation.
+**
+**      Returns:
+**              NULL, if there was an error
+**              A non-NULL value of type struct hostent*, if no error occurs
+**
+*/
+
+static struct hostent *
+sm_val_gethostbyname(name)
+        char *name;
+{
+	struct hostent *h;
+
+#if SUPPORT_DNSSEC
+	val_status_t dnssec_status = VAL_INTERNAL_ERROR;
+	h = val_gethostbyname(NULL, name, &dnssec_status);
+	if (h && !val_istrusted(dnssec_status)) {
+		h = NULL;
+		h_errno = NO_DATA;
+        
+	}
+#else /* SUPPORT_DNSSEC */
+	h = gethostbyname(name);
+#endif /* SUPPORT_DNSSEC */
+
+	return h;
+}
+
 /*
 **  SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
 **
 **	Some operating systems have wierd problems with the gethostbyXXX
 **	routines.  For example, Solaris versions at least through 2.3
@@ -4208,11 +4249,11 @@
 		/* From RFC2133, section 6.1 */
 		resv6 = bitset(RES_USE_INET6, _res.options);
 		_res.options |= RES_USE_INET6;
 	}
 	SM_SET_H_ERRNO(0);
-	h = gethostbyname(name);
+	h = sm_val_gethostbyname(name);
 	if (!resv6)
 		_res.options &= ~RES_USE_INET6;
 	*err = h_errno;
 	return h;
 }
@@ -4229,11 +4270,13 @@
 	SM_SET_H_ERRNO(0);
 	h = gethostbyaddr(addr, len, family);
 	*err = h_errno;
 	return h;
 }
+#endif /* NETINET6 && NEEDSGETIPNODE */
 
+#if (NETINET6 && NEEDSGETIPNODE) 
 void
 freehostent(h)
 	struct hostent *h;
 {
 	/*
@@ -4241,11 +4284,11 @@
 	**  they probably don't have the free routine either.
 	*/
 
 	return;
 }
-#endif /* NETINET6 && NEEDSGETIPNODE */
+#endif /* (NETINET6 && NEEDSGETIPNODE) */
 
 struct hostent *
 sm_gethostbyname(name, family)
 	char *name;
 	int family;
@@ -4288,11 +4331,11 @@
 	flags &= ~AI_ADDRCONFIG;
 #  endif /* ADDRCONFIG_IS_BROKEN */
 	h = getipnodebyname(name, family, flags, &err);
 	SM_SET_H_ERRNO(err);
 # else /* NETINET6 */
-	h = gethostbyname(name);
+	h = sm_val_gethostbyname(name);
 # endif /* NETINET6 */
 
 	save_errno = errno;
 	if (h == NULL)
 	{
@@ -4328,11 +4371,11 @@
 # if NETINET6
 				h = getipnodebyname(hbuf, family, flags, &err);
 				SM_SET_H_ERRNO(err);
 				save_errno = errno;
 # else /* NETINET6 */
-				h = gethostbyname(hbuf);
+				h = sm_val_gethostbyname(hbuf);
 				save_errno = errno;
 # endif /* NETINET6 */
 			}
 		}
 	}
@@ -4635,13 +4678,13 @@
 			if (tTd(0, 43))
 				sm_dprintf("\ta.k.a.: %s (already in $=w)\n",
 					*ha);
 		}
 	}
-#if NETINET6
+#if NETINET6 
 	freehostent(hp);
-#endif /* NETINET6 */
+#endif /* NETINET6 || SUPPORT_DNSSEC */
 	return 0;
 }
 /*
 **  LOAD_IF_NAMES -- load interface-specific names into $=w
 **
diff -U 5 -Nar sendmail-8.14.1.orig/sendmail/domain.c sendmail-8.14.1/sendmail/domain.c
--- sendmail-8.14.1.orig/sendmail/domain.c	2006-12-18 20:15:07.000000000 -0500
+++ sendmail-8.14.1/sendmail/domain.c	2008-05-12 10:12:42.000000000 -0400
@@ -24,6 +24,9 @@
 
 # include <arpa/inet.h>
 
+# if SUPPORT_DNSSEC
+#  include <validator/validator.h>
+# endif /* SUPPORT_DNSSEC */
 
 /*
 **  The standard udp packet size PACKETSZ (512) is not sufficient for some
@@ -224,7 +227,11 @@
 	char *fallbackMX = FallbackMX;
 	bool trycanon = false;
 	unsigned short *prefs;
+#if SUPPORT_DNSSEC
+	int (*resfunc) __P((val_context_t *, const char *, int, int, u_char *, int, val_status_t *));
+#else
 	int (*resfunc) __P((const char *, int, int, u_char *, int));
+#endif
 	unsigned short prefer[MAXMXHOSTS];
 	int weight[MAXMXHOSTS];
 	int ttl = 0;
@@ -266,13 +273,47 @@
 	if (!UseNameServer)
 		goto punt;
 	if (HasWildcardMX && ConfigLevel >= 6)
+#if SUPPORT_DNSSEC
+		resfunc = val_res_query;
+#else
 		resfunc = res_query;
+#endif
 	else
+#if SUPPORT_DNSSEC
+		resfunc = val_res_search;
+#else
 		resfunc = res_search;
+#endif
 
 	errno = 0;
+
+# if SUPPORT_DNSSEC
+	do {
+		val_status_t dnssec_status = VAL_INTERNAL_ERROR; 
+		n = (*resfunc)(NULL, host, C_IN, T_MX, (unsigned char *) &answer,
+						sizeof(answer), &dnssec_status);
+		if (n >= 0) {
+			if (val_istrusted(dnssec_status))
+			{
+				if (tTd(8, 2))
+					sm_dprintf("getmxrr: DNSSEC validation of MX record of %s succeeded.\n", host);
+			}
+			else
+			{
+				if (tTd(8, 1))
+					sm_dprintf("getmxrr: DNSSEC validation of MX record of %s failed.\n", host);
+					errno = 0; /* was getting random errno strings after dnssec error */
+					syserr("Error: DNSSEC validation of MX record of %s failed.", host);
+					h_errno = NO_DATA;
+					n = -1;
+			}
+		}
+	} while (0);
+# else 
 	n = (*resfunc)(host, C_IN, T_MX, (unsigned char *) &answer,
 		       sizeof(answer));
+# endif /* SUPPORT_DNSSEC */
+
 	if (n < 0)
 	{
 		if (tTd(8, 1))
@@ -520,7 +561,7 @@
 				       host, MyHostName);
 				return -1;
 			}
-# if NETINET6
+# if NETINET6 
 			freehostent(h);
 			h = NULL;
 # endif /* NETINET6 */
@@ -898,8 +939,56 @@
 				qtype == T_MX ? "MX" :
 				"???");
 		errno = 0;
+# if SUPPORT_DNSSEC
+		do
+		{
+			char dname[MAXDNAME];
+			val_status_t dnssec_status = VAL_INTERNAL_ERROR;
+	
+			bzero(dname, MAXDNAME);
+			memcpy(dname, host, strlen(host));
+			memcpy(dname + strlen(host), ".", 1);
+			memcpy(dname + strlen(host) + 1, *dp, strlen(*dp));
+			
+			if (tTd(8, 5))
+				sm_dprintf("dns_getcanonname(938): performing dnssec validation query.\n");
+
+			/* perform DNSSEC validation query */
+			ret = val_res_query (NULL, dname, C_IN, qtype, (unsigned char *) &answer, 
+                    sizeof(answer), &dnssec_status);
+
+			if (ret > 0) { 
+				if (val_istrusted(dnssec_status))
+				{
+					if (tTd(8, 2))
+						sm_dprintf("DNSSEC validation of %s succeeded.\n", dname);
+				}
+				else
+				{
+					if (tTd(8, 7))
+						sm_dprintf("\tNO: errno=%d, h_errno=%d\n",
+							   errno, h_errno);
+			    
+                    h_errno = NO_DATA;
+                    ret = -1;
+
+
+
+
+
+
+
+
+
+
+				}
+			}
+		} while (0);
+# else /* SUPPORT_DNSSEC */
 		ret = res_querydomain(host, *dp, C_IN, qtype,
 				      answer.qb2, sizeof(answer.qb2));
+# endif /* SUPPORT_DNSSEC */
+
 		if (ret <= 0)
 		{
 			int save_errno = errno;
diff -U 5 -Nar sendmail-8.14.1.orig/sendmail/sm_resolve.c sendmail-8.14.1/sendmail/sm_resolve.c
--- sendmail-8.14.1.orig/sendmail/sm_resolve.c	2006-08-15 19:24:58.000000000 -0400
+++ sendmail-8.14.1/sendmail/sm_resolve.c	2008-05-12 10:15:06.000000000 -0400
@@ -68,10 +68,14 @@
 	{	"AFSDB",	T_AFSDB		},
 	{	"SRV",		T_SRV		},
 	{	NULL,		0		}
 };
 
+#  if SUPPORT_DNSSEC
+#   include <validator/validator.h>
+#  endif /* SUPPORT_DNSSEC */
+
 static DNS_REPLY_T *parse_dns_reply __P((unsigned char *, int));
 
 /*
 **  DNS_STRING_TO_TYPE -- convert resource record name into type
 **
@@ -407,11 +411,41 @@
 		save_retry = _res.retry;
 		_res.retry = retry;
 	}
 	errno = 0;
 	SM_SET_H_ERRNO(0);
+
+#  if SUPPORT_DNSSEC
+	if (tTd(8, 16))
+		sm_dprintf("dns_lookup_int(%s, %d, %s): ",
+			   domain, rr_class, dns_type_to_string(rr_type));
+	do
+	{
+		val_status_t dnssec_status = VAL_INTERNAL_ERROR;
+
+		/* perform DNSSEC validation query */
+		len = val_res_search(NULL, domain, rr_class, rr_type, reply, sizeof(reply), &dnssec_status);
+
+		if (len >= 0) { 
+			if (val_istrusted(dnssec_status))
+			{
+				if (tTd(8, 2))
+					sm_dprintf("\t\tdnssec validation of %s succeeded.\n", domain);
+			}
+			else
+			{
+				if (tTd(8, 1))
+					sm_dprintf("\t\tdnssec validation of %s failed.\n", domain);
+                h_errno = NO_DATA;
+                len = -1;
+			}
+		}
+	} while (0);
+#  else
 	len = res_search(domain, rr_class, rr_type, reply, sizeof(reply));
+#  endif /* SUPPORT_DNSSEC */
+
 	if (tTd(8, 16))
 	{
 		_res.options = old_options;
 		sm_dprintf("dns_lookup(%s, %d, %s) --> %d\n",
 			   domain, rr_class, dns_type_to_string(rr_type), len);
