@@ -24,6 +24,7 @@ use russh_keys::key::{KeyPair, PublicKey};
2424use crate :: cipher:: CIPHERS ;
2525use crate :: compression:: * ;
2626use crate :: kex:: { EXTENSION_OPENSSH_STRICT_KEX_AS_CLIENT , EXTENSION_OPENSSH_STRICT_KEX_AS_SERVER } ;
27+ use crate :: server:: Config ;
2728use crate :: { cipher, kex, mac, msg, Error } ;
2829
2930#[ derive( Debug ) ]
@@ -40,11 +41,11 @@ pub struct Names {
4041}
4142
4243/// Lists of preferred algorithms. This is normally hard-coded into implementations.
43- #[ derive( Debug ) ]
44+ #[ derive( Debug , Clone ) ]
4445pub struct Preferred {
4546 /// Preferred key exchange algorithms.
4647 pub kex : & ' static [ kex:: Name ] ,
47- /// Preferred public key algorithms.
48+ /// Preferred host & public key algorithms.
4849 pub key : & ' static [ key:: Name ] ,
4950 /// Preferred symmetric ciphers.
5051 pub cipher : & ' static [ cipher:: Name ] ,
@@ -316,7 +317,11 @@ impl Select for Client {
316317 }
317318}
318319
319- pub fn write_kex ( prefs : & Preferred , buf : & mut CryptoVec , as_server : bool ) -> Result < ( ) , Error > {
320+ pub fn write_kex (
321+ prefs : & Preferred ,
322+ buf : & mut CryptoVec ,
323+ server_config : Option < & Config > ,
324+ ) -> Result < ( ) , Error > {
320325 // buf.clear();
321326 buf. push ( msg:: KEXINIT ) ;
322327
@@ -325,7 +330,7 @@ pub fn write_kex(prefs: &Preferred, buf: &mut CryptoVec, as_server: bool) -> Res
325330
326331 buf. extend ( & cookie) ; // cookie
327332 buf. extend_list ( prefs. kex . iter ( ) . filter ( |k| {
328- !( if as_server {
333+ !( if server_config . is_some ( ) {
329334 [
330335 crate :: kex:: EXTENSION_SUPPORT_AS_CLIENT ,
331336 crate :: kex:: EXTENSION_OPENSSH_STRICT_KEX_AS_CLIENT ,
@@ -339,7 +344,17 @@ pub fn write_kex(prefs: &Preferred, buf: &mut CryptoVec, as_server: bool) -> Res
339344 . contains ( * k)
340345 } ) ) ; // kex algo
341346
342- buf. extend_list ( prefs. key . iter ( ) ) ;
347+ if let Some ( server_config) = server_config {
348+ // Only advertise host key algorithms that we have keys for.
349+ buf. extend_list (
350+ prefs
351+ . key
352+ . iter ( )
353+ . filter ( |name| server_config. keys . iter ( ) . any ( |k| k. name ( ) == name. 0 ) ) ,
354+ ) ;
355+ } else {
356+ buf. extend_list ( prefs. key . iter ( ) ) ;
357+ }
343358
344359 buf. extend_list ( prefs. cipher . iter ( ) ) ; // cipher client to server
345360 buf. extend_list ( prefs. cipher . iter ( ) ) ; // cipher server to client
0 commit comments