- djm@cvs.openbsd.org 2005/03/01 10:40:27

[hostfile.c hostfile.h readconf.c readconf.h ssh.1 ssh_config.5]
     [sshconnect.c sshd.8]
     add support for hashing host names and addresses added to known_hosts
     files, to improve privacy of which hosts user have been visiting; ok
     markus@ deraadt@
This commit is contained in:
Damien Miller 2005-03-01 21:47:37 +11:00
parent f91ee4c3de
commit e1776155d1
9 changed files with 180 additions and 18 deletions

View File

@ -27,6 +27,12 @@
Patch originally by Dan Astorian, but worked on by several people
Adds GatewayPorts=clientspecified option on server to allow remote
forwards to bind to client-specified ports.
- djm@cvs.openbsd.org 2005/03/01 10:40:27
[hostfile.c hostfile.h readconf.c readconf.h ssh.1 ssh_config.5]
[sshconnect.c sshd.8]
add support for hashing host names and addresses added to known_hosts
files, to improve privacy of which hosts user have been visiting; ok
markus@ deraadt@
20050226
- (dtucker) [openbsd-compat/bsd-openpty.c openbsd-compat/inet_ntop.c]
@ -2203,4 +2209,4 @@
- (djm) Trim deprecated options from INSTALL. Mention UsePAM
- (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
$Id: ChangeLog,v 1.3672 2005/03/01 10:24:33 djm Exp $
$Id: ChangeLog,v 1.3673 2005/03/01 10:47:37 djm Exp $

View File

@ -36,13 +36,102 @@
*/
#include "includes.h"
RCSID("$OpenBSD: hostfile.c,v 1.32 2003/11/10 16:23:41 jakob Exp $");
RCSID("$OpenBSD: hostfile.c,v 1.33 2005/03/01 10:40:26 djm Exp $");
#include <resolv.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include "packet.h"
#include "match.h"
#include "key.h"
#include "hostfile.h"
#include "log.h"
#include "xmalloc.h"
static int
extract_salt(const char *s, u_int l, char *salt, size_t salt_len)
{
char *p, *b64salt;
u_int b64len;
int ret;
if (l < sizeof(HASH_MAGIC) - 1) {
debug2("extract_salt: string too short");
return (-1);
}
if (strncmp(s, HASH_MAGIC, sizeof(HASH_MAGIC) - 1) != 0) {
debug2("extract_salt: invalid magic identifier");
return (-1);
}
s += sizeof(HASH_MAGIC) - 1;
l -= sizeof(HASH_MAGIC) - 1;
if ((p = memchr(s, HASH_DELIM, l)) == NULL) {
debug2("extract_salt: missing salt termination character");
return (-1);
}
b64len = p - s;
/* Sanity check */
if (b64len == 0 || b64len > 1024) {
debug2("extract_salt: bad encoded salt length %u", b64len);
return (-1);
}
b64salt = xmalloc(1 + b64len);
memcpy(b64salt, s, b64len);
b64salt[b64len] = '\0';
ret = __b64_pton(b64salt, salt, salt_len);
xfree(b64salt);
if (ret == -1) {
debug2("extract_salt: salt decode error");
return (-1);
}
if (ret != SHA_DIGEST_LENGTH) {
debug2("extract_salt: expected salt len %u, got %u",
salt_len, ret);
return (-1);
}
return (0);
}
char *
host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
{
const EVP_MD *md = EVP_sha1();
HMAC_CTX mac_ctx;
char salt[256], result[256], uu_salt[512], uu_result[512];
static char encoded[1024];
u_int i, len;
len = EVP_MD_size(md);
if (name_from_hostfile == NULL) {
/* Create new salt */
for (i = 0; i < len; i++)
salt[i] = arc4random();
} else {
/* Extract salt from known host entry */
if (extract_salt(name_from_hostfile, src_len, salt,
sizeof(salt)) == -1)
return (NULL);
}
HMAC_Init(&mac_ctx, salt, len, md);
HMAC_Update(&mac_ctx, host, strlen(host));
HMAC_Final(&mac_ctx, result, NULL);
HMAC_cleanup(&mac_ctx);
if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 ||
__b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1)
fatal("host_hash: __b64_ntop failed");
snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt,
HASH_DELIM, uu_result);
return (encoded);
}
/*
* Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the
@ -104,7 +193,7 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
char line[8192];
int linenum = 0;
u_int kbits;
char *cp, *cp2;
char *cp, *cp2, *hashed_host;
HostStatus end_return;
debug3("check_host_in_hostfile: filename %s", filename);
@ -137,8 +226,18 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
;
/* Check if the host name matches. */
if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1)
continue;
if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1) {
if (*cp != HASH_DELIM)
continue;
hashed_host = host_hash(host, cp, (u_int) (cp2 - cp));
if (hashed_host == NULL) {
debug("Invalid hashed host line %d of %s",
linenum, filename);
continue;
}
if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0)
continue;
}
/* Got a match. Skip host name. */
cp = cp2;
@ -211,16 +310,28 @@ lookup_key_in_hostfile_by_type(const char *filename, const char *host,
*/
int
add_host_to_hostfile(const char *filename, const char *host, const Key *key)
add_host_to_hostfile(const char *filename, const char *host, const Key *key,
int store_hash)
{
FILE *f;
int success = 0;
char *hashed_host;
if (key == NULL)
return 1; /* XXX ? */
f = fopen(filename, "a");
if (!f)
return 0;
fprintf(f, "%s ", host);
if (store_hash) {
if ((hashed_host = host_hash(host, NULL, 0)) == NULL) {
error("add_host_to_hostfile: host_hash failed");
fclose(f);
return 0;
}
}
fprintf(f, "%s ", store_hash ? hashed_host : host);
if (key_write(key, f)) {
success = 1;
} else {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: hostfile.h,v 1.14 2003/11/10 16:23:41 jakob Exp $ */
/* $OpenBSD: hostfile.h,v 1.15 2005/03/01 10:40:26 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -21,8 +21,13 @@ typedef enum {
int hostfile_read_key(char **, u_int *, Key *);
HostStatus check_host_in_hostfile(const char *, const char *,
const Key *, Key *, int *);
int add_host_to_hostfile(const char *, const char *, const Key *);
int add_host_to_hostfile(const char *, const char *, const Key *, int);
int lookup_key_in_hostfile_by_type(const char *, const char *,
int, Key *, int *);
#define HASH_MAGIC "|1|"
#define HASH_DELIM '|'
char *host_hash(const char *, const char *, u_int);
#endif

View File

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: readconf.c,v 1.135 2005/03/01 10:09:52 djm Exp $");
RCSID("$OpenBSD: readconf.c,v 1.136 2005/03/01 10:40:26 djm Exp $");
#include "ssh.h"
#include "xmalloc.h"
@ -106,7 +106,7 @@ typedef enum {
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oControlPath, oControlMaster,
oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
oDeprecated, oUnsupported
} OpCodes;
@ -197,6 +197,7 @@ static struct {
{ "sendenv", oSendEnv },
{ "controlpath", oControlPath },
{ "controlmaster", oControlMaster },
{ "hashknownhosts", oHashKnownHosts },
{ NULL, oBadOption }
};
@ -790,6 +791,10 @@ parse_int:
intptr = &options->control_master;
goto parse_yesnoask;
case oHashKnownHosts:
intptr = &options->hash_known_hosts;
goto parse_flag;
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@ -933,6 +938,7 @@ initialize_options(Options * options)
options->num_send_env = 0;
options->control_path = NULL;
options->control_master = -1;
options->hash_known_hosts = -1;
}
/*
@ -1055,6 +1061,8 @@ fill_default_options(Options * options)
options->server_alive_count_max = 3;
if (options->control_master == -1)
options->control_master = 0;
if (options->hash_known_hosts == -1)
options->hash_known_hosts = 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 */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.65 2005/03/01 10:09:52 djm Exp $ */
/* $OpenBSD: readconf.h,v 1.66 2005/03/01 10:40:27 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -112,6 +112,8 @@ typedef struct {
char *control_path;
int control_master;
int hash_known_hosts;
} Options;

3
ssh.1
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.1,v 1.200 2005/03/01 10:09:52 djm Exp $
.\" $OpenBSD: ssh.1,v 1.201 2005/03/01 10:40:27 djm Exp $
.Dd September 25, 1999
.Dt SSH 1
.Os
@ -701,6 +701,7 @@ For full details of the options listed below, and their possible values, see
.It GlobalKnownHostsFile
.It GSSAPIAuthentication
.It GSSAPIDelegateCredentials
.It HashKnownHosts
.It Host
.It HostbasedAuthentication
.It HostKeyAlgorithms

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.43 2005/03/01 10:09:52 djm Exp $
.\" $OpenBSD: ssh_config.5,v 1.44 2005/03/01 10:40:27 djm Exp $
.Dd September 25, 1999
.Dt SSH_CONFIG 5
.Os
@ -407,6 +407,21 @@ Forward (delegate) credentials to the server.
The default is
.Dq no .
Note that this option applies to protocol version 2 only.
.It Cm HashKnownHosts
Indicates that
.Nm ssh
should hash host names and addresses when they are added to
.Pa $HOME/.ssh/known_hosts .
These hashed names may be used normally by
.Nm ssh
and
.Nm sshd ,
but they do not reveal identifying information should the file's contents
be disclosed.
The default is
.Dq no .
Note that hashing of names and addresses will not be retrospectively applied
to existing known hosts files.
.It Cm HostbasedAuthentication
Specifies whether to try rhosts based authentication with public key
authentication.

View File

@ -13,7 +13,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect.c,v 1.159 2005/01/05 08:51:32 markus Exp $");
RCSID("$OpenBSD: sshconnect.c,v 1.160 2005/03/01 10:40:27 djm Exp $");
#include <openssl/bn.h>
@ -678,7 +678,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
"'%.128s' not in list of known hosts.",
type, ip);
else if (!add_host_to_hostfile(user_hostfile, ip,
host_key))
host_key, options.hash_known_hosts))
logit("Failed to add the %s host key for IP "
"address '%.128s' to the list of known "
"hosts (%.30s).", type, ip, user_hostfile);
@ -744,7 +744,8 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
* If not in strict mode, add the key automatically to the
* local known_hosts file.
*/
if (!add_host_to_hostfile(user_hostfile, hostp, host_key))
if (!add_host_to_hostfile(user_hostfile, hostp, host_key,
options.hash_known_hosts))
logit("Failed to add the host to the list of known "
"hosts (%.500s).", user_hostfile);
else

15
sshd.8
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: sshd.8,v 1.204 2005/02/25 10:55:13 jmc Exp $
.\" $OpenBSD: sshd.8,v 1.205 2005/03/01 10:40:27 djm Exp $
.Dd September 25, 1999
.Dt SSHD 8
.Os
@ -553,6 +553,14 @@ to indicate negation: if the host name matches a negated
pattern, it is not accepted (by that line) even if it matched another
pattern on the line.
.Pp
Alternately, hostnames may be stored in a hashed form which hides host names
and addresses should the file's contents be disclosed. Hashed hostnames start
with a
.Ql \&|
character.
Only one hashed hostname may appear on a single line and none of the above
negation or wildcard operators may be applied.
.Pp
Bits, exponent, and modulus are taken directly from the RSA host key; they
can be obtained, e.g., from
.Pa /etc/ssh/ssh_host_key.pub .
@ -584,6 +592,11 @@ and adding the host names at the front.
closenet,...,130.233.208.41 1024 37 159...93 closenet.hut.fi
cvs.openbsd.org,199.185.137.3 ssh-rsa AAAA1234.....=
.Ed
.Bd -literal
# A hashed hostname
|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa
AAAA1234.....=
.Ed
.Sh FILES
.Bl -tag -width Ds
.It Pa /etc/ssh/sshd_config