[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
[scp.c]
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
- (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.
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.
@ -43,7 +43,7 @@
#include "uuencode.h"
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
static const char *errset_text[] = {
@ -83,7 +83,7 @@ dns_result_totext(unsigned int error)
*/
static int
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;
@ -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.
* Returns 0 if key verifies or -1 if key does NOT verify
* Returns 0 if lookup succeeds, -1 otherwise
*/
int
verify_host_key_dns(const char *hostname, struct sockaddr *address,
Key *hostkey)
const Key *hostkey, int *flags)
{
int counter;
int result;
struct rrsetinfo *fingerprints = NULL;
int failures = 0;
u_int8_t hostkey_algorithm;
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_int dnskey_digest_len;
*flags = 0;
debug3("verify_hostkey_dns");
if (hostkey == NULL)
@ -175,28 +175,29 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
DNS_RDATATYPE_SSHFP, 0, &fingerprints);
if (result) {
verbose("DNS lookup error: %s", dns_result_totext(result));
return DNS_VERIFY_ERROR;
return -1;
}
#ifdef DNSSEC
/* Only accept validated answers */
if (!fingerprints->rri_flags & RRSET_VALIDATED) {
error("Ignored unvalidated fingerprint from DNS.");
freerrset(fingerprints);
return DNS_VERIFY_ERROR;
if (fingerprints->rri_flags & RRSET_VALIDATED) {
*flags |= DNS_VERIFY_SECURE;
debug("found %d secure fingerprints in DNS",
fingerprints->rri_nrdatas);
} else {
debug("found %d insecure fingerprints in DNS",
fingerprints->rri_nrdatas);
}
#endif
debug("found %d fingerprints in DNS", fingerprints->rri_nrdatas);
/* 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.");
freerrset(fingerprints);
return DNS_VERIFY_ERROR;
return -1;
}
if (fingerprints->rri_nrdatas)
*flags |= DNS_VERIFY_FOUND;
for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++) {
/*
* 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,
hostkey_digest_len) == 0) {
/* Matching algoritm and digest. */
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++;
*flags |= DNS_VERIFY_MATCH;
}
}
}
freerrset(fingerprints);
if (failures) {
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
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.",
key_type(hostkey));
error("Please contact your system administrator.");
return DNS_VERIFY_FAILED;
}
if (*flags & DNS_VERIFY_FOUND)
if (*flags & DNS_VERIFY_MATCH)
debug("matching host key fingerprint found in DNS");
else
debug("mismatching host key fingerprint found in DNS");
else
debug("no host key fingerprint found in DNS");
debug("fingerprints found in DNS, but none of them matched");
return DNS_VERIFY_ERROR;
return 0;
}
@ -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
*/
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_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.
@ -45,11 +45,12 @@ enum sshfp_hashes {
#define DNS_RDATACLASS_IN 1
#define DNS_RDATATYPE_SSHFP 44
#define DNS_VERIFY_FAILED -1
#define DNS_VERIFY_OK 0
#define DNS_VERIFY_ERROR 1
#define DNS_VERIFY_FOUND 0x00000001
#define DNS_VERIFY_MATCH 0x00000002
#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 */

View File

@ -12,7 +12,7 @@
*/
#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 "xmalloc.h"
@ -401,10 +401,11 @@ parse_flag:
case oVerifyHostKeyDNS:
intptr = &options->verify_host_key_dns;
goto parse_flag;
goto parse_yesnoask;
case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking;
parse_yesnoask:
arg = strdelim(&s);
if (!arg || *arg == '\0')
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
.\" 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
.Dt SSH_CONFIG 5
.Os
@ -642,6 +642,23 @@ host key database instead of
.It Cm VerifyHostKeyDNS
Specifies whether to verify the remote key using DNS and SSHFP resource
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
.Dq no .
Note that this option applies to protocol version 2 only.

View File

@ -13,7 +13,7 @@
*/
#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>
@ -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 *server_version_string = NULL;
int verified_host_key_dns = 0;
int matching_host_key_dns = 0;
/* import */
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);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (verified_host_key_dns)
if (matching_host_key_dns)
snprintf(msg2, sizeof(msg2),
"Matching host key fingerprint"
" found in DNS.\n");
@ -892,23 +892,25 @@ int
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
{
struct stat st;
int flags = 0;
if (options.verify_host_key_dns) {
switch(verify_host_key_dns(host, hostaddr, host_key)) {
case DNS_VERIFY_OK:
#ifdef DNSSEC
return 0;
#else
verified_host_key_dns = 1;
break;
#endif
case DNS_VERIFY_FAILED:
return -1;
case DNS_VERIFY_ERROR:
break;
default:
debug3("bad return value from verify_host_key_dns");
break;
if (options.verify_host_key_dns &&
verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
if (flags & DNS_VERIFY_FOUND) {
if (options.verify_host_key_dns == 1 &&
flags & DNS_VERIFY_MATCH &&
flags & DNS_VERIFY_SECURE)
return 0;
if (flags & DNS_VERIFY_MATCH) {
matching_host_key_dns = 1;
} else {
warn_changed_key(host_key);
error("Update the SSHFP RR in DNS with the new "
"host key to get rid of this message.");
}
}
}