add sshd_config HostbasedAcceptedKeyTypes and PubkeyAcceptedKeyTypes
authordjm <djm@openbsd.org>
Tue, 13 Jan 2015 07:39:19 +0000 (07:39 +0000)
committerdjm <djm@openbsd.org>
Tue, 13 Jan 2015 07:39:19 +0000 (07:39 +0000)
options to allow sshd to control what public key types will be
accepted. Currently defaults to all. Feedback & ok markus@

usr.bin/ssh/auth2-hostbased.c
usr.bin/ssh/auth2-pubkey.c
usr.bin/ssh/key.h
usr.bin/ssh/monitor.c
usr.bin/ssh/readconf.c
usr.bin/ssh/servconf.c
usr.bin/ssh/servconf.h
usr.bin/ssh/sshd_config.5
usr.bin/ssh/sshkey.c
usr.bin/ssh/sshkey.h

index e75a5cf..104725b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.21 2015/01/08 10:14:08 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.22 2015/01/13 07:39:19 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -47,6 +47,7 @@
 #endif
 #include "monitor_wrap.h"
 #include "pathnames.h"
+#include "match.h"
 
 /* import */
 extern ServerOptions options;
@@ -107,6 +108,14 @@ userauth_hostbased(Authctxt *authctxt)
                    "signature format");
                goto done;
        }
+       if (match_pattern_list(sshkey_ssh_name(key),
+           options.hostbased_key_types,
+           strlen(options.hostbased_key_types), 0) != 1) {
+               logit("%s: key type %s not in HostbasedAcceptedKeyTypes",
+                   __func__, sshkey_type(key));
+               goto done;
+       }
+
        service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
            authctxt->service;
        buffer_init(&b);
index f880717..87c8132 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.44 2014/12/22 07:51:30 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.45 2015/01/13 07:39:19 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -124,6 +124,13 @@ userauth_pubkey(Authctxt *authctxt)
                logit("refusing previously-used %s key", key_type(key));
                goto done;
        }
+       if (match_pattern_list(sshkey_ssh_name(key), options.pubkey_key_types,
+           strlen(options.pubkey_key_types), 0) != 1) {
+               logit("%s: key type %s not in PubkeyAcceptedKeyTypes",
+                   __func__, sshkey_ssh_name(key));
+               goto done;
+       }
+
        if (have_sig) {
                sig = packet_get_string(&slen);
                packet_check_eom();
index 9d7e84e..188d417 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.h,v 1.45 2015/01/08 10:14:08 djm Exp $ */
+/* $OpenBSD: key.h,v 1.46 2015/01/13 07:39:19 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -50,7 +50,6 @@ typedef struct sshkey Key;
 #define key_size               sshkey_size
 #define key_ecdsa_bits_to_nid  sshkey_ecdsa_bits_to_nid
 #define key_ecdsa_key_to_nid   sshkey_ecdsa_key_to_nid
-#define key_names_valid2       sshkey_names_valid2
 #define key_is_cert            sshkey_is_cert
 #define key_type_plain         sshkey_type_plain
 #define key_cert_is_legacy     sshkey_cert_is_legacy
index 637009c..85b98dc 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.136 2014/12/22 07:51:30 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.137 2015/01/13 07:39:19 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -79,6 +79,7 @@
 #include "ssh2.h"
 #include "roaming.h"
 #include "authfd.h"
+#include "match.h"
 
 #ifdef GSSAPI
 static Gssctxt *gsscontext = NULL;
@@ -881,10 +882,18 @@ mm_answer_keyallowed(int sock, Buffer *m)
        debug3("%s: key_from_blob: %p", __func__, key);
 
        if (key != NULL && authctxt->valid) {
+               /* These should not make it past the privsep child */
+               if (key_type_plain(key->type) == KEY_RSA &&
+                   (datafellows & SSH_BUG_RSASIGMD5) != 0)
+                       fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__);
+
                switch (type) {
                case MM_USERKEY:
                        allowed = options.pubkey_authentication &&
                            !auth2_userkey_already_used(authctxt, key) &&
+                           match_pattern_list(sshkey_ssh_name(key),
+                           options.pubkey_key_types,
+                           strlen(options.pubkey_key_types), 0) == 1 &&
                            user_key_allowed(authctxt->pw, key);
                        pubkey_auth_info(authctxt, key, NULL);
                        auth_method = "publickey";
@@ -893,6 +902,9 @@ mm_answer_keyallowed(int sock, Buffer *m)
                        break;
                case MM_HOSTKEY:
                        allowed = options.hostbased_authentication &&
+                           match_pattern_list(sshkey_ssh_name(key),
+                           options.hostbased_key_types,
+                           strlen(options.hostbased_key_types), 0) == 1 &&
                            hostbased_key_allowed(authctxt->pw,
                            cuser, chost, key);
                        pubkey_auth_info(authctxt, key,
index 51034c1..83944dc 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.225 2015/01/08 13:44:36 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.226 2015/01/13 07:39:19 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1104,7 +1104,7 @@ parse_int:
                arg = strdelim(&s);
                if (!arg || *arg == '\0')
                        fatal("%.200s line %d: Missing argument.", filename, linenum);
-               if (!key_names_valid2(arg))
+               if (!sshkey_names_valid2(arg, 1))
                        fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
                            filename, linenum, arg ? arg : "<NONE>");
                if (*activep && options->hostkeyalgorithms == NULL)
index 5732d78..f36cc9c 100644 (file)
@@ -1,5 +1,5 @@
 
-/* $OpenBSD: servconf.c,v 1.257 2014/12/22 07:55:51 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.258 2015/01/13 07:39:19 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -94,8 +94,10 @@ initialize_server_options(ServerOptions *options)
        options->rhosts_rsa_authentication = -1;
        options->hostbased_authentication = -1;
        options->hostbased_uses_name_from_packet_only = -1;
+       options->hostbased_key_types = NULL;
        options->rsa_authentication = -1;
        options->pubkey_authentication = -1;
+       options->pubkey_key_types = NULL;
        options->kerberos_authentication = -1;
        options->kerberos_or_local_passwd = -1;
        options->kerberos_ticket_cleanup = -1;
@@ -231,10 +233,14 @@ fill_default_server_options(ServerOptions *options)
                options->hostbased_authentication = 0;
        if (options->hostbased_uses_name_from_packet_only == -1)
                options->hostbased_uses_name_from_packet_only = 0;
+       if (options->hostbased_key_types == NULL)
+               options->hostbased_key_types = xstrdup("*");
        if (options->rsa_authentication == -1)
                options->rsa_authentication = 1;
        if (options->pubkey_authentication == -1)
                options->pubkey_authentication = 1;
+       if (options->pubkey_key_types == NULL)
+               options->pubkey_key_types = xstrdup("*");
        if (options->kerberos_authentication == -1)
                options->kerberos_authentication = 0;
        if (options->kerberos_or_local_passwd == -1)
@@ -335,8 +341,8 @@ fill_default_server_options(ServerOptions *options)
 /* Keyword tokens. */
 typedef enum {
        sBadOption,             /* == unknown option */
-       sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
-       sPermitRootLogin, sLogFacility, sLogLevel,
+       sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime,
+       sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel,
        sRhostsRSAAuthentication, sRSAAuthentication,
        sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
        sKerberosGetAFSToken,
@@ -349,11 +355,11 @@ typedef enum {
        sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
        sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
        sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
-       sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
-       sMaxStartups, sMaxAuthTries, sMaxSessions,
+       sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
+       sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
        sBanner, sUseDNS, sHostbasedAuthentication,
-       sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
-       sClientAliveCountMax, sAuthorizedKeysFile,
+       sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
+       sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
        sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
        sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
        sUsePrivilegeSeparation, sAllowAgentForwarding,
@@ -392,8 +398,10 @@ static struct {
        { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
        { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
        { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
+       { "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL },
        { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
        { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
+       { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
        { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
 #ifdef KRB5
        { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
@@ -1063,6 +1071,20 @@ process_server_config_line(ServerOptions *options, char *line,
                intptr = &options->hostbased_uses_name_from_packet_only;
                goto parse_flag;
 
+       case sHostbasedAcceptedKeyTypes:
+               charptr = &options->hostbased_key_types;
+ parse_keytypes:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: Missing argument.",
+                           filename, linenum);
+               if (!sshkey_names_valid2(arg, 1))
+                       fatal("%s line %d: Bad key types '%s'.",
+                           filename, linenum, arg ? arg : "<NONE>");
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
+
        case sRSAAuthentication:
                intptr = &options->rsa_authentication;
                goto parse_flag;
@@ -1071,6 +1093,10 @@ process_server_config_line(ServerOptions *options, char *line,
                intptr = &options->pubkey_authentication;
                goto parse_flag;
 
+       case sPubkeyAcceptedKeyTypes:
+               charptr = &options->pubkey_key_types;
+               goto parse_keytypes;
+
        case sKerberosAuthentication:
                intptr = &options->kerberos_authentication;
                goto parse_flag;
@@ -2089,6 +2115,10 @@ dump_config(ServerOptions *o)
        dump_cfg_string(sHostKeyAgent, o->host_key_agent);
        dump_cfg_string(sKexAlgorithms,
            o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX);
+       dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ?
+           o->hostbased_key_types : KEX_DEFAULT_PK_ALG);
+       dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ?
+           o->pubkey_key_types : KEX_DEFAULT_PK_ALG);
 
        /* string arguments requiring a lookup */
        dump_cfg_string(sLogLevel, log_level_name(o->log_level));
index 88a4bd4..447a2ce 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.115 2014/12/21 22:27:56 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.116 2015/01/13 07:39:19 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -99,8 +99,10 @@ typedef struct {
                                                 * authentication. */
        int     hostbased_authentication;       /* If true, permit ssh2 hostbased auth */
        int     hostbased_uses_name_from_packet_only; /* experimental */
+       char   *hostbased_key_types;    /* Key types allowed for hostbased */
        int     rsa_authentication;     /* If true, permit RSA authentication. */
        int     pubkey_authentication;  /* If true, permit ssh2 pubkey authentication. */
+       char   *pubkey_key_types;       /* Key types allowed for public key */
        int     kerberos_authentication;        /* If true, permit Kerberos
                                                 * authentication. */
        int     kerberos_or_local_passwd;       /* If true, permit kerberos
@@ -213,6 +215,8 @@ struct connection_info {
                M_CP_STROPT(authorized_principals_file); \
                M_CP_STROPT(authorized_keys_command); \
                M_CP_STROPT(authorized_keys_command_user); \
+               M_CP_STROPT(hostbased_key_types); \
+               M_CP_STROPT(pubkey_key_types); \
                M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
                M_CP_STRARRAYOPT(allow_users, num_allow_users); \
                M_CP_STRARRAYOPT(deny_users, num_deny_users); \
index 7f79255..33c93bc 100644 (file)
@@ -33,8 +33,8 @@
 .\" (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_config.5,v 1.188 2014/12/22 09:05:17 djm Exp $
-.Dd $Mdocdate: December 22 2014 $
+.\" $OpenBSD: sshd_config.5,v 1.189 2015/01/13 07:39:19 djm Exp $
+.Dd $Mdocdate: January 13 2015 $
 .Dt SSHD_CONFIG 5
 .Os
 .Sh NAME
@@ -562,6 +562,17 @@ on logout.
 The default is
 .Dq yes .
 Note that this option applies to protocol version 2 only.
+.It Cm HostbasedAcceptedKeyTypes
+Specifies the key types that will be accepted for hostbased authentication
+as a comma-separated pattern list.
+The default
+.Dq *
+will allow all key types.
+The
+.Fl Q
+option of
+.Xr ssh 1
+may be used to list supported key types.
 .It Cm HostbasedAuthentication
 Specifies whether rhosts or /etc/hosts.equiv authentication together
 with successful public key client host authentication is allowed
@@ -963,6 +974,7 @@ Available keywords are
 .Cm ForceCommand ,
 .Cm GatewayPorts ,
 .Cm GSSAPIAuthentication ,
+.Cm HostbasedAcceptedKeyTypes ,
 .Cm HostbasedAuthentication ,
 .Cm HostbasedUsesNameFromPacketOnly ,
 .Cm KbdInteractiveAuthentication ,
@@ -976,6 +988,7 @@ Available keywords are
 .Cm PermitTTY ,
 .Cm PermitTunnel ,
 .Cm PermitUserRC ,
+.Cm PubkeyAcceptedKeyTypes ,
 .Cm PubkeyAuthentication ,
 .Cm RekeyLimit ,
 .Cm RhostsRSAAuthentication ,
@@ -1183,6 +1196,17 @@ Specifying
 .Dq 2,1
 is identical to
 .Dq 1,2 .
+.It Cm PubkeyAcceptedKeyTypes
+Specifies the key types that will be accepted for public key authentication
+as a comma-separated pattern list.
+The default
+.Dq *
+will allow all key types.
+The
+.Fl Q
+option of
+.Xr ssh 1
+may be used to list supported key types.
 .It Cm PubkeyAuthentication
 Specifies whether public key authentication is allowed.
 The default is
index 1fd3136..5116fad 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.10 2015/01/12 20:13:27 markus Exp $ */
+/* $OpenBSD: sshkey.c,v 1.11 2015/01/13 07:39:19 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -50,6 +50,7 @@
 #include "digest.h"
 #define SSHKEY_INTERNAL
 #include "sshkey.h"
+#include "match.h"
 
 /* openssh private key file format */
 #define MARK_BEGIN             "-----BEGIN OPENSSH PRIVATE KEY-----\n"
@@ -207,9 +208,11 @@ key_alg_list(int certs_only, int plain_only)
 }
 
 int
-sshkey_names_valid2(const char *names)
+sshkey_names_valid2(const char *names, int allow_wildcard)
 {
        char *s, *cp, *p;
+       const struct keytype *kt;
+       int type;
 
        if (names == NULL || strcmp(names, "") == 0)
                return 0;
@@ -217,9 +220,28 @@ sshkey_names_valid2(const char *names)
                return 0;
        for ((p = strsep(&cp, ",")); p && *p != '\0';
            (p = strsep(&cp, ","))) {
-               switch (sshkey_type_from_name(p)) {
-               case KEY_RSA1:
-               case KEY_UNSPEC:
+               type = sshkey_type_from_name(p);
+               if (type == KEY_RSA1) {
+                       free(s);
+                       return 0;
+               }
+               if (type == KEY_UNSPEC) {
+                       if (allow_wildcard) {
+                               /*
+                                * Try matching key types against the string.
+                                * If any has a positive or negative match then
+                                * the component is accepted.
+                                */
+                               for (kt = keytypes; kt->type != -1; kt++) {
+                                       if (kt->type == KEY_RSA1)
+                                               continue;
+                                       if (match_pattern_list(kt->name,
+                                           p, strlen(p), 0) != 0)
+                                               break;
+                               }
+                               if (kt->type != -1)
+                                       continue;
+                       }
                        free(s);
                        return 0;
                }
index 2db64d7..f4d7b95 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.3 2015/01/08 10:14:08 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.4 2015/01/13 07:39:19 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -150,7 +150,7 @@ int          sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *);
 int             sshkey_ec_validate_private(const EC_KEY *);
 const char     *sshkey_ssh_name(const struct sshkey *);
 const char     *sshkey_ssh_name_plain(const struct sshkey *);
-int             sshkey_names_valid2(const char *);
+int             sshkey_names_valid2(const char *, int);
 char           *key_alg_list(int, int);
 
 int     sshkey_from_blob(const u_char *, size_t, struct sshkey **);