Bug#528046: Access control public-key authentication key type
Package: openssh-server
Version: 1:5.1p1-5
Severity: wishlist
Tags: patch, upstream
With respect to the Debian OpenSSL random number generator issues, and
the consequent recovery of DSA private keys, I have developed a desire
to disable the use of DSA keys on my systems.
I attach here a patch to achieve this for comment. I do so here because
of the specific experience of Debian in this issue.
Matthew W. S. Bell
diff -ruN openssh-5.1p1/auth2-pubkey.c openssh-5.1p1.new/auth2-pubkey.c
--- openssh-5.1p1/auth2-pubkey.c 2009-05-09 22:43:48.000000000 +0100
+++ openssh-5.1p1.new/auth2-pubkey.c 2009-05-10 12:51:32.000000000 +0100
@@ -182,7 +182,7 @@
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
char line[SSH_MAX_PUBKEY_BYTES];
- int found_key = 0;
+ int valid = 0, found_key = 0;
FILE *f;
u_long linenum = 0;
Key *found;
@@ -231,6 +231,7 @@
continue;
}
}
+
if (key_equal(found, key) &&
auth_parse_options(pw, key_options, file, linenum) == 1) {
found_key = 1;
@@ -246,9 +247,14 @@
restore_uid();
fclose(f);
key_free(found);
- if (!found_key)
+ if (found_key)
+ if (key_type_valid(options.pubkey_types, key->type))
+ valid = 1;
+ else
+ debug2("key type not allowed: %s", key_type(key));
+ else
debug2("key not found");
- return found_key;
+ return valid;
}
/* check whether given key is in .ssh/authorized_keys* */
diff -ruN openssh-5.1p1/key.c openssh-5.1p1.new/key.c
--- openssh-5.1p1/key.c 2009-05-09 22:43:48.000000000 +0100
+++ openssh-5.1p1.new/key.c 2009-05-10 02:19:08.000000000 +0100
@@ -770,6 +770,60 @@
return KEY_UNSPEC;
}
+#define SEP ","
+#define FOR_TOKENS(_tokens, _tmp) \
+ do { \
+ char *_dup, *_r; /* remainder */ \
+ _dup = _r = xstrdup((_tokens)); \
+ for (((_tmp) = strsep(&_r, SEP)); \
+ (_tmp) && *(_tmp) != '\0'; \
+ ((_tmp) = strsep(&_r, SEP)))
+#define FOR_TOKENS_END \
+ xfree(_dup); \
+ } while(0)
+
+int
+key_types_valid(const char *names)
+{
+ int type, ret = 1;
+ char *tkn;
+
+ if (names == NULL || *names == '\0')
+ return 1;
+ FOR_TOKENS(names, tkn) {
+ type = key_type_from_name(tkn);
+ if (type == KEY_UNSPEC) {
+ debug("bad key type %s [%s]", tkn, names);
+ ret = 0;
+ break;
+ } else
+ debug3("key type ok: %s [%s]", tkn, names);
+ }
+ FOR_TOKENS_END;
+ debug3("key types ok: [%s]", names);
+ return ret;
+}
+
+int
+key_type_valid(const char *names, int key_type)
+{
+ int found = 0;
+ char *tkn;
+
+ if (names == NULL || *names == '\0')
+ return 1;
+
+ FOR_TOKENS(names, tkn) {
+ if (key_type_from_name(tkn) == key_type) {
+ found = 1;
+ break;
+ }
+ }
+ FOR_TOKENS_END;
+ return found;
+}
+
+
int
key_names_valid2(const char *names)
{
diff -ruN openssh-5.1p1/key.h openssh-5.1p1.new/key.h
--- openssh-5.1p1/key.h 2009-05-09 22:43:48.000000000 +0100
+++ openssh-5.1p1.new/key.h 2009-05-10 03:52:17.000000000 +0100
@@ -76,6 +76,8 @@
Key *key_from_blob(const u_char *, u_int);
int key_to_blob(const Key *, u_char **, u_int *);
const char *key_ssh_name(const Key *);
+int key_types_valid(const char *);
+int key_type_valid(const char *, int);
int key_names_valid2(const char *);
int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
diff -ruN openssh-5.1p1/servconf.c openssh-5.1p1.new/servconf.c
--- openssh-5.1p1/servconf.c 2009-05-09 22:43:48.000000000 +0100
+++ openssh-5.1p1.new/servconf.c 2009-05-10 03:47:54.000000000 +0100
@@ -87,6 +87,7 @@
options->hostbased_uses_name_from_packet_only = -1;
options->rsa_authentication = -1;
options->pubkey_authentication = -1;
+ options->pubkey_types = NULL;
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
@@ -303,8 +304,8 @@
sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
- sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
- sMaxStartups, sMaxAuthTries, sMaxSessions,
+ sGatewayPorts, sPubkeyAuthentication, sPubKeyTypes, sXAuthLocation,
+ sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
@@ -351,6 +352,7 @@
{ "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
+ { "pubkeytypes", sPubKeyTypes, SSHCFG_ALL },
#ifdef KRB5
{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
@@ -881,6 +883,17 @@
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
+
+ case sPubKeyTypes:
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: Missing argument.", filename, linenum);
+ if (!key_types_valid(arg))
+ fatal("%s line %d: Bad SSH2 public key authentication key type spec. '%s'.",
+ filename, linenum, arg ? arg : "<NONE>");
+ if (options->pubkey_types == NULL)
+ options->pubkey_types = xstrdup(arg);
+ break;
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
@@ -1406,6 +1419,7 @@
M_CP_INTOPT(gss_authentication);
M_CP_INTOPT(rsa_authentication);
M_CP_INTOPT(pubkey_authentication);
+ M_CP_INTOPT(pubkey_types);
M_CP_INTOPT(kerberos_authentication);
M_CP_INTOPT(hostbased_authentication);
M_CP_INTOPT(kbd_interactive_authentication);
@@ -1629,6 +1643,7 @@
dump_cfg_string(sCiphers, o->ciphers);
dump_cfg_string(sMacs, o->macs);
dump_cfg_string(sBanner, o->banner);
+ dump_cfg_string(sPubKeyTypes, o->pubkey_types);
dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
dump_cfg_string(sForceCommand, o->adm_forced_command);
diff -ruN openssh-5.1p1/servconf.h openssh-5.1p1.new/servconf.h
--- openssh-5.1p1/servconf.h 2009-05-09 22:43:48.000000000 +0100
+++ openssh-5.1p1.new/servconf.h 2009-05-09 20:35:22.000000000 +0100
@@ -79,6 +79,7 @@
int hostbased_uses_name_from_packet_only; /* experimental */
int rsa_authentication; /* If true, permit RSA authentication. */
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
+ char *pubkey_types; /* Allowed key types for pubkey auth2. */
int kerberos_authentication; /* If true, permit Kerberos
* authentication. */
int kerberos_or_local_passwd; /* If true, permit kerberos
diff -ruN openssh-5.1p1/sshd_config.5 openssh-5.1p1.new/sshd_config.5
--- openssh-5.1p1/sshd_config.5 2009-05-09 22:43:48.000000000 +0100
+++ openssh-5.1p1.new/sshd_config.5 2009-05-10 13:30:31.000000000 +0100
@@ -858,10 +858,15 @@
is identical to
.Dq 1,2 .
.It Cm PubkeyAuthentication
-Specifies whether public key authentication is allowed.
+Specifies whether public key client authentication is allowed.
The default is
.Dq yes .
-Note that this option applies to protocol version 2 only.
+This option applies to protocol version 2 only.
+.It Cm PubKeyTypes
+Specifies which key types are accepted for public key authentication.
+The default is
+.Dq ,
+which allows all types. This applies to protcol version 2 public key client authentication only.
.It Cm RhostsRSAAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication together
with successful RSA host authentication is allowed.
Reply to: