diff --git a/ChangeLog b/ChangeLog index 73954735a..7125eaa1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,11 @@ [PROTOCOL.certkeys ssh-keygen.c] tighten the rules for certificate encoding by requiring that options appear in lexical order and make our ssh-keygen comply. ok markus@ + - djm@cvs.openbsd.org 2010/08/04 05:42:47 + [auth.c auth2-hostbased.c authfile.c authfile.h ssh-keysign.8] + [ssh-keysign.c ssh.c] + enable certificates for hostbased authentication, from Iain Morgan; + "looks ok" markus@ 20100903 - (dtucker) [monitor.c] Bug #1795: Initialize the values to be returned from diff --git a/auth.c b/auth.c index d1727a4a9..a27667f42 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.88 2010/06/22 04:49:47 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.89 2010/08/04 05:42:47 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -385,7 +385,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, HostStatus host_status; /* Check if we know the host and its host key. */ - found = key_new(key->type); + found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); host_status = check_host_in_hostfile(sysfile, host, key, found, NULL); if (host_status != HOST_OK && userfile != NULL) { diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 721646520..cdf442f97 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.13 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.14 2010/08/04 05:42:47 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -141,9 +141,10 @@ int hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, Key *key) { - const char *resolvedname, *ipaddr, *lookup; + const char *resolvedname, *ipaddr, *lookup, *reason; HostStatus host_status; int len; + char *fp; if (auth_key_is_revoked(key)) return 0; @@ -174,16 +175,40 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, } debug2("userauth_hostbased: access allowed by auth_rhosts2"); + if (key_is_cert(key) && + key_cert_check_authority(key, 1, 0, lookup, &reason)) { + error("%s", reason); + auth_debug_add("%s", reason); + return 0; + } + host_status = check_key_in_hostfiles(pw, key, lookup, _PATH_SSH_SYSTEM_HOSTFILE, options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); /* backward compat if no key has been found. */ - if (host_status == HOST_NEW) + if (host_status == HOST_NEW) { host_status = check_key_in_hostfiles(pw, key, lookup, _PATH_SSH_SYSTEM_HOSTFILE2, options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE2); + } + + if (host_status == HOST_OK) { + if (key_is_cert(key)) { + fp = key_fingerprint(key->cert->signature_key, + SSH_FP_MD5, SSH_FP_HEX); + verbose("Accepted certificate ID \"%s\" signed by " + "%s CA %s from %s@%s", key->cert->key_id, + key_type(key->cert->signature_key), fp, + cuser, lookup); + } else { + fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + verbose("Accepted %s public key %s from %s@%s", + key_type(key), fp, cuser, lookup); + } + xfree(fp); + } return (host_status == HOST_OK); } diff --git a/authfile.c b/authfile.c index 224c6aa80..6bf41db9a 100644 --- a/authfile.c +++ b/authfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.c,v 1.80 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: authfile.c,v 1.81 2010/08/04 05:42:47 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -693,6 +693,64 @@ key_load_public(const char *filename, char **commentp) return NULL; } +/* Load the certificate associated with the named private key */ +Key * +key_load_cert(const char *filename) +{ + Key *pub; + char file[MAXPATHLEN]; + + pub = key_new(KEY_UNSPEC); + if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && + (strlcat(file, "-cert.pub", sizeof file) < sizeof(file)) && + (key_try_load_public(pub, file, NULL) == 1)) + return pub; + key_free(pub); + return NULL; +} + +/* Load private key and certificate */ +Key * +key_load_private_cert(int type, const char *filename, const char *passphrase, + int *perm_ok) +{ + Key *key, *pub; + + switch (type) { + case KEY_RSA: + case KEY_DSA: + break; + default: + error("%s: unsupported key type", __func__); + return NULL; + } + + if ((key = key_load_private_type(type, filename, + passphrase, NULL, perm_ok)) == NULL) + return NULL; + + if ((pub = key_load_cert(filename)) == NULL) { + key_free(key); + return NULL; + } + + /* Make sure the private key matches the certificate */ + if (key_equal_public(key, pub) == 0) { + error("%s: certificate does not match private key %s", + __func__, filename); + } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) { + error("%s: key_to_certified failed", __func__); + } else { + key_cert_copy(pub, key); + key_free(pub); + return key; + } + + key_free(key); + key_free(pub); + return NULL; +} + /* * Returns 1 if the specified "key" is listed in the file "filename", * 0 if the key is not listed or -1 on error. diff --git a/authfile.h b/authfile.h index 6dfa478e7..6745dc062 100644 --- a/authfile.h +++ b/authfile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.h,v 1.14 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: authfile.h,v 1.15 2010/08/04 05:42:47 djm Exp $ */ /* * Author: Tatu Ylonen @@ -16,9 +16,11 @@ #define AUTHFILE_H int key_save_private(Key *, const char *, const char *, const char *); +Key *key_load_cert(const char *); Key *key_load_public(const char *, char **); Key *key_load_public_type(int, const char *, char **); Key *key_load_private(const char *, const char *, char **); +Key *key_load_private_cert(int, const char *, const char *, int *); Key *key_load_private_type(int, const char *, const char *, char **, int *); Key *key_load_private_pem(int, int, const char *, char **); int key_perm_ok(int, const char *); diff --git a/ssh-keysign.8 b/ssh-keysign.8 index 3ba54b935..46c0ee9cd 100644 --- a/ssh-keysign.8 +++ b/ssh-keysign.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keysign.8,v 1.9 2007/05/31 19:20:16 jmc Exp $ +.\" $OpenBSD: ssh-keysign.8,v 1.10 2010/08/04 05:42:47 djm Exp $ .\" .\" Copyright (c) 2002 Markus Friedl. All rights reserved. .\" @@ -22,7 +22,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. .\" -.Dd $Mdocdate: May 31 2007 $ +.Dd $Mdocdate: August 4 2010 $ .Dt SSH-KEYSIGN 8 .Os .Sh NAME @@ -68,6 +68,9 @@ accessible to others. Since they are readable only by root, .Nm must be set-uid root if host-based authentication is used. +.It Pa /etc/ssh/ssh_host_dsa_key-cert.pub, /etc/ssh/ssh_host_rsa_key-cert.pub +If these files exist they are assumed to contain public certificate +information corresponding with the private keys above. .El .Sh SEE ALSO .Xr ssh 1 , diff --git a/ssh-keysign.c b/ssh-keysign.c index 0fdcebbd2..2f6ac99ab 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keysign.c,v 1.30 2010/01/13 01:20:20 dtucker Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.31 2010/08/04 05:42:47 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -232,7 +232,7 @@ main(int argc, char **argv) found = 0; for (i = 0; i < 2; i++) { if (keys[i] != NULL && - key_equal(key, keys[i])) { + key_equal_public(key, keys[i])) { found = 1; break; } diff --git a/ssh.c b/ssh.c index 249be2db8..ab37c205d 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.344 2010/07/19 09:15:12 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.345 2010/08/04 05:42:47 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -774,26 +774,34 @@ main(int ac, char **av) sensitive_data.external_keysign = 0; if (options.rhosts_rsa_authentication || options.hostbased_authentication) { - sensitive_data.nkeys = 3; + sensitive_data.nkeys = 5; sensitive_data.keys = xcalloc(sensitive_data.nkeys, sizeof(Key)); PRIV_START; sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, _PATH_HOST_KEY_FILE, "", NULL, NULL); - sensitive_data.keys[1] = key_load_private_type(KEY_DSA, + sensitive_data.keys[1] = key_load_private_cert(KEY_DSA, + _PATH_HOST_DSA_KEY_FILE, "", NULL); + sensitive_data.keys[2] = key_load_private_cert(KEY_RSA, + _PATH_HOST_RSA_KEY_FILE, "", NULL); + sensitive_data.keys[3] = key_load_private_type(KEY_DSA, _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); - sensitive_data.keys[2] = key_load_private_type(KEY_RSA, + sensitive_data.keys[4] = key_load_private_type(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); PRIV_END; if (options.hostbased_authentication == 1 && sensitive_data.keys[0] == NULL && - sensitive_data.keys[1] == NULL && - sensitive_data.keys[2] == NULL) { - sensitive_data.keys[1] = key_load_public( + sensitive_data.keys[3] == NULL && + sensitive_data.keys[4] == NULL) { + sensitive_data.keys[1] = key_load_cert( + _PATH_HOST_DSA_KEY_FILE); + sensitive_data.keys[2] = key_load_cert( + _PATH_HOST_RSA_KEY_FILE); + sensitive_data.keys[3] = key_load_public( _PATH_HOST_DSA_KEY_FILE, NULL); - sensitive_data.keys[2] = key_load_public( + sensitive_data.keys[4] = key_load_public( _PATH_HOST_RSA_KEY_FILE, NULL); sensitive_data.external_keysign = 1; }