vishalmishra434 / rpms / openssh

Forked from rpms/openssh a month ago
Clone
Dmitry Belyavskiy 9fd698
diff --color -ru a/clientloop.c b/clientloop.c
Dmitry Belyavskiy 9fd698
--- a/clientloop.c	2022-06-29 16:35:06.677597259 +0200
Dmitry Belyavskiy 9fd698
+++ b/clientloop.c	2022-06-29 16:40:29.737926205 +0200
Dmitry Belyavskiy 9fd698
@@ -116,6 +116,9 @@
Dmitry Belyavskiy 9fd698
 #include "ssh-gss.h"
Dmitry Belyavskiy 9fd698
 #endif
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
+/* Permitted RSA signature algorithms for UpdateHostkeys proofs */
Dmitry Belyavskiy 9fd698
+#define HOSTKEY_PROOF_RSA_ALGS	"rsa-sha2-512,rsa-sha2-256"
Dmitry Belyavskiy 9fd698
+
Dmitry Belyavskiy 9fd698
 /* import options */
Dmitry Belyavskiy 9fd698
 extern Options options;
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
@@ -2110,8 +2113,10 @@
Dmitry Belyavskiy 9fd698
 	struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
Dmitry Belyavskiy 9fd698
 	size_t i, ndone;
Dmitry Belyavskiy 9fd698
 	struct sshbuf *signdata;
Dmitry Belyavskiy 9fd698
-	int r, kexsigtype, use_kexsigtype;
Dmitry Belyavskiy 9fd698
+	int r, plaintype;
Dmitry Belyavskiy 9fd698
 	const u_char *sig;
Dmitry Belyavskiy 9fd698
+	const char *rsa_kexalg = NULL;
Dmitry Belyavskiy 9fd698
+	char *alg = NULL;
Dmitry Belyavskiy 9fd698
 	size_t siglen;
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
 	if (ctx->nnew == 0)
Dmitry Belyavskiy 9fd698
@@ -2122,9 +2127,9 @@
Dmitry Belyavskiy 9fd698
 		hostkeys_update_ctx_free(ctx);
Dmitry Belyavskiy 9fd698
 		return;
Dmitry Belyavskiy 9fd698
 	}
Dmitry Belyavskiy 9fd698
-	kexsigtype = sshkey_type_plain(
Dmitry Belyavskiy 9fd698
-	    sshkey_type_from_name(ssh->kex->hostkey_alg));
Dmitry Belyavskiy 9fd698
-
Dmitry Belyavskiy 9fd698
+	if (sshkey_type_plain(sshkey_type_from_name(
Dmitry Belyavskiy 9fd698
+	    ssh->kex->hostkey_alg)) == KEY_RSA)
Dmitry Belyavskiy 9fd698
+		rsa_kexalg = ssh->kex->hostkey_alg;
Dmitry Belyavskiy 9fd698
 	if ((signdata = sshbuf_new()) == NULL)
Dmitry Belyavskiy 9fd698
 		fatal_f("sshbuf_new failed");
Dmitry Belyavskiy 9fd698
 	/*
Dmitry Belyavskiy 9fd698
@@ -2135,6 +2140,7 @@
Dmitry Belyavskiy 9fd698
 	for (ndone = i = 0; i < ctx->nkeys; i++) {
Dmitry Belyavskiy 9fd698
 		if (ctx->keys_match[i])
Dmitry Belyavskiy 9fd698
 			continue;
Dmitry Belyavskiy 9fd698
+		plaintype = sshkey_type_plain(ctx->keys[i]->type);
Dmitry Belyavskiy 9fd698
 		/* Prepare data to be signed: session ID, unique string, key */
Dmitry Belyavskiy 9fd698
 		sshbuf_reset(signdata);
Dmitry Belyavskiy 9fd698
 		if ( (r = sshbuf_put_cstring(signdata,
Dmitry Belyavskiy 9fd698
@@ -2148,19 +2154,33 @@
Dmitry Belyavskiy 9fd698
 			error_fr(r, "parse sig");
Dmitry Belyavskiy 9fd698
 			goto out;
Dmitry Belyavskiy 9fd698
 		}
Dmitry Belyavskiy 9fd698
+		if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) {
Dmitry Belyavskiy 9fd698
+			error_fr(r, "server gave unintelligible signature "
Dmitry Belyavskiy 9fd698
+				"for %s key %zu", sshkey_type(ctx->keys[i]), i);
Dmitry Belyavskiy 9fd698
+			goto out;
Dmitry Belyavskiy 9fd698
+		}
Dmitry Belyavskiy 9fd698
 		/*
Dmitry Belyavskiy 9fd698
-		 * For RSA keys, prefer to use the signature type negotiated
Dmitry Belyavskiy 9fd698
-		 * during KEX to the default (SHA1).
Dmitry Belyavskiy 9fd698
+		 * Special case for RSA keys: if a RSA hostkey was negotiated,
Dmitry Belyavskiy 9fd698
+		 * then use its signature type for verification of RSA hostkey
Dmitry Belyavskiy 9fd698
+		 * proofs. Otherwise, accept only RSA-SHA256/512 signatures.
Dmitry Belyavskiy 9fd698
 		 */
Dmitry Belyavskiy 9fd698
-		use_kexsigtype = kexsigtype == KEY_RSA &&
Dmitry Belyavskiy 9fd698
-		    sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA;
Dmitry Belyavskiy 9fd698
-		debug3_f("verify %s key %zu using %s sigalg",
Dmitry Belyavskiy 9fd698
-		    sshkey_type(ctx->keys[i]), i,
Dmitry Belyavskiy 9fd698
-		    use_kexsigtype ? ssh->kex->hostkey_alg : "default");
Dmitry Belyavskiy 9fd698
+		if (plaintype == KEY_RSA && rsa_kexalg == NULL &&
Dmitry Belyavskiy 9fd698
+		    match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) {
Dmitry Belyavskiy 9fd698
+			debug_f("server used untrusted RSA signature algorithm "
Dmitry Belyavskiy 9fd698
+				"%s for key %zu, disregarding", alg, i);
Dmitry Belyavskiy 9fd698
+			free(alg);
Dmitry Belyavskiy 9fd698
+			/* zap the key from the list */
Dmitry Belyavskiy 9fd698
+			sshkey_free(ctx->keys[i]);
Dmitry Belyavskiy 9fd698
+			ctx->keys[i] = NULL;
Dmitry Belyavskiy 9fd698
+			ndone++;
Dmitry Belyavskiy 9fd698
+			continue;
Dmitry Belyavskiy 9fd698
+		}
Dmitry Belyavskiy 9fd698
+		debug3_f("verify %s key %zu using sigalg %s",
Dmitry Belyavskiy 9fd698
+			sshkey_type(ctx->keys[i]), i, alg);
Dmitry Belyavskiy 9fd698
+		free(alg);
Dmitry Belyavskiy 9fd698
 		if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
Dmitry Belyavskiy 9fd698
 		    sshbuf_ptr(signdata), sshbuf_len(signdata),
Dmitry Belyavskiy 9fd698
-		    use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0,
Dmitry Belyavskiy 9fd698
-		    NULL)) != 0) {
Dmitry Belyavskiy 9fd698
+		    plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) {
Dmitry Belyavskiy 9fd698
 			error_fr(r, "server gave bad signature for %s key %zu",
Dmitry Belyavskiy 9fd698
 			    sshkey_type(ctx->keys[i]), i);
Dmitry Belyavskiy 9fd698
 			goto out;
Dmitry Belyavskiy 9fd698
diff --color -ru a/kex.c b/kex.c
Dmitry Belyavskiy 9fd698
--- a/kex.c	2022-06-29 16:35:06.775599179 +0200
Dmitry Belyavskiy 9fd698
+++ b/kex.c	2022-06-29 16:42:00.839710940 +0200
Dmitry Belyavskiy 9fd698
@@ -959,6 +959,18 @@
Dmitry Belyavskiy 9fd698
 	return (1);
Dmitry Belyavskiy 9fd698
 }
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
+/* returns non-zero if proposal contains any algorithm from algs */
Dmitry Belyavskiy 9fd698
+static int
Dmitry Belyavskiy 9fd698
+has_any_alg(const char *proposal, const char *algs)
Dmitry Belyavskiy 9fd698
+{
Dmitry Belyavskiy 9fd698
+	char *cp;
Dmitry Belyavskiy 9fd698
+
Dmitry Belyavskiy 9fd698
+	if ((cp = match_list(proposal, algs, NULL)) == NULL)
Dmitry Belyavskiy 9fd698
+		return 0;
Dmitry Belyavskiy 9fd698
+	free(cp);
Dmitry Belyavskiy 9fd698
+	return 1;
Dmitry Belyavskiy 9fd698
+}
Dmitry Belyavskiy 9fd698
+
Dmitry Belyavskiy 9fd698
 static int
Dmitry Belyavskiy 9fd698
 kex_choose_conf(struct ssh *ssh)
Dmitry Belyavskiy 9fd698
 {
Dmitry Belyavskiy 9fd698
@@ -994,6 +1006,16 @@
Dmitry Belyavskiy 9fd698
 		free(ext);
Dmitry Belyavskiy 9fd698
 	}
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
+	/* Check whether client supports rsa-sha2 algorithms */
Dmitry Belyavskiy 9fd698
+	if (kex->server && (kex->flags & KEX_INITIAL)) {
Dmitry Belyavskiy 9fd698
+		if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
Dmitry Belyavskiy 9fd698
+		    "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com"))
Dmitry Belyavskiy 9fd698
+			kex->flags |= KEX_RSA_SHA2_256_SUPPORTED;
Dmitry Belyavskiy 9fd698
+		if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS],
Dmitry Belyavskiy 9fd698
+		    "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com"))
Dmitry Belyavskiy 9fd698
+			kex->flags |= KEX_RSA_SHA2_512_SUPPORTED;
Dmitry Belyavskiy 9fd698
+	}
Dmitry Belyavskiy 9fd698
+
Dmitry Belyavskiy 9fd698
 	/* Algorithm Negotiation */
Dmitry Belyavskiy 9fd698
 	if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
