Sophie

Sophie

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

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

diff -c -r openssh-4.7p1.orig/configure.ac openssh-4.7p1/configure.ac
*** openssh-4.7p1.orig/configure.ac	Fri Aug 10 00:36:12 2007
--- openssh-4.7p1/configure.ac	Wed Apr 30 10:40:54 2008
***************
*** 3115,3146 ****
  	]
  )
  
! # Check whether user wants OpenSC support
! OPENSC_CONFIG="no"
! AC_ARG_WITH(opensc,
! 	[  --with-opensc[[=PFX]]     Enable smartcard support using OpenSC (optionally in PATH)],
! 	[
! 	    if test "x$withval" != "xno" ; then
  		if test "x$withval" != "xyes" ; then
!   			OPENSC_CONFIG=$withval/bin/opensc-config
! 		else
!   			AC_PATH_PROG(OPENSC_CONFIG, opensc-config, no)
  		fi
! 		if test "$OPENSC_CONFIG" != "no"; then
! 			LIBOPENSC_CFLAGS=`$OPENSC_CONFIG --cflags`
! 			LIBOPENSC_LIBS=`$OPENSC_CONFIG --libs`
! 			CPPFLAGS="$CPPFLAGS $LIBOPENSC_CFLAGS"
! 			LIBS="$LIBS $LIBOPENSC_LIBS"
! 			AC_DEFINE(SMARTCARD)
! 			AC_DEFINE(USE_OPENSC, 1,
! 				[Define if you want smartcard support
! 				using OpenSC])
! 			SCARD_MSG="yes, using OpenSC"
  		fi
  	    fi
! 	]
! )
! 
  # Check libraries needed by DNS fingerprint support
  AC_SEARCH_LIBS(getrrsetbyname, resolv,
  	[AC_DEFINE(HAVE_GETRRSETBYNAME, 1,
--- 3115,3155 ----
  	]
  )
  
! LIBVAL_MSG="no"
! # Check whether user wants DNSSEC local validation support
! AC_ARG_WITH(local-dnssec-validation,
! 	[  --with-local-dnssec-validation Enable local DNSSEC validation using libval],
! 	[ if test "x$withval" != "xno" ; then
  		if test "x$withval" != "xyes" ; then
! 			CPPFLAGS="$CPPFLAGS -I${withval}"
! 			LDFLAGS="$LDFLAGS -L${withval}"
! 			if test ! -z "$need_dash_r" ; then
! 				LDFLAGS="$LDFLAGS -R${withval}"
  		fi
! 			if test ! -z "$blibpath" ; then
! 				blibpath="$blibpath:${withval}"
  		fi
  	    fi
! 		AC_CHECK_HEADERS(validator/validator.h)
! 		if test "$ac_cv_header_validator_validator_h" != yes; then
! 			AC_MSG_ERROR(Can't find validator.h)
! 		fi
! 		AC_CHECK_LIB(sres, query_send)
! 		if test "$ac_cv_lib_sres_query_send" != yes; then
! 			AC_MSG_ERROR(Can't find libsres)
! 		fi
! 		LIBVAL_SUFFIX=""
! 		AC_CHECK_LIB(val, p_val_status,LIBS="$LIBS -lval",
! 			[ AC_CHECK_LIB(pthread, pthread_rwlock_init)
! 			  AC_CHECK_LIB(val-threads, p_val_status,
! 				[ LIBS="$LIBS -lval-threads -lpthread"
! 				  LIBVAL_SUFFIX="-threads"],
! 				AC_MSG_ERROR(Can't find libval or libval-threads))
! 			])
! 		AC_DEFINE(LOCAL_DNSSEC_VALIDATION, 1,
! 			[Define if you want local DNSSEC validation support])
! 		LIBVAL_MSG="yes, libval${LIBVAL_SUFFIX}"
! 	else
  # Check libraries needed by DNS fingerprint support
  AC_SEARCH_LIBS(getrrsetbyname, resolv,
  	[AC_DEFINE(HAVE_GETRRSETBYNAME, 1,
***************
*** 3177,3182 ****
--- 3186,3220 ----
  			    [Define if HEADER.ad exists in arpa/nameser.h])],,
  			[#include <arpa/nameser.h>])
  	])
+ 	 fi]
+ )
+ 
+ # Check whether user wants OpenSC support
+ OPENSC_CONFIG="no"
+ AC_ARG_WITH(opensc,
+ 	[  --with-opensc[[=PFX]]     Enable smartcard support using OpenSC (optionally in PATH)],
+ 	[
+ 	    if test "x$withval" != "xno" ; then
+ 		if test "x$withval" != "xyes" ; then
+   			OPENSC_CONFIG=$withval/bin/opensc-config
+ 		else
+   			AC_PATH_PROG(OPENSC_CONFIG, opensc-config, no)
+ 		fi
+ 		if test "$OPENSC_CONFIG" != "no"; then
+ 			LIBOPENSC_CFLAGS=`$OPENSC_CONFIG --cflags`
+ 			LIBOPENSC_LIBS=`$OPENSC_CONFIG --libs`
+ 			CPPFLAGS="$CPPFLAGS $LIBOPENSC_CFLAGS"
+ 			LIBS="$LIBS $LIBOPENSC_LIBS"
+ 			AC_DEFINE(SMARTCARD)
+ 			AC_DEFINE(USE_OPENSC, 1,
+ 				[Define if you want smartcard support
+ 				using OpenSC])
+ 			SCARD_MSG="yes, using OpenSC"
+ 		fi
+ 	    fi
+ 	]
+ )
+ 
  
  AC_MSG_CHECKING(if struct __res_state _res is an extern)
  AC_LINK_IFELSE([
***************
*** 4035,4040 ****
--- 4073,4079 ----
  echo "              MD5 password support: $MD5_MSG"
  echo "                   libedit support: $LIBEDIT_MSG"
  echo "  Solaris process contract support: $SPC_MSG"
+ echo "   Local DNSSEC validation support: $LIBVAL_MSG"
  echo "       IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
  echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
  echo "                  BSD Auth support: $BSD_AUTH_MSG"
diff -c -r openssh-4.7p1.orig/dns.c openssh-4.7p1/dns.c
*** openssh-4.7p1.orig/dns.c	Fri Jan  5 00:30:16 2007
--- openssh-4.7p1/dns.c	Wed Apr 30 10:54:27 2008
***************
*** 35,40 ****
--- 35,44 ----
  #include <stdio.h>
  #include <string.h>
  
+ #ifdef LOCAL_DNSSEC_VALIDATION
+ # include <validator/validator.h>
+ #endif
+ 
  #include "xmalloc.h"
  #include "key.h"
  #include "dns.h"
***************
*** 167,179 ****
  {
  	u_int counter;
  	int result;
- 	struct rrsetinfo *fingerprints = NULL;
  
  	u_int8_t hostkey_algorithm;
  	u_int8_t hostkey_digest_type;
  	u_char *hostkey_digest;
  	u_int hostkey_digest_len;
  
  	u_int8_t dnskey_algorithm;
  	u_int8_t dnskey_digest_type;
  	u_char *dnskey_digest;
--- 171,189 ----
  {
  	u_int counter;
  	int result;
  
  	u_int8_t hostkey_algorithm;
  	u_int8_t hostkey_digest_type;
  	u_char *hostkey_digest;
  	u_int hostkey_digest_len;
  
+ #ifndef LOCAL_DNSSEC_VALIDATION
+ 	struct rrsetinfo *fingerprints = NULL;
+ #else
+ 	struct val_result_chain *val_res, *val_results = NULL;
+ 	char hostname_n[NS_MAXDNAME];
+ #endif
+ 
  	u_int8_t dnskey_algorithm;
  	u_int8_t dnskey_digest_type;
  	u_char *dnskey_digest;
***************
*** 190,195 ****
--- 200,206 ----
  		return -1;
  	}
  
+ #ifndef LOCAL_DNSSEC_VALIDATION
  	result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
  	    DNS_RDATATYPE_SSHFP, 0, &fingerprints);
  	if (result) {
***************
*** 198,204 ****
  	}
  
  	if (fingerprints->rri_flags & RRSET_VALIDATED) {
! 		*flags |= DNS_VERIFY_SECURE;
  		debug("found %d secure fingerprints in DNS",
  		    fingerprints->rri_nrdatas);
  	} else {
--- 209,215 ----
  	}
  
  	if (fingerprints->rri_flags & RRSET_VALIDATED) {
! 		*flags |= (DNS_VERIFY_SECURE|DNS_VERIFY_TRUSTED);
  		debug("found %d secure fingerprints in DNS",
  		    fingerprints->rri_nrdatas);
  	} else {
***************
*** 246,251 ****
--- 257,350 ----
  
  	xfree(hostkey_digest); /* from key_fingerprint_raw() */
  	freerrset(fingerprints);
+ #else
+ 	ns_name_pton(hostname, hostname_n, sizeof(hostname_n));
+ 	result = val_resolve_and_check(NULL, hostname_n, DNS_RDATACLASS_IN,
+ 	    DNS_RDATATYPE_SSHFP, 0, &val_results);
+ 	if (result != VAL_NO_ERROR){
+ 		verbose("DNS lookup error: %s", p_ac_status(val_results->val_rc_status));
+ 		return -1;
+ 	}
+ 
+ 	/* Initialize host key parameters */
+ 	if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
+ 	    &hostkey_digest, &hostkey_digest_len, hostkey)) {
+ 		error("Error calculating host key fingerprint.");
+ 		val_free_result_chain(val_results);
+ 		return -1;
+ 	}
+ 
+ 	counter = 0;
+ 	for (val_res = val_results; val_res; val_res = val_res->val_rc_next)  {
+ 		struct val_rrset_rec *val_rrset;
+ 		struct val_rr_rec *rr;
+ 
+ 		val_rrset = val_res->val_rc_rrset;
+ 		if ((NULL == val_rrset) || (NULL == val_rrset->val_rrset_data)) 
+ 			continue;
+ 
+ 		for(rr = val_rrset->val_rrset_data; rr;
+ 		    rr = rr->rr_next) {
+ 
+ 			if (NULL == rr->rr_rdata)
+ 				continue;
+ 
+ 			/*
+ 			 * Extract the key from the answer. Ignore any badly
+ 			 * formatted fingerprints.
+ 			 */
+ 			if (!dns_read_rdata(&dnskey_algorithm, &dnskey_digest_type,
+ 			    &dnskey_digest, &dnskey_digest_len,
+ 			    rr->rr_rdata,
+ 			    rr->rr_rdata_length_h)) {
+ 				verbose("Error parsing fingerprint from DNS.");
+ 				continue;
+ 			}
+ 
+ 			++counter;
+ 
+ 			/* Check if the current key is the same as the given key */
+ 			if (hostkey_algorithm == dnskey_algorithm &&
+ 			    hostkey_digest_type == dnskey_digest_type) {
+ 
+ 				if (hostkey_digest_len == dnskey_digest_len &&
+ 				    memcmp(hostkey_digest, dnskey_digest,
+ 				    hostkey_digest_len) == 0) {
+ 
+ 					debug("found matching fingerprints in DNS");
+ 					*flags |= DNS_VERIFY_MATCH;
+ 
+ 
+ 
+ 				}
+ 			}
+ 			xfree(dnskey_digest);
+ 		}
+ 	    if (val_istrusted(val_res->val_rc_status)) {
+ 		    /*
+ 		     * local validation can result in a non-secure, but trusted
+ 		     * response. For example, in a corporate network the authoritative
+ 		     * server for internal DNS may be on the internal network, behind
+ 		     * a firewall. Local validation policy can be configured to trust
+ 		     * these results without using DNSSEC to validate them.
+ 		     */
+ 		    *flags |= DNS_VERIFY_TRUSTED;
+ 		    if (val_isvalidated(val_res->val_rc_status)) {
+ 			    *flags |= DNS_VERIFY_SECURE;
+ 			    debug("found %d trusted fingerprints in DNS", counter);
+ 		    } else  {
+ 			    debug("found %d trusted, but not validated, fingerprints in DNS", counter);
+ 		    }
+ 	    } else {
+ 		    debug("found %d un-trusted fingerprints in DNS", counter);
+ 	    }
+ 	}
+ 	if(counter)
+ 		*flags |= DNS_VERIFY_FOUND;
+ 
+ 	xfree(hostkey_digest); /* from key_fingerprint_raw() */
+ 	val_free_result_chain(val_results);
+ #endif /* */
  
  	if (*flags & DNS_VERIFY_FOUND)
  		if (*flags & DNS_VERIFY_MATCH)
diff -c -r openssh-4.7p1.orig/dns.h openssh-4.7p1/dns.h
*** openssh-4.7p1.orig/dns.h	Fri Aug  4 22:39:40 2006
--- openssh-4.7p1/dns.h	Wed Apr 30 10:40:54 2008
***************
*** 45,50 ****
--- 45,51 ----
  #define DNS_VERIFY_FOUND	0x00000001
  #define DNS_VERIFY_MATCH	0x00000002
  #define DNS_VERIFY_SECURE	0x00000004
+ #define DNS_VERIFY_TRUSTED	0x00000008
  
  int	verify_host_key_dns(const char *, struct sockaddr *, const Key *, int *);
  int	export_dns_rr(const char *, const Key *, FILE *, int);
diff -c -r openssh-4.7p1.orig/readconf.c openssh-4.7p1/readconf.c
*** openssh-4.7p1.orig/readconf.c	Wed Mar 21 05:46:03 2007
--- openssh-4.7p1/readconf.c	Wed Apr 30 10:40:54 2008
***************
*** 130,135 ****
--- 130,136 ----
  	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
  	oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
  	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
+ 	oStrictDnssecChecking,oAutoAnswerValidatedKeys,
  	oDeprecated, oUnsupported
  } OpCodes;
  
***************
*** 226,231 ****
--- 227,239 ----
  	{ "tunneldevice", oTunnelDevice },
  	{ "localcommand", oLocalCommand },
  	{ "permitlocalcommand", oPermitLocalCommand },
+ #ifdef LOCAL_DNSSEC_VALIDATION
+ 	{ "strictdnssecchecking", oStrictDnssecChecking },
+         { "autoanswervalidatedkeys", oAutoAnswerValidatedKeys },
+ #else
+ 	{ "strictdnssecchecking", oUnsupported },
+         { "autoanswervalidatedkeys", oUnsupported },
+ #endif
  	{ NULL, oBadOption }
  };
  
***************
*** 477,482 ****
--- 485,498 ----
  			*intptr = value;
  		break;
  
+ 	case oStrictDnssecChecking:
+ 		intptr = &options->strict_dnssec_checking;
+                 goto parse_yesnoask;
+ 
+ 	case oAutoAnswerValidatedKeys:
+ 		intptr = &options->autoanswer_validated_keys;
+                 goto parse_yesnoask;
+ 
  	case oCompression:
  		intptr = &options->compression;
  		goto parse_flag;
***************
*** 1019,1024 ****
--- 1035,1042 ----
  	options->batch_mode = -1;
  	options->check_host_ip = -1;
  	options->strict_host_key_checking = -1;
+ 	options->strict_dnssec_checking = -1;
+         options->autoanswer_validated_keys = -1;
  	options->compression = -1;
  	options->tcp_keep_alive = -1;
  	options->compression_level = -1;
***************
*** 1115,1120 ****
--- 1133,1142 ----
  		options->check_host_ip = 1;
  	if (options->strict_host_key_checking == -1)
  		options->strict_host_key_checking = 2;	/* 2 is default */
+ 	if (options->strict_dnssec_checking == -1)
+ 		options->strict_dnssec_checking = 2;	/* 2 is default */
+ 	if (options->autoanswer_validated_keys == -1)
+ 		options->autoanswer_validated_keys = 0;	/* 0 is default */
  	if (options->compression == -1)
  		options->compression = 0;
  	if (options->tcp_keep_alive == -1)
diff -c -r openssh-4.7p1.orig/readconf.h openssh-4.7p1/readconf.h
*** openssh-4.7p1.orig/readconf.h	Fri Aug  4 22:39:40 2006
--- openssh-4.7p1/readconf.h	Wed Apr 30 10:40:54 2008
***************
*** 121,126 ****
--- 121,129 ----
  	char	*local_command;
  	int	permit_local_command;
  
+ 	int     strict_dnssec_checking;	/* Strict DNSSEC checking. */
+ 	int     autoanswer_validated_keys;
+ 
  }       Options;
  
  #define SSHCTL_MASTER_NO	0
diff -c -r openssh-4.7p1.orig/sshconnect.c openssh-4.7p1/sshconnect.c
*** openssh-5.0p1/sshconnect.c.orig	Tue May 27 16:23:00 2008
--- openssh-5.0p1/sshconnect.c	Tue May 27 16:27:04 2008
***************
*** 26,31 ****
--- 26,35 ----
  #include <netinet/in.h>
  #include <arpa/inet.h>
  
+ #ifdef LOCAL_DNSSEC_VALIDATION
+ # include <validator/validator.h>
+ #endif
+ 
  #include <ctype.h>
  #include <errno.h>
  #include <netdb.h>
***************
*** 63,68 ****
--- 67,75 ----
  char *server_version_string = NULL;
  
  static int matching_host_key_dns = 0;
+ #ifdef LOCAL_DNSSEC_VALIDATION
+ static int validated_host_key_dns = 0;
+ #endif
  
  /* import */
  extern Options options;
***************
*** 77,82 ****
--- 84,90 ----
  
  static int show_other_keys(const char *, Key *);
  static void warn_changed_key(Key *);
+ static int confirm(const char *prompt);
  
  static void
  ms_subtract_diff(struct timeval *start, int *ms)
***************
*** 225,230 ****
--- 233,239 ----
  	hints.ai_socktype = ai->ai_socktype;
  	hints.ai_protocol = ai->ai_protocol;
  	hints.ai_flags = AI_PASSIVE;
+ #ifndef LOCAL_DNSSEC_VALIDATION
  	gaierr = getaddrinfo(options.bind_address, "0", &hints, &res);
  	if (gaierr) {
  		error("getaddrinfo: %s: %s", options.bind_address,
***************
*** 232,237 ****
--- 241,283 ----
  		close(sock);
  		return -1;
  	}
+ #else
+         gaierr = val_getaddrinfo(NULL, host, strport, &hints, &aitop,
+                                  &val_status);
+  	if (gaierr)
+             fatal("%s: %.100s: %s", __progname, host, gai_strerror(gaierr));
+  	debug("ValStatus: %s", p_val_status(val_status));
+  	if (!val_istrusted(val_status)) {
+             error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+             error("@ WARNING: UNTRUSTED DNS RESOLUTION FOR HOST IP ADRRESS! @");
+             error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+             error("The authenticity of DNS data for the host '%.200s' "
+                   "can't be established.", host);
+             if (options.strict_dnssec_checking == 1) {
+                 fatal("DNS resolution is not trusted (%s) "
+                       "and you have requested strict checking",
+                       p_val_status(val_status));
+             } else if (options.strict_dnssec_checking == 2) {
+                 char msg[1024];
+                 for (ai = aitop; ai; ai = ai->ai_next) {
+                     if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+                         continue;
+                     if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
+  				    ntop, sizeof(ntop), strport, sizeof(strport),
+  				    NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
+                         error("ssh_connect: getnameinfo failed");
+                         continue;
+                     }
+                     error(" IP address %s port %s", ntop, strport);
+                 }
+                 snprintf(msg,sizeof(msg),
+                          "Are you sure you want to attempt to connect "
+                          "(yes/no)? ");
+                 if (!confirm(msg))
+                     return (-1);
+             }
+  	}
+ #endif
  	if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
  		error("bind: %s: %s", options.bind_address, strerror(errno));
  		close(sock);
***************
*** 345,351 ****
  	int on = 1;
  	int sock = -1, attempt;
  	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
! 	struct addrinfo hints, *ai, *aitop;
  
  	debug2("ssh_connect: needpriv %d", needpriv);
  
--- 391,401 ----
  	int on = 1;
  	int sock = -1, attempt;
  	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
! 	struct addrinfo hints;
! 	struct addrinfo *ai, *aitop = NULL;
! #ifdef LOCAL_DNSSEC_VALIDATION
! 	val_status_t val_status;
! #endif
  
  	debug2("ssh_connect: needpriv %d", needpriv);
  
***************
*** 747,752 ****
--- 797,803 ----
  		}
  		break;
  	case HOST_NEW:
+ 		debug("Host '%.200s' new.", host);
  		if (options.host_key_alias == NULL && port != 0 &&
  		    port != SSH_DEFAULT_PORT) {
  			debug("checking without port identifier");
***************
*** 790,795 ****
--- 841,857 ----
  					    "No matching host key fingerprint"
  					    " found in DNS.\n");
  			}
+ #ifdef LOCAL_DNSSEC_VALIDATION
+                         if (options.autoanswer_validated_keys &&
+                             validated_host_key_dns && matching_host_key_dns) {
+                             snprintf(msg, sizeof(msg),
+                                      "The authenticity of host '%.200s (%s)' was "
+                                      " validated via DNSSEC%s",
+                                      host, ip, msg1);
+                             logit(msg);
+                             xfree(fp);
+                         } else {
+ #endif
  			snprintf(msg, sizeof(msg),
  			    "The authenticity of host '%.200s (%s)' can't be "
  			    "established%s\n"
***************
*** 800,805 ****
--- 862,870 ----
  			xfree(fp);
  			if (!confirm(msg))
  				goto fail;
+ #ifdef LOCAL_DNSSEC_VALIDATION
+                         }
+ #endif
  		}
  		/*
  		 * If not in strict mode, add the key automatically to the
***************
*** 835,840 ****
--- 900,906 ----
  			    "list of known hosts.", hostp, type);
  		break;
  	case HOST_CHANGED:
+ 		debug("Host '%.200s' changed.", host);
  		if (readonly == ROQUIET)
  			goto fail;
  		if (options.check_host_ip && host_ip_differ) {
***************
*** 845,850 ****
--- 911,918 ----
  				key_msg = "is unchanged";
  			else
  				key_msg = "has a different value";
+ #ifdef LOCAL_DNSSEC_VALIDATION
+                         if (!validated_host_key_dns) {
  			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  			error("@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @");
  			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
***************
*** 853,858 ****
--- 921,939 ----
  			error("%s. This could either mean that", key_msg);
  			error("DNS SPOOFING is happening or the IP address for the host");
  			error("and its host key have changed at the same time.");
+                         }
+                         else {
+ #endif
+ 			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ 			error("@       WARNING: HOST IP ADDRESS HAS CHANGED!             @");
+ 			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+                         error("The %s host key for %s has changed,", type, host);
+ 			error("and the key for the according IP address %s", ip);
+ 			error("%s. The IP address for the host", key_msg);
+ 			error("and its host key have changed at the same time.");
+ #ifdef LOCAL_DNSSEC_VALIDATION
+                         }
+ #endif
  			if (ip_status != HOST_NEW)
  				error("Offending key for IP in %s:%d", ip_file, ip_line);
  		}
***************
*** 866,877 ****
  		 * If strict host key checking is in use, the user will have
  		 * to edit the key manually and we can only abort.
  		 */
  		if (options.strict_host_key_checking) {
  			error("%s host key for %.200s has changed and you have "
  			    "requested strict checking.", type, host);
  			goto fail;
  		}
! 
  		/*
  		 * If strict host key checking has not been requested, allow
  		 * the connection but without MITM-able authentication or
--- 947,1000 ----
  		 * If strict host key checking is in use, the user will have
  		 * to edit the key manually and we can only abort.
  		 */
+ #ifdef LOCAL_DNSSEC_VALIDATION
+ 		if ((options.strict_host_key_checking == 2) &&
+                     options.autoanswer_validated_keys &&
+                     matching_host_key_dns && validated_host_key_dns) {
+                     logit("The authenticity of host '%.200s (%s)' was "
+                           " validated via DNSSEC.",
+                           host, ip);
+                     /*
+                      * If not in strict mode, add the key automatically to the
+                      * local known_hosts file.
+                      */
+                     if (options.check_host_ip && ip_status == HOST_NEW) {
+ 			snprintf(hostline, sizeof(hostline), "%s,%s",
+                                  host, ip);
+ 			hostp = hostline;
+ 			if (options.hash_known_hosts) {
+                             /* Add hash of host and IP separately */
+                             r = add_host_to_hostfile(user_hostfile, host,
+                                                      host_key, options.hash_known_hosts) &&
+                                 add_host_to_hostfile(user_hostfile, ip,
+                                                      host_key, options.hash_known_hosts);
+ 			} else {
+                             /* Add unhashed "host,ip" */
+                             r = add_host_to_hostfile(user_hostfile,
+                                                      hostline, host_key,
+                                                      options.hash_known_hosts);
+ 			}
+                     } else {
+ 			r = add_host_to_hostfile(user_hostfile, host, host_key,
+                                                  options.hash_known_hosts);
+ 			hostp = host;
+                     }
+                     
+                     if (!r)
+ 			logit("Failed to add the host to the list of known "
+                               "hosts (%.500s).", user_hostfile);
+                     else
+ 			logit("Warning: Permanently added '%.200s' (%s) to the "
+                               "list of known hosts.", hostp, type);
+                 }
+                 else
+ #endif
  		if (options.strict_host_key_checking) {
  			error("%s host key for %.200s has changed and you have "
  			    "requested strict checking.", type, host);
  			goto fail;
  		}
!                 else {
  		/*
  		 * If strict host key checking has not been requested, allow
  		 * the connection but without MITM-able authentication or
***************
*** 919,927 ****
  		 * XXX Should permit the user to change to use the new id.
  		 * This could be done by converting the host key to an
  		 * identifying sentence, tell that the host identifies itself
! 		 * by that sentence, and ask the user if he/she whishes to
  		 * accept the authentication.
  		 */
  		break;
  	case HOST_FOUND:
  		fatal("internal error");
--- 1042,1051 ----
  		 * XXX Should permit the user to change to use the new id.
  		 * This could be done by converting the host key to an
  		 * identifying sentence, tell that the host identifies itself
! 		 * by that sentence, and ask the user if he/she wishes to
  		 * accept the authentication.
  		 */
+                 }
  		break;
  	case HOST_FOUND:
  		fatal("internal error");
***************
*** 946,955 ****
--- 1070,1088 ----
  			error("Exiting, you have requested strict checking.");
  			goto fail;
  		} else if (options.strict_host_key_checking == 2) {
+ #ifdef LOCAL_DNSSEC_VALIDATION
+                     if (options.autoanswer_validated_keys &&
+                         matching_host_key_dns && validated_host_key_dns) {
+ 			logit("%s", msg);
+                     } else {
+ #endif
  			strlcat(msg, "\nAre you sure you want "
  			    "to continue connecting (yes/no)? ", sizeof(msg));
  			if (!confirm(msg))
  				goto fail;
+ #ifdef LOCAL_DNSSEC_VALIDATION
+                     }
+ #endif
  		} else {
  			logit("%s", msg);
  		}
