- jakob@cvs.openbsd.org 2003/05/14 18:16:20
[key.c key.h readconf.c readconf.h ssh_config.5 sshconnect.c] [dns.c dns.h README.dns ssh-keygen.1 ssh-keygen.c] add experimental support for verifying hos keys using DNS as described in draft-ietf-secsh-dns-xx.txt. more information in README.dns. ok markus@ and henning@
This commit is contained in:
parent
abbae980e7
commit
37876e913a
|
@ -4,6 +4,12 @@
|
|||
[ssh-agent.1]
|
||||
setup -> set up;
|
||||
from wiz@netbsd
|
||||
- jakob@cvs.openbsd.org 2003/05/14 18:16:20
|
||||
[key.c key.h readconf.c readconf.h ssh_config.5 sshconnect.c]
|
||||
[dns.c dns.h README.dns ssh-keygen.1 ssh-keygen.c]
|
||||
add experimental support for verifying hos keys using DNS as described
|
||||
in draft-ietf-secsh-dns-xx.txt. more information in README.dns.
|
||||
ok markus@ and henning@
|
||||
|
||||
20030514
|
||||
- (djm) Bug #117: Don't lie to PAM about username
|
||||
|
@ -1479,4 +1485,4 @@
|
|||
save auth method before monitor_reset_key_state(); bugzilla bug #284;
|
||||
ok provos@
|
||||
|
||||
$Id: ChangeLog,v 1.2701 2003/05/15 00:16:21 djm Exp $
|
||||
$Id: ChangeLog,v 1.2702 2003/05/15 00:19:46 djm Exp $
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile.in,v 1.232 2003/05/14 04:31:11 djm Exp $
|
||||
# $Id: Makefile.in,v 1.233 2003/05/15 00:19:46 djm Exp $
|
||||
|
||||
# uncomment if you run a non bourne compatable shell. Ie. csh
|
||||
#SHELL = @SH@
|
||||
|
@ -62,11 +62,11 @@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keys
|
|||
|
||||
LIBSSH_OBJS=authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o \
|
||||
cipher.o compat.o compress.o crc32.o deattack.o fatal.o \
|
||||
hostfile.o log.o match.o mpaux.o nchan.o packet.o radix.o readpass.o \
|
||||
rsa.o tildexpand.o ttymodes.o xmalloc.o atomicio.o \
|
||||
hostfile.o log.o match.o mpaux.o nchan.o packet.o radix.o \
|
||||
readpass.o rsa.o tildexpand.o ttymodes.o xmalloc.o atomicio.o \
|
||||
key.o dispatch.o kex.o mac.o uuencode.o misc.o \
|
||||
rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o kexgex.o \
|
||||
kexdhc.o kexgexc.o scard.o msg.o progressmeter.o \
|
||||
kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
|
||||
entropy.o
|
||||
|
||||
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
How to verify host keys using OpenSSH and DNS
|
||||
---------------------------------------------
|
||||
|
||||
OpenSSH contains experimental support for verifying host keys using DNS
|
||||
as described in draft-ietf-secsh-dns-xx.txt. The document contains
|
||||
very brief instructions on how to test this feature. Configuring DNS
|
||||
and DNSSEC is out of the scope of this document.
|
||||
|
||||
|
||||
(1) Enable DNS fingerprint support in OpenSSH
|
||||
|
||||
Edit /usr/src/usr.bin/ssh/Makefile.inc and uncomment the line containing
|
||||
|
||||
CFLAGS+= -DDNS
|
||||
|
||||
|
||||
(2) Generate and publish the DNS RR
|
||||
|
||||
To create a DNS resource record (RR) containing a fingerprint of the
|
||||
public host key, use the following command:
|
||||
|
||||
ssh-keygen -r hostname -f keyfile -g
|
||||
|
||||
where "hostname" is your fully qualified hostname and "keyfile" is the
|
||||
file containing the public host key file. If you have multiple keys,
|
||||
you should generate one RR for each key.
|
||||
|
||||
In the example above, ssh-keygen will print the fingerprint in a
|
||||
generic DNS RR format parsable by most modern name server
|
||||
implementations. If your nameserver has support for the SSHFP RR, as
|
||||
defined by the draft, you can omit the -g flag and ssh-keygen will
|
||||
print a standard RR.
|
||||
|
||||
To publish the fingerprint using the DNS you must add the generated RR
|
||||
to your DNS zone file and sign your zone.
|
||||
|
||||
|
||||
(3) Enable the ssh client to verify host keys using DNS
|
||||
|
||||
To enable the ssh client to verify host keys using DNS, you have to
|
||||
add the following option to the ssh configuration file
|
||||
($HOME/.ssh/config or /etc/ssh/ssh_config):
|
||||
|
||||
VerifyHostKeyDNS yes
|
||||
|
||||
Upon connection the client will try to look up the fingerprint RR
|
||||
using DNS. If the fingerprint received from the DNS server matches
|
||||
the remote host key, the user will be notified.
|
||||
|
||||
|
||||
Jakob Schlyter
|
||||
Wesley Griffin
|
||||
|
||||
|
||||
$OpenBSD: README.dns,v 1.1 2003/05/14 18:16:20 jakob Exp $
|
|
@ -0,0 +1,293 @@
|
|||
/* $OpenBSD: dns.c,v 1.4 2003/05/14 23:29:22 jakob Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
|
||||
* Copyright (c) 2003 Jakob Schlyter. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifdef DNS
|
||||
#include <openssl/bn.h>
|
||||
#ifdef LWRES
|
||||
#include <lwres/netdb.h>
|
||||
#include <dns/result.h>
|
||||
#else /* LWRES */
|
||||
#include <netdb.h>
|
||||
#endif /* LWRES */
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "key.h"
|
||||
#include "dns.h"
|
||||
#include "log.h"
|
||||
#include "uuencode.h"
|
||||
|
||||
extern char *__progname;
|
||||
RCSID("$OpenBSD: dns.c,v 1.4 2003/05/14 23:29:22 jakob Exp $");
|
||||
|
||||
#ifndef LWRES
|
||||
static const char *errset_text[] = {
|
||||
"success", /* 0 ERRSET_SUCCESS */
|
||||
"out of memory", /* 1 ERRSET_NOMEMORY */
|
||||
"general failure", /* 2 ERRSET_FAIL */
|
||||
"invalid parameter", /* 3 ERRSET_INVAL */
|
||||
"name does not exist", /* 4 ERRSET_NONAME */
|
||||
"data does not exist", /* 5 ERRSET_NODATA */
|
||||
};
|
||||
|
||||
static const char *
|
||||
dns_result_totext(unsigned int error)
|
||||
{
|
||||
switch (error) {
|
||||
case ERRSET_SUCCESS:
|
||||
return errset_text[ERRSET_SUCCESS];
|
||||
case ERRSET_NOMEMORY:
|
||||
return errset_text[ERRSET_NOMEMORY];
|
||||
case ERRSET_FAIL:
|
||||
return errset_text[ERRSET_FAIL];
|
||||
case ERRSET_INVAL:
|
||||
return errset_text[ERRSET_INVAL];
|
||||
case ERRSET_NONAME:
|
||||
return errset_text[ERRSET_NONAME];
|
||||
case ERRSET_NODATA:
|
||||
return errset_text[ERRSET_NODATA];
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
}
|
||||
#endif /* LWRES */
|
||||
|
||||
|
||||
/*
|
||||
* Read SSHFP parameters from key buffer.
|
||||
*/
|
||||
static int
|
||||
dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
|
||||
u_char **digest, u_int *digest_len, Key *key)
|
||||
{
|
||||
int success = 0;
|
||||
|
||||
switch (key->type) {
|
||||
case KEY_RSA:
|
||||
*algorithm = SSHFP_KEY_RSA;
|
||||
break;
|
||||
case KEY_DSA:
|
||||
*algorithm = SSHFP_KEY_DSA;
|
||||
break;
|
||||
default:
|
||||
*algorithm = SSHFP_KEY_RESERVED;
|
||||
}
|
||||
|
||||
if (*algorithm) {
|
||||
*digest_type = SSHFP_HASH_SHA1;
|
||||
*digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len);
|
||||
success = 1;
|
||||
} else {
|
||||
*digest_type = SSHFP_HASH_RESERVED;
|
||||
*digest = NULL;
|
||||
*digest_len = 0;
|
||||
success = 0;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read SSHFP parameters from rdata buffer.
|
||||
*/
|
||||
static int
|
||||
dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
|
||||
u_char **digest, u_int *digest_len, u_char *rdata, int rdata_len)
|
||||
{
|
||||
int success = 0;
|
||||
|
||||
*algorithm = SSHFP_KEY_RESERVED;
|
||||
*digest_type = SSHFP_HASH_RESERVED;
|
||||
|
||||
if (rdata_len >= 2) {
|
||||
*algorithm = rdata[0];
|
||||
*digest_type = rdata[1];
|
||||
*digest_len = rdata_len - 2;
|
||||
|
||||
if (*digest_len > 0) {
|
||||
*digest = (u_char *) xmalloc(*digest_len);
|
||||
memcpy(*digest, rdata + 2, *digest_len);
|
||||
} else {
|
||||
*digest = NULL;
|
||||
}
|
||||
|
||||
success = 1;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Verify the given hostname, address and host key using DNS.
|
||||
* Returns 0 if key verifies or -1 if key does NOT verify
|
||||
*/
|
||||
int
|
||||
verify_host_key_dns(const char *hostname, struct sockaddr *address,
|
||||
Key *hostkey)
|
||||
{
|
||||
int counter;
|
||||
int result;
|
||||
struct rrsetinfo *fingerprints = NULL;
|
||||
int failures = 0;
|
||||
|
||||
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;
|
||||
u_int dnskey_digest_len;
|
||||
|
||||
|
||||
debug3("verify_hostkey_dns");
|
||||
if (hostkey == NULL)
|
||||
fatal("No key to look up!");
|
||||
|
||||
result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
|
||||
DNS_RDATATYPE_SSHFP, 0, &fingerprints);
|
||||
if (result) {
|
||||
verbose("DNS lookup error: %s", dns_result_totext(result));
|
||||
return DNS_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
#ifdef DNSSEC
|
||||
/* Only accept validated answers */
|
||||
if (!fingerprints->rri_flags & RRSET_VALIDATED) {
|
||||
error("Ignored unvalidated fingerprint from DNS.");
|
||||
return DNS_VERIFY_ERROR;
|
||||
}
|
||||
#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.");
|
||||
return DNS_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++) {
|
||||
/*
|
||||
* 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,
|
||||
fingerprints->rri_rdatas[counter].rdi_data,
|
||||
fingerprints->rri_rdatas[counter].rdi_length)) {
|
||||
verbose("Error parsing fingerprint from DNS.");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
|
||||
/* Matching algoritm and digest. */
|
||||
freerrset(fingerprints);
|
||||
#ifdef DNSSEC
|
||||
debug("matching host key fingerprint found in DNS");
|
||||
return DNS_VERIFY_OK;
|
||||
#else
|
||||
logit("Matching host key fingerprint found in DNS.");
|
||||
return DNS_VERIFY_ERROR;
|
||||
#endif
|
||||
} else {
|
||||
/* Correct algorithm but bad digest */
|
||||
debug("verify_hostkey_dns: failed");
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
debug("fingerprints found in DNS, but none of them matched");
|
||||
|
||||
return DNS_VERIFY_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Export the fingerprint of a key as a DNS resource record
|
||||
*/
|
||||
int
|
||||
export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
|
||||
{
|
||||
u_int8_t rdata_pubkey_algorithm = 0;
|
||||
u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
|
||||
u_char *rdata_digest;
|
||||
u_int rdata_digest_len;
|
||||
|
||||
int i;
|
||||
int success = 0;
|
||||
|
||||
if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
|
||||
&rdata_digest, &rdata_digest_len, key)) {
|
||||
|
||||
if (generic)
|
||||
fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname,
|
||||
DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len,
|
||||
rdata_pubkey_algorithm, rdata_digest_type);
|
||||
else
|
||||
fprintf(f, "%s IN SSHFP %d %d ", hostname,
|
||||
rdata_pubkey_algorithm, rdata_digest_type);
|
||||
|
||||
for (i = 0; i < rdata_digest_len; i++)
|
||||
fprintf(f, "%02x", rdata_digest[i]);
|
||||
fprintf(f, "\n");
|
||||
success = 1;
|
||||
} else {
|
||||
error("dns_export_rr: unsupported algorithm");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif /* DNS */
|
|
@ -0,0 +1,57 @@
|
|||
/* $OpenBSD: dns.h,v 1.3 2003/05/14 22:56:51 jakob Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
|
||||
* Copyright (c) 2003 Jakob Schlyter. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifdef DNS
|
||||
#ifndef DNS_H
|
||||
#define DNS_H
|
||||
|
||||
enum sshfp_types {
|
||||
SSHFP_KEY_RESERVED,
|
||||
SSHFP_KEY_RSA,
|
||||
SSHFP_KEY_DSA
|
||||
};
|
||||
|
||||
enum sshfp_hashes {
|
||||
SSHFP_HASH_RESERVED,
|
||||
SSHFP_HASH_SHA1
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
int verify_host_key_dns(const char *, struct sockaddr *, Key *);
|
||||
int export_dns_rr(const char *, Key *, FILE *, int);
|
||||
|
||||
#endif /* DNS_H */
|
||||
#endif /* DNS */
|
4
key.c
4
key.c
|
@ -32,7 +32,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: key.c,v 1.51 2003/02/12 09:33:04 markus Exp $");
|
||||
RCSID("$OpenBSD: key.c,v 1.52 2003/05/14 18:16:20 jakob Exp $");
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
|
@ -169,7 +169,7 @@ key_equal(Key *a, Key *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u_char *
|
||||
u_char*
|
||||
key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
|
||||
{
|
||||
const EVP_MD *md = NULL;
|
||||
|
|
3
key.h
3
key.h
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: key.h,v 1.20 2003/02/12 09:33:04 markus Exp $ */
|
||||
/* $OpenBSD: key.h,v 1.21 2003/05/14 18:16:20 jakob Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
|
@ -61,6 +61,7 @@ void key_free(Key *);
|
|||
Key *key_demote(Key *);
|
||||
int key_equal(Key *, Key *);
|
||||
char *key_fingerprint(Key *, enum fp_type, enum fp_rep);
|
||||
u_char *key_fingerprint_raw(Key *, enum fp_type, u_int *);
|
||||
char *key_type(Key *);
|
||||
int key_write(Key *, FILE *);
|
||||
int key_read(Key *, char **);
|
||||
|
|
12
readconf.c
12
readconf.c
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: readconf.c,v 1.106 2003/04/09 12:00:37 djm Exp $");
|
||||
RCSID("$OpenBSD: readconf.c,v 1.107 2003/05/14 18:16:20 jakob Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
|
@ -114,7 +114,7 @@ typedef enum {
|
|||
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
|
||||
oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
|
||||
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
|
||||
oEnableSSHKeysign, oRekeyLimit,
|
||||
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS,
|
||||
oDeprecated
|
||||
} OpCodes;
|
||||
|
||||
|
@ -187,6 +187,7 @@ static struct {
|
|||
{ "smartcarddevice", oSmartcardDevice },
|
||||
{ "clearallforwardings", oClearAllForwardings },
|
||||
{ "enablesshkeysign", oEnableSSHKeysign },
|
||||
{ "verifyhostkeydns", oVerifyHostKeyDNS },
|
||||
{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
|
||||
{ "rekeylimit", oRekeyLimit },
|
||||
{ NULL, oBadOption }
|
||||
|
@ -392,6 +393,10 @@ parse_flag:
|
|||
intptr = &options->check_host_ip;
|
||||
goto parse_flag;
|
||||
|
||||
case oVerifyHostKeyDNS:
|
||||
intptr = &options->verify_host_key_dns;
|
||||
goto parse_flag;
|
||||
|
||||
case oStrictHostKeyChecking:
|
||||
intptr = &options->strict_host_key_checking;
|
||||
arg = strdelim(&s);
|
||||
|
@ -829,6 +834,7 @@ initialize_options(Options * options)
|
|||
options->enable_ssh_keysign = - 1;
|
||||
options->no_host_authentication_for_localhost = - 1;
|
||||
options->rekey_limit = - 1;
|
||||
options->verify_host_key_dns = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -947,6 +953,8 @@ fill_default_options(Options * options)
|
|||
options->enable_ssh_keysign = 0;
|
||||
if (options->rekey_limit == -1)
|
||||
options->rekey_limit = 0;
|
||||
if (options->verify_host_key_dns == -1)
|
||||
options->verify_host_key_dns = 0;
|
||||
/* options->proxy_command should not be set by default */
|
||||
/* options->user will be set in the main program if appropriate */
|
||||
/* options->hostname will be set in the main program if appropriate */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: readconf.h,v 1.47 2003/04/02 09:48:07 markus Exp $ */
|
||||
/* $OpenBSD: readconf.h,v 1.48 2003/05/14 18:16:20 jakob Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -86,6 +86,7 @@ typedef struct {
|
|||
char *preferred_authentications;
|
||||
char *bind_address; /* local socket address for connection to sshd */
|
||||
char *smartcard_device; /* Smartcard reader device */
|
||||
int verify_host_key_dns; /* Verify host key using DNS */
|
||||
|
||||
int num_identity_files; /* Number of files for RSA/DSA identities. */
|
||||
char *identity_files[SSH_MAX_IDENTITY_FILES];
|
||||
|
|
11
ssh-keygen.1
11
ssh-keygen.1
|
@ -1,4 +1,4 @@
|
|||
.\" $OpenBSD: ssh-keygen.1,v 1.56 2003/03/28 10:11:43 jmc Exp $
|
||||
.\" $OpenBSD: ssh-keygen.1,v 1.57 2003/05/14 18:16:20 jakob Exp $
|
||||
.\"
|
||||
.\" -*- nroff -*-
|
||||
.\"
|
||||
|
@ -83,6 +83,10 @@
|
|||
.Nm ssh-keygen
|
||||
.Fl U Ar reader
|
||||
.Op Fl f Ar input_keyfile
|
||||
.Nm ssh-keygen
|
||||
.Fl r Ar hostname
|
||||
.Op Fl f Ar input_keyfile
|
||||
.Op Fl g
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
generates, manages and converts authentication keys for
|
||||
|
@ -163,6 +167,8 @@ print the key in a
|
|||
to stdout.
|
||||
This option allows exporting keys for use by several commercial
|
||||
SSH implementations.
|
||||
.It Fl g
|
||||
Use generic DNS resource record format.
|
||||
.It Fl f Ar filename
|
||||
Specifies the filename of the key file.
|
||||
.It Fl i
|
||||
|
@ -218,6 +224,9 @@ Provides the (old) passphrase.
|
|||
.It Fl U Ar reader
|
||||
Upload an existing RSA private key into the smartcard in
|
||||
.Ar reader .
|
||||
.It Fl r Ar hostname
|
||||
Print DNS resource record with the specified
|
||||
.Ar hostname .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width Ds
|
||||
|
|
55
ssh-keygen.c
55
ssh-keygen.c
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh-keygen.c,v 1.104 2003/05/11 16:56:48 markus Exp $");
|
||||
RCSID("$OpenBSD: ssh-keygen.c,v 1.105 2003/05/14 18:16:20 jakob Exp $");
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
|
@ -70,6 +70,7 @@ char *identity_comment = NULL;
|
|||
int convert_to_ssh2 = 0;
|
||||
int convert_from_ssh2 = 0;
|
||||
int print_public = 0;
|
||||
int print_generic = 0;
|
||||
|
||||
char *key_type_name = NULL;
|
||||
|
||||
|
@ -620,6 +621,38 @@ do_change_passphrase(struct passwd *pw)
|
|||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef DNS
|
||||
/*
|
||||
* Print the SSHFP RR.
|
||||
*/
|
||||
static void
|
||||
do_print_resource_record(struct passwd *pw, char *hostname)
|
||||
{
|
||||
Key *public;
|
||||
char *comment = NULL;
|
||||
struct stat st;
|
||||
|
||||
if (!have_identity)
|
||||
ask_filename(pw, "Enter file in which the key is");
|
||||
if (stat(identity_file, &st) < 0) {
|
||||
perror(identity_file);
|
||||
exit(1);
|
||||
}
|
||||
public = key_load_public(identity_file, &comment);
|
||||
if (public != NULL) {
|
||||
export_dns_rr(hostname, public, stdout, print_generic);
|
||||
key_free(public);
|
||||
xfree(comment);
|
||||
exit(0);
|
||||
}
|
||||
if (comment)
|
||||
xfree(comment);
|
||||
|
||||
printf("failed to read v2 public key from %s.\n", identity_file);
|
||||
exit(1);
|
||||
}
|
||||
#endif /* DNS */
|
||||
|
||||
/*
|
||||
* Change the comment of a private key file.
|
||||
*/
|
||||
|
@ -726,6 +759,7 @@ usage(void)
|
|||
fprintf(stderr, " -c Change comment in private and public key files.\n");
|
||||
fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n");
|
||||
fprintf(stderr, " -f filename Filename of the key file.\n");
|
||||
fprintf(stderr, " -g Use generic DNS resource record format.\n");
|
||||
fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n");
|
||||
fprintf(stderr, " -l Show fingerprint of key file.\n");
|
||||
fprintf(stderr, " -p Change passphrase of private key file.\n");
|
||||
|
@ -736,6 +770,9 @@ usage(void)
|
|||
fprintf(stderr, " -C comment Provide new comment.\n");
|
||||
fprintf(stderr, " -N phrase Provide new passphrase.\n");
|
||||
fprintf(stderr, " -P phrase Provide old passphrase.\n");
|
||||
#ifdef DNS
|
||||
fprintf(stderr, " -r hostname Print DNS resource record.\n");
|
||||
#endif /* DNS */
|
||||
#ifdef SMARTCARD
|
||||
fprintf(stderr, " -D reader Download public key from smartcard.\n");
|
||||
fprintf(stderr, " -U reader Upload private key to smartcard.\n");
|
||||
|
@ -752,6 +789,7 @@ main(int ac, char **av)
|
|||
{
|
||||
char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
|
||||
char *reader_id = NULL;
|
||||
char *resource_record_hostname = NULL;
|
||||
Key *private, *public;
|
||||
struct passwd *pw;
|
||||
struct stat st;
|
||||
|
@ -778,7 +816,7 @@ main(int ac, char **av)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:U:D:P:N:C:")) != -1) {
|
||||
while ((opt = getopt(ac, av, "degiqpclBRxXyb:f:t:U:D:P:N:C:r:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
bits = atoi(optarg);
|
||||
|
@ -803,6 +841,9 @@ main(int ac, char **av)
|
|||
strlcpy(identity_file, optarg, sizeof(identity_file));
|
||||
have_identity = 1;
|
||||
break;
|
||||
case 'g':
|
||||
print_generic = 1;
|
||||
break;
|
||||
case 'P':
|
||||
identity_passphrase = optarg;
|
||||
break;
|
||||
|
@ -843,6 +884,9 @@ main(int ac, char **av)
|
|||
case 'U':
|
||||
reader_id = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
resource_record_hostname = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
|
@ -868,6 +912,13 @@ main(int ac, char **av)
|
|||
do_convert_from_ssh2(pw);
|
||||
if (print_public)
|
||||
do_print_public(pw);
|
||||
if (resource_record_hostname != NULL) {
|
||||
#ifdef DNS
|
||||
do_print_resource_record(pw, resource_record_hostname);
|
||||
#else /* DNS */
|
||||
fatal("no DNS support.");
|
||||
#endif /* DNS */
|
||||
}
|
||||
if (reader_id != NULL) {
|
||||
#ifdef SMARTCARD
|
||||
if (download)
|
||||
|
|
|
@ -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.7 2003/03/28 10:11:43 jmc Exp $
|
||||
.\" $OpenBSD: ssh_config.5,v 1.8 2003/05/14 18:16:20 jakob Exp $
|
||||
.Dd September 25, 1999
|
||||
.Dt SSH_CONFIG 5
|
||||
.Os
|
||||
|
@ -618,6 +618,11 @@ having to remember to give the user name on the command line.
|
|||
Specifies a file to use for the user
|
||||
host key database instead of
|
||||
.Pa $HOME/.ssh/known_hosts .
|
||||
.It Cm VerifyHostKeyDNS
|
||||
Specifies whether to verify the remote key using DNS and SSHFP resource
|
||||
records.
|
||||
The default is
|
||||
.Dq no .
|
||||
.It Cm XAuthLocation
|
||||
Specifies the full pathname of the
|
||||
.Xr xauth 1
|
||||
|
|
23
sshconnect.c
23
sshconnect.c
|
@ -13,7 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshconnect.c,v 1.139 2003/04/14 14:17:50 markus Exp $");
|
||||
RCSID("$OpenBSD: sshconnect.c,v 1.140 2003/05/14 18:16:21 jakob Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
|
@ -33,6 +33,10 @@ RCSID("$OpenBSD: sshconnect.c,v 1.139 2003/04/14 14:17:50 markus Exp $");
|
|||
#include "misc.h"
|
||||
#include "readpass.h"
|
||||
|
||||
#ifdef DNS
|
||||
#include "dns.h"
|
||||
#endif
|
||||
|
||||
char *client_version_string = NULL;
|
||||
char *server_version_string = NULL;
|
||||
|
||||
|
@ -797,11 +801,28 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* returns 0 if key verifies or -1 if key does NOT verify */
|
||||
int
|
||||
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
#ifdef DNS
|
||||
if (options.verify_host_key_dns) {
|
||||
switch(verify_host_key_dns(host, hostaddr, host_key)) {
|
||||
case DNS_VERIFY_OK:
|
||||
return 0;
|
||||
case DNS_VERIFY_FAILED:
|
||||
return -1;
|
||||
case DNS_VERIFY_ERROR:
|
||||
break;
|
||||
default:
|
||||
debug3("bad return value from verify_host_key_dns");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* DNS */
|
||||
|
||||
/* return ok if the key can be found in an old keyfile */
|
||||
if (stat(options.system_hostfile2, &st) == 0 ||
|
||||
stat(options.user_hostfile2, &st) == 0) {
|
||||
|
|
Loading…
Reference in New Issue