Dmitry Belyavskiy 9fd698
 	    sprop[PROPOSAL_KEX_ALGS])) != 0) {
Dmitry Belyavskiy 9fd698
diff --color -ru a/kex.h b/kex.h
Dmitry Belyavskiy 9fd698
--- a/kex.h	2022-06-29 16:35:06.766599003 +0200
Dmitry Belyavskiy 9fd698
+++ b/kex.h	2022-06-29 16:42:24.199168567 +0200
Dmitry Belyavskiy 9fd698
@@ -116,6 +116,8 @@
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
 #define KEX_INIT_SENT	0x0001
Dmitry Belyavskiy 9fd698
 #define KEX_INITIAL	0x0002
Dmitry Belyavskiy 9fd698
+#define KEX_RSA_SHA2_256_SUPPORTED      0x0008 /* only set in server for now */
Dmitry Belyavskiy 9fd698
+#define KEX_RSA_SHA2_512_SUPPORTED      0x0010 /* only set in server for now */
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
 struct sshenc {
Dmitry Belyavskiy 9fd698
 	char	*name;
Dmitry Belyavskiy 9fd698
diff --color -ru a/serverloop.c b/serverloop.c
Dmitry Belyavskiy 9fd698
--- a/serverloop.c	2021-08-20 06:03:49.000000000 +0200
Dmitry Belyavskiy 9fd698
+++ b/serverloop.c	2022-06-29 16:45:05.902336428 +0200
Dmitry Belyavskiy 9fd698
@@ -684,16 +684,18 @@
Dmitry Belyavskiy 9fd698
 	struct sshbuf *resp = NULL;
Dmitry Belyavskiy 9fd698
 	struct sshbuf *sigbuf = NULL;
Dmitry Belyavskiy 9fd698
 	struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
Dmitry Belyavskiy 9fd698
-	int r, ndx, kexsigtype, use_kexsigtype, success = 0;
Dmitry Belyavskiy 9fd698
+	int r, ndx, success = 0;
Dmitry Belyavskiy 9fd698
 	const u_char *blob;
Dmitry Belyavskiy 9fd698
+	const char *sigalg, *kex_rsa_sigalg = NULL;
Dmitry Belyavskiy 9fd698
 	u_char *sig = 0;
Dmitry Belyavskiy 9fd698
 	size_t blen, slen;
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
 	if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
Dmitry Belyavskiy 9fd698
 		fatal_f("sshbuf_new");
Dmitry Belyavskiy 9fd698
 
Dmitry Belyavskiy 9fd698
-	kexsigtype = sshkey_type_plain(
Dmitry Belyavskiy 9fd698
-	    sshkey_type_from_name(ssh->kex->hostkey_alg));
Dmitry Belyavskiy 9fd698
+	if (sshkey_type_plain(sshkey_type_from_name(
Dmitry Belyavskiy 9fd698
+	    ssh->kex->hostkey_alg)) == KEY_RSA)
Dmitry Belyavskiy 9fd698
+		kex_rsa_sigalg = ssh->kex->hostkey_alg;
Dmitry Belyavskiy 9fd698
 	while (ssh_packet_remaining(ssh) > 0) {
Dmitry Belyavskiy 9fd698
 		sshkey_free(key);
Dmitry Belyavskiy 9fd698
 		key = NULL;
Dmitry Belyavskiy 9fd698
@@ -726,16 +728,24 @@
Dmitry Belyavskiy 9fd698
 		 * For RSA keys, prefer to use the signature type negotiated
Dmitry Belyavskiy 9fd698
 		 * during KEX to the default (SHA1).
Dmitry Belyavskiy 9fd698
 		 */
Dmitry Belyavskiy 9fd698
-		use_kexsigtype = kexsigtype == KEY_RSA &&
Dmitry Belyavskiy 9fd698
-		    sshkey_type_plain(key->type) == KEY_RSA;
Dmitry Belyavskiy 9fd698
+		sigalg = NULL;
Dmitry Belyavskiy 9fd698
+		if (sshkey_type_plain(key->type) == KEY_RSA) {
Dmitry Belyavskiy 9fd698
+			if (kex_rsa_sigalg != NULL)
Dmitry Belyavskiy 9fd698
+				sigalg = kex_rsa_sigalg;
Dmitry Belyavskiy 9fd698
+			else if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED)
Dmitry Belyavskiy 9fd698
+				sigalg = "rsa-sha2-512";
Dmitry Belyavskiy 9fd698
+			else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED)
Dmitry Belyavskiy 9fd698
+				sigalg = "rsa-sha2-256";
Dmitry Belyavskiy 9fd698
+		}
Dmitry Belyavskiy 9fd698
+		debug3_f("sign %s key (index %d) using sigalg %s",
Dmitry Belyavskiy 9fd698
+		sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg);
Dmitry Belyavskiy 9fd698
 		if ((r = sshbuf_put_cstring(sigbuf,
Dmitry Belyavskiy 9fd698
 		    "hostkeys-prove-00@openssh.com")) != 0 ||
Dmitry Belyavskiy 9fd698
 		    (r = sshbuf_put_stringb(sigbuf,
Dmitry Belyavskiy 9fd698
 		    ssh->kex->session_id)) != 0 ||
Dmitry Belyavskiy 9fd698
 		    (r = sshkey_puts(key, sigbuf)) != 0 ||
Dmitry Belyavskiy 9fd698
 		    (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen,
Dmitry Belyavskiy 9fd698
-		    sshbuf_ptr(sigbuf), sshbuf_len(sigbuf),
Dmitry Belyavskiy 9fd698
-		    use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 ||
Dmitry Belyavskiy 9fd698
+		    sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), sigalg)) != 0 ||
Dmitry Belyavskiy 9fd698
 		    (r = sshbuf_put_string(resp, sig, slen)) != 0) {
Dmitry Belyavskiy 9fd698
 			error_fr(r, "assemble signature");
Dmitry Belyavskiy 9fd698
 			goto out;