***************
*** 975,986 ****
--- 1108,1149 ----
  	if (options.verify_host_key_dns &&
  	    verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
  
+ #ifdef LOCAL_DNSSEC_VALIDATION
+ 		/*
+ 		 * local validation can result in a non-secure, but trusted
+ 		 * response. For example, in a corporate network the authoritative
+ 		 * server for internal DNS may be on the internal network, behind
+ 		 * a firewall. Local validation policy can be configured to trust
+ 		 * these results without using DNSSEC to validate them.
+ 		 */
+ 		if (!(flags & DNS_VERIFY_TRUSTED)) {
+ 			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ 			error("@  WARNING: UNTRUSTED DNS RESOLUTION FOR HOST KEY!       @");
+ 			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ 		}
+                 if (flags & DNS_VERIFY_SECURE)
+                     validated_host_key_dns = 1;
+ #endif
  		if (flags & DNS_VERIFY_FOUND) {
  
  			if (options.verify_host_key_dns == 1 &&
  			    flags & DNS_VERIFY_MATCH &&
  			    flags & DNS_VERIFY_SECURE)
+ #ifndef LOCAL_DNSSEC_VALIDATION
  				return 0;
+ #else
+                         {
+                             if (flags & DNS_VERIFY_MATCH)
+ 				matching_host_key_dns = 1;
+                             if (options.autoanswer_validated_keys)
+                                 return check_host_key(host, hostaddr, options.port,
+                                                       host_key, RDRW,
+                                                       options.user_hostfile,
+                                                       options.system_hostfile);
+                             else
+ 				return 0;
+                         }
+ #endif
  
  			if (flags & DNS_VERIFY_MATCH) {
  				matching_host_key_dns = 1;
***************
*** 1129,1137 ****
--- 1292,1309 ----
  	error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  	error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
  	error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ #ifdef LOCAL_DNSSEC_VALIDATION
+         if (matching_host_key_dns && validated_host_key_dns) {
+             error("Howerver, a matching host key, validated by DNSSEC, was found.");
+         }
+         else {
+ #endif
  	error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
  	error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
  	error("It is also possible that the %s host key has just been changed.", type);
+ #ifdef LOCAL_DNSSEC_VALIDATION
+         }
+ #endif
  	error("The fingerprint for the %s key sent by the remote host is\n%s.",
  	    type, fp);
  	error("Please contact your system administrator.");