mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-29 08:44:52 +02:00
upstream: stricter UpdateHostkey signature verification logic on
the client- side. Require RSA/SHA2 signatures for RSA hostkeys except when RSA/SHA1 was explicitly negotiated during initial KEX; bz3375 ok markus@ OpenBSD-Commit-ID: 46e75e8dfa2c813781805b842580dcfbd888cf29
This commit is contained in:
parent
0fa3368322
commit
291721bc7c
48
clientloop.c
48
clientloop.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: clientloop.c,v 1.374 2022/01/06 21:48:38 djm Exp $ */
|
/* $OpenBSD: clientloop.c,v 1.375 2022/01/06 21:57:28 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -113,6 +113,9 @@
|
|||||||
#include "ssherr.h"
|
#include "ssherr.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
|
||||||
|
/* Permitted RSA signature algorithms for UpdateHostkeys proofs */
|
||||||
|
#define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256"
|
||||||
|
|
||||||
/* import options */
|
/* import options */
|
||||||
extern Options options;
|
extern Options options;
|
||||||
|
|
||||||
@ -2111,8 +2114,10 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
|
|||||||
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
|
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
|
||||||
size_t i, ndone;
|
size_t i, ndone;
|
||||||
struct sshbuf *signdata;
|
struct sshbuf *signdata;
|
||||||
int r, kexsigtype, use_kexsigtype;
|
int r, plaintype;
|
||||||
const u_char *sig;
|
const u_char *sig;
|
||||||
|
const char *rsa_kexalg = NULL;
|
||||||
|
char *alg = NULL;
|
||||||
size_t siglen;
|
size_t siglen;
|
||||||
|
|
||||||
if (ctx->nnew == 0)
|
if (ctx->nnew == 0)
|
||||||
@ -2123,9 +2128,9 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
|
|||||||
hostkeys_update_ctx_free(ctx);
|
hostkeys_update_ctx_free(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
kexsigtype = sshkey_type_plain(
|
if (sshkey_type_plain(sshkey_type_from_name(
|
||||||
sshkey_type_from_name(ssh->kex->hostkey_alg));
|
ssh->kex->hostkey_alg)) == KEY_RSA)
|
||||||
|
rsa_kexalg = ssh->kex->hostkey_alg;
|
||||||
if ((signdata = sshbuf_new()) == NULL)
|
if ((signdata = sshbuf_new()) == NULL)
|
||||||
fatal_f("sshbuf_new failed");
|
fatal_f("sshbuf_new failed");
|
||||||
/*
|
/*
|
||||||
@ -2136,6 +2141,7 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
|
|||||||
for (ndone = i = 0; i < ctx->nkeys; i++) {
|
for (ndone = i = 0; i < ctx->nkeys; i++) {
|
||||||
if (ctx->keys_match[i])
|
if (ctx->keys_match[i])
|
||||||
continue;
|
continue;
|
||||||
|
plaintype = sshkey_type_plain(ctx->keys[i]->type);
|
||||||
/* Prepare data to be signed: session ID, unique string, key */
|
/* Prepare data to be signed: session ID, unique string, key */
|
||||||
sshbuf_reset(signdata);
|
sshbuf_reset(signdata);
|
||||||
if ( (r = sshbuf_put_cstring(signdata,
|
if ( (r = sshbuf_put_cstring(signdata,
|
||||||
@ -2149,19 +2155,33 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
|
|||||||
error_fr(r, "parse sig");
|
error_fr(r, "parse sig");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) {
|
||||||
|
error_fr(r, "server gave unintelligible signature "
|
||||||
|
"for %s key %zu", sshkey_type(ctx->keys[i]), i);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* For RSA keys, prefer to use the signature type negotiated
|
* Special case for RSA keys: if a RSA hostkey was negotiated,
|
||||||
* during KEX to the default (SHA1).
|
* then use its signature type for verification of RSA hostkey
|
||||||
|
* proofs. Otherwise, accept only RSA-SHA256/512 signatures.
|
||||||
*/
|
*/
|
||||||
use_kexsigtype = kexsigtype == KEY_RSA &&
|
if (plaintype == KEY_RSA && rsa_kexalg == NULL &&
|
||||||
sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA;
|
match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) {
|
||||||
debug3_f("verify %s key %zu using %s sigalg",
|
debug_f("server used untrusted RSA signature algorithm "
|
||||||
sshkey_type(ctx->keys[i]), i,
|
"%s for key %zu, disregarding", alg, i);
|
||||||
use_kexsigtype ? ssh->kex->hostkey_alg : "default");
|
free(alg);
|
||||||
|
/* zap the key from the list */
|
||||||
|
sshkey_free(ctx->keys[i]);
|
||||||
|
ctx->keys[i] = NULL;
|
||||||
|
ndone++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
debug3_f("verify %s key %zu using sigalg %s",
|
||||||
|
sshkey_type(ctx->keys[i]), i, alg);
|
||||||
|
free(alg);
|
||||||
if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
|
if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
|
||||||
sshbuf_ptr(signdata), sshbuf_len(signdata),
|
sshbuf_ptr(signdata), sshbuf_len(signdata),
|
||||||
use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0,
|
plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) {
|
||||||
NULL)) != 0) {
|
|
||||||
error_fr(r, "server gave bad signature for %s key %zu",
|
error_fr(r, "server gave bad signature for %s key %zu",
|
||||||
sshkey_type(ctx->keys[i]), i);
|
sshkey_type(ctx->keys[i]), i);
|
||||||
goto out;
|
goto out;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user