[dns.c dns.h readconf.c ssh_config.5 sshconnect.c]
     update SSHFP validation. ok markus@
This commit is contained in:
Damien Miller 2003-11-17 21:19:29 +11:00
parent c1f2792bd0
commit 150b55745b
6 changed files with 81 additions and 69 deletions

View File

@ -31,6 +31,9 @@
- dtucker@cvs.openbsd.org 2003/11/12 10:12:15 - dtucker@cvs.openbsd.org 2003/11/12 10:12:15
[scp.c] [scp.c]
When called with -q, pass -q to ssh; suppresses SSH2 banner. ok markus@ When called with -q, pass -q to ssh; suppresses SSH2 banner. ok markus@
- jakob@cvs.openbsd.org 2003/11/12 16:39:58
[dns.c dns.h readconf.c ssh_config.5 sshconnect.c]
update SSHFP validation. ok markus@
20031115 20031115
- (dtucker) [regress/agent-ptrace.sh] Test for GDB output from Solaris and - (dtucker) [regress/agent-ptrace.sh] Test for GDB output from Solaris and
@ -1451,4 +1454,4 @@
- Fix sshd BindAddress and -b options for systems using fake-getaddrinfo. - Fix sshd BindAddress and -b options for systems using fake-getaddrinfo.
Report from murple@murple.net, diagnosis from dtucker@zip.com.au Report from murple@murple.net, diagnosis from dtucker@zip.com.au
$Id: ChangeLog,v 1.3105 2003/11/17 10:19:05 djm Exp $ $Id: ChangeLog,v 1.3106 2003/11/17 10:19:29 djm Exp $

68
dns.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dns.c,v 1.7 2003/10/14 19:42:10 jakob Exp $ */ /* $OpenBSD: dns.c,v 1.8 2003/11/12 16:39:58 jakob Exp $ */
/* /*
* Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@ -43,7 +43,7 @@
#include "uuencode.h" #include "uuencode.h"
extern char *__progname; extern char *__progname;
RCSID("$OpenBSD: dns.c,v 1.7 2003/10/14 19:42:10 jakob Exp $"); RCSID("$OpenBSD: dns.c,v 1.8 2003/11/12 16:39:58 jakob Exp $");
#ifndef LWRES #ifndef LWRES
static const char *errset_text[] = { static const char *errset_text[] = {
@ -83,7 +83,7 @@ dns_result_totext(unsigned int error)
*/ */
static int static int
dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
u_char **digest, u_int *digest_len, Key *key) u_char **digest, u_int *digest_len, const Key *key)
{ {
int success = 0; int success = 0;
@ -145,16 +145,15 @@ dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
/* /*
* Verify the given hostname, address and host key using DNS. * Verify the given hostname, address and host key using DNS.
* Returns 0 if key verifies or -1 if key does NOT verify * Returns 0 if lookup succeeds, -1 otherwise
*/ */
int int
verify_host_key_dns(const char *hostname, struct sockaddr *address, verify_host_key_dns(const char *hostname, struct sockaddr *address,
Key *hostkey) const Key *hostkey, int *flags)
{ {
int counter; int counter;
int result; int result;
struct rrsetinfo *fingerprints = NULL; struct rrsetinfo *fingerprints = NULL;
int failures = 0;
u_int8_t hostkey_algorithm; u_int8_t hostkey_algorithm;
u_int8_t hostkey_digest_type; u_int8_t hostkey_digest_type;
@ -166,6 +165,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
u_char *dnskey_digest; u_char *dnskey_digest;
u_int dnskey_digest_len; u_int dnskey_digest_len;
*flags = 0;
debug3("verify_hostkey_dns"); debug3("verify_hostkey_dns");
if (hostkey == NULL) if (hostkey == NULL)
@ -175,28 +175,29 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
DNS_RDATATYPE_SSHFP, 0, &fingerprints); DNS_RDATATYPE_SSHFP, 0, &fingerprints);
if (result) { if (result) {
verbose("DNS lookup error: %s", dns_result_totext(result)); verbose("DNS lookup error: %s", dns_result_totext(result));
return DNS_VERIFY_ERROR; return -1;
} }
#ifdef DNSSEC if (fingerprints->rri_flags & RRSET_VALIDATED) {
/* Only accept validated answers */ *flags |= DNS_VERIFY_SECURE;
if (!fingerprints->rri_flags & RRSET_VALIDATED) { debug("found %d secure fingerprints in DNS",
error("Ignored unvalidated fingerprint from DNS."); fingerprints->rri_nrdatas);
freerrset(fingerprints); } else {
return DNS_VERIFY_ERROR; debug("found %d insecure fingerprints in DNS",
fingerprints->rri_nrdatas);
} }
#endif
debug("found %d fingerprints in DNS", fingerprints->rri_nrdatas);
/* Initialize host key parameters */ /* Initialize host key parameters */
if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type, if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
&hostkey_digest, &hostkey_digest_len, hostkey)) { &hostkey_digest, &hostkey_digest_len, hostkey)) {
error("Error calculating host key fingerprint."); error("Error calculating host key fingerprint.");
freerrset(fingerprints); freerrset(fingerprints);
return DNS_VERIFY_ERROR; return -1;
} }
if (fingerprints->rri_nrdatas)
*flags |= DNS_VERIFY_FOUND;
for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++) { for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++) {
/* /*
* Extract the key from the answer. Ignore any badly * Extract the key from the answer. Ignore any badly
@ -218,35 +219,22 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
memcmp(hostkey_digest, dnskey_digest, memcmp(hostkey_digest, dnskey_digest,
hostkey_digest_len) == 0) { hostkey_digest_len) == 0) {
/* Matching algoritm and digest. */ *flags |= DNS_VERIFY_MATCH;
freerrset(fingerprints);
debug("matching host key fingerprint found in DNS");
return DNS_VERIFY_OK;
} else {
/* Correct algorithm but bad digest */
debug("verify_hostkey_dns: failed");
failures++;
} }
} }
} }
freerrset(fingerprints); freerrset(fingerprints);
if (failures) { if (*flags & DNS_VERIFY_FOUND)
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); if (*flags & DNS_VERIFY_MATCH)
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); debug("matching host key fingerprint found in DNS");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); else
error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); debug("mismatching host key fingerprint found in DNS");
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); else
error("It is also possible that the %s host key has just been changed.", debug("no host key fingerprint found in DNS");
key_type(hostkey));
error("Please contact your system administrator.");
return DNS_VERIFY_FAILED;
}
debug("fingerprints found in DNS, but none of them matched"); return 0;
return DNS_VERIFY_ERROR;
} }
@ -254,7 +242,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
* Export the fingerprint of a key as a DNS resource record * Export the fingerprint of a key as a DNS resource record
*/ */
int int
export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) export_dns_rr(const char *hostname, const Key *key, FILE *f, int generic)
{ {
u_int8_t rdata_pubkey_algorithm = 0; u_int8_t rdata_pubkey_algorithm = 0;
u_int8_t rdata_digest_type = SSHFP_HASH_SHA1; u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;

13
dns.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dns.h,v 1.4 2003/10/14 19:42:10 jakob Exp $ */ /* $OpenBSD: dns.h,v 1.5 2003/11/12 16:39:58 jakob Exp $ */
/* /*
* Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@ -45,11 +45,12 @@ enum sshfp_hashes {
#define DNS_RDATACLASS_IN 1 #define DNS_RDATACLASS_IN 1
#define DNS_RDATATYPE_SSHFP 44 #define DNS_RDATATYPE_SSHFP 44
#define DNS_VERIFY_FAILED -1 #define DNS_VERIFY_FOUND 0x00000001
#define DNS_VERIFY_OK 0 #define DNS_VERIFY_MATCH 0x00000002
#define DNS_VERIFY_ERROR 1 #define DNS_VERIFY_SECURE 0x00000004
int verify_host_key_dns(const char *, struct sockaddr *, Key *);
int export_dns_rr(const char *, Key *, FILE *, int); int verify_host_key_dns(const char *, struct sockaddr *, const Key *, int *);
int export_dns_rr(const char *, const Key *, FILE *, int);
#endif /* DNS_H */ #endif /* DNS_H */

View File

@ -12,7 +12,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: readconf.c,v 1.124 2003/10/14 19:42:10 jakob Exp $"); RCSID("$OpenBSD: readconf.c,v 1.125 2003/11/12 16:39:58 jakob Exp $");
#include "ssh.h" #include "ssh.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -401,10 +401,11 @@ parse_flag:
case oVerifyHostKeyDNS: case oVerifyHostKeyDNS:
intptr = &options->verify_host_key_dns; intptr = &options->verify_host_key_dns;
goto parse_flag; goto parse_yesnoask;
case oStrictHostKeyChecking: case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking; intptr = &options->strict_host_key_checking;
parse_yesnoask:
arg = strdelim(&s); arg = strdelim(&s);
if (!arg || *arg == '\0') if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing yes/no/ask argument.", fatal("%.200s line %d: Missing yes/no/ask argument.",

View File

@ -34,7 +34,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: ssh_config.5,v 1.23 2003/10/12 13:12:13 jmc Exp $ .\" $OpenBSD: ssh_config.5,v 1.24 2003/11/12 16:39:58 jakob Exp $
.Dd September 25, 1999 .Dd September 25, 1999
.Dt SSH_CONFIG 5 .Dt SSH_CONFIG 5
.Os .Os
@ -642,6 +642,23 @@ host key database instead of
.It Cm VerifyHostKeyDNS .It Cm VerifyHostKeyDNS
Specifies whether to verify the remote key using DNS and SSHFP resource Specifies whether to verify the remote key using DNS and SSHFP resource
records. records.
If this option is set to
.Dq yes ,
the client will implicitly trust keys that matches a secure fingerprint
from DNS.
Insecure fingerprints will be handled as if this option was set to
.Dq ask .
If this option is set to
.Dq ask ,
information on fingerprint match will be displayed, but the user will still
need to confirm new host keys according to the
.Cm StrictHostKeyChecking
option.
The argument must be
.Dq yes ,
.Dq no
or
.Dq ask .
The default is The default is
.Dq no . .Dq no .
Note that this option applies to protocol version 2 only. Note that this option applies to protocol version 2 only.

View File

@ -13,7 +13,7 @@
*/ */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sshconnect.c,v 1.152 2003/11/10 16:23:41 jakob Exp $"); RCSID("$OpenBSD: sshconnect.c,v 1.153 2003/11/12 16:39:58 jakob Exp $");
#include <openssl/bn.h> #include <openssl/bn.h>
@ -38,7 +38,7 @@ RCSID("$OpenBSD: sshconnect.c,v 1.152 2003/11/10 16:23:41 jakob Exp $");
char *client_version_string = NULL; char *client_version_string = NULL;
char *server_version_string = NULL; char *server_version_string = NULL;
int verified_host_key_dns = 0; int matching_host_key_dns = 0;
/* import */ /* import */
extern Options options; extern Options options;
@ -728,7 +728,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
msg2[0] = '\0'; msg2[0] = '\0';
if (options.verify_host_key_dns) { if (options.verify_host_key_dns) {
if (verified_host_key_dns) if (matching_host_key_dns)
snprintf(msg2, sizeof(msg2), snprintf(msg2, sizeof(msg2),
"Matching host key fingerprint" "Matching host key fingerprint"
" found in DNS.\n"); " found in DNS.\n");
@ -892,23 +892,25 @@ int
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
{ {
struct stat st; struct stat st;
int flags = 0;
if (options.verify_host_key_dns) { if (options.verify_host_key_dns &&
switch(verify_host_key_dns(host, hostaddr, host_key)) { verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
case DNS_VERIFY_OK:
#ifdef DNSSEC if (flags & DNS_VERIFY_FOUND) {
return 0;
#else if (options.verify_host_key_dns == 1 &&
verified_host_key_dns = 1; flags & DNS_VERIFY_MATCH &&
break; flags & DNS_VERIFY_SECURE)
#endif return 0;
case DNS_VERIFY_FAILED:
return -1; if (flags & DNS_VERIFY_MATCH) {
case DNS_VERIFY_ERROR: matching_host_key_dns = 1;
break; } else {
default: warn_changed_key(host_key);
debug3("bad return value from verify_host_key_dns"); error("Update the SSHFP RR in DNS with the new "
break; "host key to get rid of this message.");
}
} }
} }