- 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@
This commit is contained in:
parent
c1f2792bd0
commit
150b55745b
|
@ -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
68
dns.c
|
@ -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
13
dns.h
|
@ -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 */
|
||||
|
|
|
@ -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.",
|
||||
|
|
19
ssh_config.5
19
ssh_config.5
|
@ -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.
|
||||
|
|
40
sshconnect.c
40
sshconnect.c
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue