Skip to content

Commit

Permalink
fixed handling of rsa-sha2-* key algorithms
Browse files Browse the repository at this point in the history
  • Loading branch information
Eugeny committed Dec 7, 2024
1 parent 457706e commit 044da62
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 16 deletions.
22 changes: 20 additions & 2 deletions russh/src/negotiation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,27 @@ pub struct Preferred {
pub compression: Cow<'static, [compression::Name]>,
}

pub(crate) fn is_key_compatible_with_algo(key: &PrivateKey, algo: &Algorithm) -> bool {
match algo {
// All RSA keys are compatible with all RSA based algos.
Algorithm::Rsa { .. } => key.algorithm().is_rsa(),
// Other keys have to match exactly
a => key.algorithm() == *a,
}
}

impl Preferred {
pub(crate) fn possible_host_key_algos_for_keys(
&self,
available_host_keys: &[PrivateKey],
) -> Vec<Algorithm> {
self.key
.iter()
.filter(|n| available_host_keys.iter().any(|k| k.algorithm() == **n))
.filter(|n| {
available_host_keys
.iter()
.any(|k| is_key_compatible_with_algo(k, *n))
})
.cloned()
.collect::<Vec<_>>()
}
Expand Down Expand Up @@ -433,7 +446,12 @@ pub fn write_kex(
prefs
.key
.iter()
.filter(|algo| server_config.keys.iter().any(|k| k.algorithm() == **algo))
.filter(|algo| {
server_config
.keys
.iter()
.any(|k| is_key_compatible_with_algo(k, *algo))
})
.map(|x| x.to_string())
.collect(),
)
Expand Down
28 changes: 14 additions & 14 deletions russh/src/server/kex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use ssh_encoding::Encode;
use super::*;
use crate::cipher::SealingKey;
use crate::kex::KEXES;
use crate::negotiation::Select;
use crate::negotiation::{is_key_compatible_with_algo, Select};
use crate::{msg, negotiation};

thread_local! {
Expand All @@ -32,23 +32,23 @@ impl KexInit {
if !self.sent {
self.server_write(config, cipher, write_buffer)?
}
let mut key = 0;
#[allow(clippy::indexing_slicing)] // length checked
while key < config.keys.len() && config.keys[key].algorithm() != algo.key {
key += 1
}
let next_kex = if key < config.keys.len() {
Kex::Dh(KexDh {
exchange: self.exchange,
key,
names: algo,
session_id: self.session_id,
})
} else {

let Some(matching_key_index) = config
.keys
.iter()
.position(|key| is_key_compatible_with_algo(&key, &algo.key))
else {
debug!("unknown key {:?}", algo.key);
return Err(Error::UnknownKey);
};

let next_kex = Kex::Dh(KexDh {
exchange: self.exchange,
key: matching_key_index,
names: algo,
session_id: self.session_id,
});

Ok(next_kex)
} else {
Ok(Kex::Init(self))
Expand Down

0 comments on commit 044da62

Please sign in to comment.