enable certificates for hostbased authentication, from Iain Morgan;
authordjm <djm@openbsd.org>
Wed, 4 Aug 2010 05:42:47 +0000 (05:42 +0000)
committerdjm <djm@openbsd.org>
Wed, 4 Aug 2010 05:42:47 +0000 (05:42 +0000)
"looks ok" markus@

usr.bin/ssh/auth.c
usr.bin/ssh/auth2-hostbased.c
usr.bin/ssh/authfile.c
usr.bin/ssh/authfile.h
usr.bin/ssh/ssh-keysign.8
usr.bin/ssh/ssh-keysign.c
usr.bin/ssh/ssh.c

index f391930..d264f2f 100644 (file)
@@ -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.
  *
@@ -295,7 +295,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) {
index 882651c..c10cb32 100644 (file)
@@ -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.
  *
@@ -140,9 +140,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;
@@ -173,16 +174,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);
 }
index 3726f51..ffc2100 100644 (file)
@@ -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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -681,6 +681,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.
index 6dfa478..6745dc0 100644 (file)
@@ -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 <ylo@cs.hut.fi>
 #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 *);
index 3ba54b9..46c0ee9 100644 (file)
@@ -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 ,
index 47cbd3f..298a90f 100644 (file)
@@ -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.
  *
@@ -223,7 +223,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;
                }
index 0c18fec..dc49752 100644 (file)
@@ -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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -755,26 +755,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;
                }