PubkeyAuthentication=yes|no|unbound|host-bound
authordjm <djm@openbsd.org>
Sun, 19 Dec 2021 22:14:47 +0000 (22:14 +0000)
committerdjm <djm@openbsd.org>
Sun, 19 Dec 2021 22:14:47 +0000 (22:14 +0000)
Allow control over which pubkey methods are used. Added out of
concern that some hardware devices may have difficulty signing
the longer pubkey authentication challenges. This provides a
way for them to disable the extension. It's also handy for
testing.

feedback / ok markus@

usr.bin/ssh/readconf.c
usr.bin/ssh/readconf.h
usr.bin/ssh/sshconnect2.c

index 5324d4f..0365dc6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.363 2021/09/16 05:36:03 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.364 2021/12/19 22:14:47 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -876,6 +876,15 @@ static const struct multistate multistate_canonicalizehostname[] = {
        { "always",                     SSH_CANONICALISE_ALWAYS },
        { NULL, -1 }
 };
+static const struct multistate multistate_pubkey_auth[] = {
+       { "true",                       SSH_PUBKEY_AUTH_ALL },
+       { "false",                      SSH_PUBKEY_AUTH_NO },
+       { "yes",                        SSH_PUBKEY_AUTH_ALL },
+       { "no",                         SSH_PUBKEY_AUTH_NO },
+       { "unbound",                    SSH_PUBKEY_AUTH_UNBOUND },
+       { "host-bound",                 SSH_PUBKEY_AUTH_HBOUND },
+       { NULL, -1 }
+};
 static const struct multistate multistate_compression[] = {
 #ifdef WITH_ZLIB
        { "yes",                        COMP_ZLIB },
@@ -1088,8 +1097,9 @@ parse_time:
                goto parse_string;
 
        case oPubkeyAuthentication:
+               multistate_ptr = multistate_pubkey_auth;
                intptr = &options->pubkey_authentication;
-               goto parse_flag;
+               goto parse_multistate;
 
        case oHostbasedAuthentication:
                intptr = &options->hostbased_authentication;
@@ -2473,7 +2483,7 @@ fill_default_options(Options * options)
        if (options->fwd_opts.streamlocal_bind_unlink == -1)
                options->fwd_opts.streamlocal_bind_unlink = 0;
        if (options->pubkey_authentication == -1)
-               options->pubkey_authentication = 1;
+               options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
        if (options->gss_authentication == -1)
                options->gss_authentication = 0;
        if (options->gss_deleg_creds == -1)
@@ -3116,6 +3126,8 @@ fmt_intarg(OpCodes code, int val)
                return fmt_multistate_int(val, multistate_canonicalizehostname);
        case oAddKeysToAgent:
                return fmt_multistate_int(val, multistate_yesnoaskconfirm);
+       case oPubkeyAuthentication:
+               return fmt_multistate_int(val, multistate_pubkey_auth);
        case oFingerprintHash:
                return ssh_digest_alg_name(val);
        default:
index f24719f..ded13c9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.145 2021/09/15 06:56:01 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.146 2021/12/19 22:14:47 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -179,6 +179,11 @@ typedef struct {
        char    *ignored_unknown; /* Pattern list of unknown tokens to ignore */
 }       Options;
 
+#define SSH_PUBKEY_AUTH_NO     0x00
+#define SSH_PUBKEY_AUTH_UNBOUND        0x01
+#define SSH_PUBKEY_AUTH_HBOUND 0x02
+#define SSH_PUBKEY_AUTH_ALL    0x03
+
 #define SSH_CANONICALISE_NO    0
 #define SSH_CANONICALISE_YES   1
 #define SSH_CANONICALISE_ALWAYS        2
index 02383a4..6a6373f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.353 2021/12/19 22:12:54 djm Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.354 2021/12/19 22:14:47 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Damien Miller.  All rights reserved.
@@ -1338,16 +1338,20 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
        int r, fallback_sigtype, sent = 0;
        char *alg = NULL, *fp = NULL;
        const char *loc = "", *method = "publickey";
+       int hostbound = 0;
 
        /* prefer host-bound pubkey signatures if supported by server */
-       if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0)
+       if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0 &&
+           (options.pubkey_authentication & SSH_PUBKEY_AUTH_HBOUND) != 0) {
+               hostbound = 1;
                method = "publickey-hostbound-v00@openssh.com";
+       }
 
        if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
            SSH_FP_DEFAULT)) == NULL)
                return 0;
 
-       debug3_f("%s %s", sshkey_type(id->key), fp);
+       debug3_f("using %s with %s %s", method, sshkey_type(id->key), fp);
 
        /*
         * If the key is an certificate, try to find a matching private key
@@ -1433,7 +1437,7 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
                    (r = sshkey_puts(id->key, b)) != 0) {
                        fatal_fr(r, "assemble signed data");
                }
-               if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0) {
+               if (hostbound) {
                        if (ssh->kex->initial_hostkey == NULL) {
                                fatal_f("internal error: initial hostkey "
                                    "not recorded");