[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: