diff --git a/CHANGELOG.md b/CHANGELOG.md index 9554fff..b55b1eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,16 @@ # Makiko changelog -## 0.2.1 +## Unreleased -- Deprecate `Pubkey::algos_secure()` and `Pubkey::algos_compatible_less_secure()`, replace with -`Pubkey::algos()` +- Replace the `guard` crate with (now stabilized) `let else` expressions + supported directly by the compiler. Fixes compatibility with Rust 1.70.0. -## 0.2.0 +## 0.2.1 (2023-02-09) + +- Deprecated `Pubkey::algos_secure()` and + `Pubkey::algos_compatible_less_secure()`, replace with + `Pubkey::algos()` + +## 0.2.0 (2022-10-01) The first generally usable version. diff --git a/Cargo.toml b/Cargo.toml index ec65ac0..eafcc88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ ecdsa = {version = "0.15", features = ["signing", "verifying"]} ed25519 = {version = "1.5", features = ["pkcs8"]} ed25519-dalek = "1.0" futures-core = "0.3" -guard = "0.5" hex-literal = "0.3" hmac = "0.12" log = "0.4" diff --git a/src/client/channel_state.rs b/src/client/channel_state.rs index a361ad5..48fffa0 100644 --- a/src/client/channel_state.rs +++ b/src/client/channel_state.rs @@ -1,6 +1,5 @@ use bytes::Bytes; use futures_core::ready; -use guard::guard; use parking_lot::Mutex; use std::cmp::min; use std::collections::VecDeque; @@ -182,18 +181,18 @@ fn send_channel_request(st: &mut ClientState, channel_st: &ChannelState, req: &C } pub(super) fn recv_channel_success(channel_st: &mut ChannelState) -> ResultRecvState { - guard!{let Some(reply) = channel_st.recv_replies.pop_front() else { + let Some(reply) = channel_st.recv_replies.pop_front() else { return Err(Error::Protocol("received SSH_MSG_CHANNEL_SUCCESS, but no reply was expected")) - }}; + }; log::debug!("received SSH_MSG_CHANNEL_SUCCESS for our channel {}", channel_st.our_id); let _: Result<_, _> = reply.reply_tx.send(ChannelReply::Success); Ok(None) } pub(super) fn recv_channel_failure(channel_st: &mut ChannelState) -> ResultRecvState { - guard!{let Some(reply) = channel_st.recv_replies.pop_front() else { + let Some(reply) = channel_st.recv_replies.pop_front() else { return Err(Error::Protocol("received SSH_MSG_CHANNEL_FAILURE, but no reply was expected")) - }}; + }; log::debug!("received SSH_MSG_CHANNEL_FAILURE for our channel {}", channel_st.our_id); let _: Result<_, _> = reply.reply_tx.send(ChannelReply::Failure); Ok(None) diff --git a/src/client/conn.rs b/src/client/conn.rs index 312736d..616125d 100644 --- a/src/client/conn.rs +++ b/src/client/conn.rs @@ -1,5 +1,4 @@ use bytes::Bytes; -use guard::guard; use parking_lot::Mutex; use std::collections::{HashMap, VecDeque}; use std::future::Future as _; @@ -248,18 +247,18 @@ fn recv_channel_open_confirmation( window {}, max packet size {}", our_id, send_window, send_packet_len_max); let mut channels = st.conn_st.channels.lock(); - guard!{let Some(conn_channel_st) = channels.get_mut(&our_id) else { + let Some(conn_channel_st) = channels.get_mut(&our_id) else { return Err(Error::Protocol("received SSH_MSG_CHANNEL_OPEN_CONFIRMATION for unknown channel")); - }}; + }; - guard!{let ConnChannelState::Open(_) = conn_channel_st else { + let ConnChannelState::Open(_) = conn_channel_st else { return Err(Error::Protocol("received SSH_MSG_CHANNEL_OPEN_CONFIRMATION \ for a channel that is not being opened")); - }}; + }; // use `replace()` only after we are sure that `*conn_channel_st` is `Open` - guard!{let ConnChannelState::Open(open_st) = replace(conn_channel_st, ConnChannelState::Closed) else { + let ConnChannelState::Open(open_st) = replace(conn_channel_st, ConnChannelState::Closed) else { unreachable!() - }}; + }; let confirm = ConfirmChannel { their_id, send_window, send_packet_len_max, confirm_payload }; *conn_channel_st = init_confirmed_channel(open_st, confirm); @@ -303,17 +302,17 @@ fn recv_channel_open_failure( let description_lang = payload.get_string()?; let mut channels = st.conn_st.channels.lock(); - guard!{let Some(conn_channel_st) = channels.get_mut(&our_id) else { + let Some(conn_channel_st) = channels.get_mut(&our_id) else { return Err(Error::Protocol("received SSH_MSG_CHANNEL_OPEN_FAILURE for unknown channel")); - }}; - guard!{let ConnChannelState::Open(_) = conn_channel_st else { + }; + let ConnChannelState::Open(_) = conn_channel_st else { return Err(Error::Protocol("received SSH_MSG_CHANNEL_OPEN_FAILURE \ for a channel that is not being opened")); - }}; + }; // use `replace()` only after we are sure that `*conn_channel_st` is `Open` - guard!{let ConnChannelState::Open(open_st) = replace(conn_channel_st, ConnChannelState::Closed) else { + let ConnChannelState::Open(open_st) = replace(conn_channel_st, ConnChannelState::Closed) else { unreachable!() - }}; + }; log::debug!("received SSH_MSG_CHANNEL_OPEN_FAILURE for our channel {}", our_id); @@ -406,12 +405,12 @@ fn recv_channel_packet( let channels = st.conn_st.channels.clone(); let mut channels = channels.lock(); - guard!{let Some(conn_channel_st) = channels.get_mut(&our_id) else { + let Some(conn_channel_st) = channels.get_mut(&our_id) else { return Err(Error::Protocol(unknown_err)); - }}; - guard!{let ConnChannelState::Ready(channel_st) = conn_channel_st else { + }; + let ConnChannelState::Ready(channel_st) = conn_channel_st else { return Err(Error::Protocol(not_ready_err)); - }}; + }; callback(st, channel_st, payload) } @@ -532,9 +531,9 @@ fn send_global_request(st: &mut ClientState, req: &GlobalReq) { } fn recv_request_success(st: &mut ClientState, payload: &mut PacketDecode) -> ResultRecvState { - guard!{let Some(reply) = st.conn_st.recv_replies.pop_front() else { + let Some(reply) = st.conn_st.recv_replies.pop_front() else { return Err(Error::Protocol("received SSH_MSG_REQUEST_SUCCESS, but no reply was expected")) - }}; + }; log::debug!("received SSH_MSG_REQUEST_SUCCESS"); let payload = payload.remaining(); let _: Result<_, _> = reply.reply_tx.send(GlobalReply::Success(payload)); @@ -542,9 +541,9 @@ fn recv_request_success(st: &mut ClientState, payload: &mut PacketDecode) -> Res } fn recv_request_failure(st: &mut ClientState) -> ResultRecvState { - guard!{let Some(reply) = st.conn_st.recv_replies.pop_front() else { + let Some(reply) = st.conn_st.recv_replies.pop_front() else { return Err(Error::Protocol("received SSH_MSG_REQUEST_FAILURE, but no reply was expected")) - }}; + }; log::debug!("received SSH_MSG_REQUEST_FAILURE"); let _: Result<_, _> = reply.reply_tx.send(GlobalReply::Failure); Ok(None) diff --git a/src/host_file.rs b/src/host_file.rs index 9ecc49c..d498945 100644 --- a/src/host_file.rs +++ b/src/host_file.rs @@ -1,6 +1,5 @@ //! Support for OpenSSH-compatible `known_hosts` file. -use guard::guard; use base64::Engine as _; use bytes::{Bytes, BytesMut}; use hmac::Mac as _; @@ -373,9 +372,9 @@ impl EntryBuilder { fn pattern_matches(pattern: &Pattern, hostname: &str) -> bool { match pattern { Pattern::Hashed(pattern) => { - guard!{let Ok(mut hmac) = hmac::Hmac::::new_from_slice(&pattern.salt) else { + let Ok(mut hmac) = hmac::Hmac::::new_from_slice(&pattern.salt) else { return false; - }}; + }; hmac.update(hostname.as_bytes()); hmac.verify_slice(&pattern.hash).is_ok() }, @@ -417,9 +416,9 @@ fn decode_file(data: Bytes) -> File { fn decode_line(mut bytes: &[u8], line_i: usize) -> Result { // empty lines are treated as comments - guard!{let Some(first_field) = read_field(&mut bytes) else { + let Some(first_field) = read_field(&mut bytes) else { return Ok(LineContent::Comment) - }}; + }; // first comes the optional marker preceded with '@' let (pattern_field, marker) = if first_field[0] == b'@' { diff --git a/src/pubkey/ed25519.rs b/src/pubkey/ed25519.rs index 5bbe215..34dc872 100644 --- a/src/pubkey/ed25519.rs +++ b/src/pubkey/ed25519.rs @@ -1,5 +1,4 @@ use bytes::Bytes; -use guard::guard; use crate::codec::{PacketDecode, PacketEncode}; use crate::error::{Result, Error}; use std::fmt; @@ -40,7 +39,7 @@ impl Ed25519Privkey { } fn verify(pubkey: &Pubkey, message: &[u8], signature: Bytes) -> Result { - guard!{let Pubkey::Ed25519(pubkey) = pubkey else { return Err(Error::PubkeyFormat) }}; + let Pubkey::Ed25519(pubkey) = pubkey else { return Err(Error::PubkeyFormat) }; let mut signature = PacketDecode::new(signature); if signature.get_string()? != "ssh-ed25519" { @@ -57,7 +56,7 @@ fn verify(pubkey: &Pubkey, message: &[u8], signature: Bytes) -> Result Result { - guard!{let Privkey::Ed25519(privkey) = privkey else { return Err(Error::PrivkeyFormat) }}; + let Privkey::Ed25519(privkey) = privkey else { return Err(Error::PrivkeyFormat) }; use ed25519_dalek::Signer as _; let ed_signature = privkey.keypair.try_sign(message) diff --git a/src/pubkey/rsa.rs b/src/pubkey/rsa.rs index 24baac5..38741cd 100644 --- a/src/pubkey/rsa.rs +++ b/src/pubkey/rsa.rs @@ -1,5 +1,4 @@ use bytes::Bytes; -use guard::guard; use rsa::{PublicKey as _, PublicKeyParts as _, pkcs8}; use sha1::digest; use std::fmt; @@ -62,7 +61,7 @@ impl RsaPrivkey { } fn verify(pubkey: &Pubkey, message: &[u8], signature_blob: Bytes) -> Result { - guard!{let Pubkey::Rsa(pubkey) = pubkey else { return Err(Error::PubkeyFormat) }}; + let Pubkey::Rsa(pubkey) = pubkey else { return Err(Error::PubkeyFormat) }; let mut signature_blob = PacketDecode::new(signature_blob); if signature_blob.get_string()? != H::ALGO_NAME { @@ -83,7 +82,7 @@ fn verify(pubkey: &Pubkey, message: &[u8], signature_blob: Bytes) -> } fn sign(privkey: &Privkey, message: &[u8]) -> Result { - guard!{let Privkey::Rsa(privkey) = privkey else { return Err(Error::PrivkeyFormat) }}; + let Privkey::Rsa(privkey) = privkey else { return Err(Error::PrivkeyFormat) }; let mut hasher = H::new(); hasher.update(message);