diff --git a/sshproto/src/auth.rs b/sshproto/src/auth.rs index 03e2dd91f2ddac5fe8537d670e1ee8811f621c94..5646f3ebc78b054c7fd7685930ed7c301c3adc75 100644 --- a/sshproto/src/auth.rs +++ b/sshproto/src/auth.rs @@ -10,7 +10,6 @@ use heapless::{String, Vec}; use crate::*; use behaviour::CliBehaviour; use client::*; -use conn::RespPackets; use packets::ParseContext; use packets::{Packet, Signature, Userauth60}; use sign::SignKey; diff --git a/sshproto/src/behaviour.rs b/sshproto/src/behaviour.rs index ebbe27eccfc11cca96e61c7d979c2365cf341a77..75f67af23292a6b54f209c5ba905f83f525cf6c9 100644 --- a/sshproto/src/behaviour.rs +++ b/sshproto/src/behaviour.rs @@ -6,7 +6,7 @@ use { use snafu::prelude::*; -use crate::{*, conn::RespPackets}; +use crate::*; use packets::{ForwardedTcpip,DirectTcpip}; use channel::ChanOpened; use sshnames::*; diff --git a/sshproto/src/channel.rs b/sshproto/src/channel.rs index f116e1226bfa2b6582eae6f8ac946569732d1a66..31ae28a450d6e810e6733b1f726b3ab4f26652a6 100644 --- a/sshproto/src/channel.rs +++ b/sshproto/src/channel.rs @@ -8,9 +8,10 @@ use core::mem; use heapless::{Deque, String, Vec}; -use crate::{conn::RespPackets, *, packets::ChannelOpenFailure}; +use crate::*; use config::*; -use packets::{ChannelReqType, ChannelRequest, Packet, ChannelOpen, ChannelOpenType, ChannelData, ChannelDataExt}; +use packets::{ChannelReqType, ChannelOpenFailure, ChannelRequest, Packet, ChannelOpen, ChannelOpenType, ChannelData, ChannelDataExt}; +use traffic::TrafSend; use sshwire::{BinString, TextString}; use sshnames::*; @@ -196,20 +197,18 @@ impl Channels { } fn dispatch_open(&mut self, p: &ChannelOpen<'_>, - resp: &mut RespPackets<'_>, + s: &TrafSend, b: &mut Behaviour<'_>, ) -> Result<()> { - match self.dispatch_open_inner(p, resp, b) { + match self.dispatch_open_inner(p, s, b) { Err(DispatchOpenError::Failure(f)) => { - let r = packets::ChannelOpenFailure { + s.send(packets::ChannelOpenFailure { num: p.num, reason: f as u32, desc: "".into(), lang: "", - }; - let r: Packet = r.into(); - resp.push(r.into()).trap()?; + })?; Ok(()) }, Err(DispatchOpenError::Error(e)) => Err(e), @@ -219,7 +218,7 @@ impl Channels { // the caller will send failure messages if required fn dispatch_open_inner(&mut self, p: &ChannelOpen<'_>, - resp: &mut RespPackets<'_>, + s: &TrafSend, b: &mut Behaviour<'_>, ) -> Result<(), DispatchOpenError> { @@ -261,7 +260,7 @@ impl Channels { match r { ChanOpened::Success => { - resp.push(ch.open_done().into()).trap()? + s.send(ch.open_done())?; }, ChanOpened::Failure(f) => { let n = ch.recv.num; @@ -278,8 +277,8 @@ impl Channels { pub fn dispatch_request(&mut self, p: &packets::ChannelRequest, - resp: &mut RespPackets<'_>, - b: &mut Behaviour<'_>, + _s: &TrafSend, + _b: &mut Behaviour<'_>, ) -> Result<()> { let ch = match self.get(p.num) { Ok(ch) => ch, @@ -300,13 +299,13 @@ impl Channels { pub async fn dispatch( &mut self, packet: Packet<'_>, - resp: &mut RespPackets<'_>, + s: &TrafSend<'_>, b: &mut Behaviour<'_>, ) -> Result<Option<ChanEventMaker>> { trace!("chan dispatch"); let r = match packet { Packet::ChannelOpen(p) => { - self.dispatch_open(&p, resp, b)?; + self.dispatch_open(&p, s, b)?; Ok(None) } @@ -324,7 +323,7 @@ impl Channels { window: p.initial_window as usize, }); for r in init_req { - ch.request(r, resp)? + ch.request(r, s)? } ch.state = ChanState::Normal; } @@ -381,7 +380,7 @@ impl Channels { Ok(None) } Packet::ChannelRequest(p) => { - self.dispatch_request(&p, resp, b)?; + self.dispatch_request(&p, s, b)?; Ok(None) } Packet::ChannelSuccess(_p) => { @@ -577,11 +576,10 @@ impl Channel { } } - fn request(&mut self, req: ReqDetails, resp: &mut RespPackets) -> Result<()> { + fn request(&mut self, req: ReqDetails, s: &TrafSend) -> Result<()> { let num = self.send.as_ref().trap()?.num; let r = Req { num, details: req }; - resp.push(r.into()).trap()?; - Ok(()) + s.send(r.packet()?) } pub(crate) fn number(&self) -> u32 { diff --git a/sshproto/src/cliauth.rs b/sshproto/src/cliauth.rs index cd517ab2c0b3dba17dbd6a7933956706b297ad94..b9a66083778756e761eb600722ca413fbadd0e9e 100644 --- a/sshproto/src/cliauth.rs +++ b/sshproto/src/cliauth.rs @@ -12,8 +12,8 @@ use pretty_hex::PrettyHex; use crate::{packets::UserauthPkOk, *}; use behaviour::CliBehaviour; +use traffic::TrafSend; use client::*; -use conn::RespPackets; use packets::{MessageNumber, AuthMethod, MethodPubKey, ParseContext, UserauthRequest}; use packets::{Packet, Signature, Userauth60}; use sign::{SignKey, OwnedSig}; @@ -96,24 +96,22 @@ impl CliAuth { // May be called multiple times pub async fn start<'b>( &'b mut self, - resp: &mut RespPackets<'b>, + s: &TrafSend<'_>, b: &mut dyn CliBehaviour, ) -> Result<()> { if let AuthState::Unstarted = self.state { self.state = AuthState::MethodQuery; self.username = b.username()?; - let p: Packet = packets::ServiceRequest { + s.send(packets::ServiceRequest { name: SSH_SERVICE_USERAUTH, - }.into(); - resp.push(p.into()).trap()?; + })?; - let p: Packet = packets::UserauthRequest { + s.send(packets::UserauthRequest { username: self.username.as_str().into(), service: SSH_SERVICE_CONNECTION, method: packets::AuthMethod::None, - }.into(); - resp.push(p.into()).trap()?; + })?; } Ok(()) } @@ -182,14 +180,14 @@ impl CliAuth { pub async fn auth60<'b>( &'b mut self, auth60: &packets::Userauth60<'_>, - resp: &mut RespPackets<'b>, sess_id: &SessId, parse_ctx: &mut ParseContext, + s: &TrafSend<'_>, ) -> Result<()> { parse_ctx.cli_auth_type = None; match auth60 { - Userauth60::PkOk(pkok) => self.auth_pkok(pkok, resp, sess_id, parse_ctx), + Userauth60::PkOk(pkok) => self.auth_pkok(pkok, sess_id, parse_ctx, s), _ => todo!(), } } @@ -197,9 +195,9 @@ impl CliAuth { fn auth_pkok<'b>( &'b mut self, pkok: &UserauthPkOk<'_>, - resp: &mut RespPackets<'b>, sess_id: &SessId, parse_ctx: &mut ParseContext, + s: &TrafSend<'_>, ) -> Result<()> { // We are only sending keys one at a time so they shouldn't // get out of sync. In future we could change it to send @@ -237,7 +235,7 @@ impl CliAuth { let rsig = &*rsig; *psig = Some(Blob(rsig.into())) } - resp.push(p.into()).trap()?; + s.send(p)?; return Ok(()); } } @@ -251,9 +249,9 @@ impl CliAuth { pub async fn failure<'b>( &'b mut self, failure: &packets::UserauthFailure<'_>, - b: &mut dyn CliBehaviour, - resp: &mut RespPackets<'b>, parse_ctx: &mut ParseContext, + s: &TrafSend<'_>, + b: &mut dyn CliBehaviour, ) -> Result<()> { parse_ctx.cli_auth_type = None; // TODO: look at existing self.state, handle the failure. @@ -287,7 +285,7 @@ impl CliAuth { if let AuthState::Request { last_req, .. } = &self.state { let p = last_req.req_packet(&self.username, parse_ctx)?; - resp.push(p.into()).trap()?; + s.send(p)?; } Ok(()) } diff --git a/sshproto/src/client.rs b/sshproto/src/client.rs index e2d61ff3de159f006268d7ba74652306c1ed1c7b..eef52c109acebf63008e115d9a93704464c4fa38 100644 --- a/sshproto/src/client.rs +++ b/sshproto/src/client.rs @@ -8,9 +8,9 @@ use snafu::prelude::*; use crate::{*, packets::ChannelOpen}; use packets::{Packet, PubKey, ParseContext}; +use traffic::TrafSend; use sshnames::*; use cliauth::CliAuth; -use conn::RespPackets; use sign::SignKey; use behaviour::CliBehaviour; use heapless::String; @@ -28,13 +28,13 @@ impl Client { // pub fn check_hostkey(hostkey: ) - pub(crate) fn auth_success(&mut self, resp: &mut RespPackets<'_>, + pub(crate) fn auth_success(&mut self, parse_ctx: &mut ParseContext, + s: &TrafSend, b: &mut dyn CliBehaviour) -> Result<()> { parse_ctx.cli_auth_type = None; - let p: Packet = packets::ServiceRequest { name: SSH_SERVICE_CONNECTION }.into(); - resp.push(p.into()).trap()?; + s.send(packets::ServiceRequest { name: SSH_SERVICE_CONNECTION })?; self.auth.success(b) } diff --git a/sshproto/src/conn.rs b/sshproto/src/conn.rs index 4c5b830b20136754e02d91b4f013a8b5d8bd4f49..6c73b0fdbdc8d8083a9847223b885cd5957068f4 100644 --- a/sshproto/src/conn.rs +++ b/sshproto/src/conn.rs @@ -17,20 +17,11 @@ use client::Client; use encrypt::KeyState; use packets::{Packet,ParseContext}; use server::Server; -use traffic::{Traffic,PacketMaker}; +use traffic::{Traffic, TrafSend}; use channel::{Channels, ChanEvent, ChanEventMaker}; use config::MAX_CHANNELS; use kex::SessId; -// TODO a max value needs to be analysed -pub(crate) const MAX_RESPONSES: usize = 4; - -pub type RespPackets<'a> = heapless::Vec<PacketMaker<'a>, MAX_RESPONSES>; - -pub(crate) enum Handled<'a> { - Response(RespPackets<'a>), -} - /// The core state of a SSH instance. pub struct Conn<'a> { state: ConnState, @@ -133,13 +124,12 @@ impl<'a> Conn<'a> { b: &mut Behaviour<'_>, ) -> Result<(), Error> { debug!("progress conn state {:?}", self.state); - let mut resp = RespPackets::new(); + let s = TrafSend::new(traffic, keys); match self.state { ConnState::SendIdent => { traffic.send_version(ident::OUR_VERSION)?; - let p = self.kex.make_kexinit(&self.algo_conf); + let p = self.kex.send_kexinit(&self.algo_conf, &s)?; // TODO: first_follows would have a second packet here - resp.push(p.into()).trap()?; self.state = ConnState::ReceiveIdent } ConnState::ReceiveIdent => { @@ -152,7 +142,7 @@ impl<'a> Conn<'a> { // and backpressure. can_output() should have a size check? if traffic.can_output() { if let ClientServer::Client(cli) = &mut self.cliserv { - cli.auth.start(&mut resp, b.client()?).await?; + cli.auth.start(&s, b.client()?).await?; } } // send userauth request @@ -162,9 +152,6 @@ impl<'a> Conn<'a> { // TODO } } - for r in resp { - r.send_packet(traffic, keys)?; - } // TODO: if keys.seq > MAX_REKEY then we must rekey for security. @@ -185,30 +172,27 @@ impl<'a> Conn<'a> { /// after `handle_payload()` runs. pub(crate) async fn handle_payload<'p>( &mut self, payload: &'p [u8], seq: u32, - keys: &mut KeyState, b: &mut Behaviour<'_>, - ) -> Result<Dispatched<'_>, Error> { + s: &TrafSend<'_>, + b: &mut Behaviour<'_>, + ) -> Result<Dispatched, Error> { let r = sshwire::packet_from_bytes(payload, &self.parse_ctx); match r { - Ok(p) => self.dispatch_packet(p, keys, b).await, + Ok(p) => self.dispatch_packet(p, s, b).await, Err(Error::UnknownPacket { number }) => { trace!("Unimplemented packet type {number}"); - let p: Packet = packets::Unimplemented { seq }.into(); - let mut resp = RespPackets::new(); - // unwrap is OK, single packet has space - resp.push(p.into()).unwrap(); - Ok(Dispatched { resp, event: None }) + s.send(packets::Unimplemented { seq })?; + Ok(Dispatched { event: None }) } Err(e) => return Err(e), } } async fn dispatch_packet<'p>( - &mut self, packet: Packet<'p>, keys: &mut KeyState, b: &mut Behaviour<'_>, - ) -> Result<Dispatched<'_>, Error> { + &mut self, packet: Packet<'p>, s: &TrafSend<'_>, b: &mut Behaviour<'_>, + ) -> Result<Dispatched, Error> { // TODO: perhaps could consolidate packet allowed checks into a separate function // to run first? trace!("Incoming {packet:#?}"); - let mut resp = RespPackets::new(); let mut event = None; match packet { Packet::KexInit(_) => { @@ -220,14 +204,12 @@ impl<'a> Conn<'a> { output: None, }; let r = self.kex.handle_kexinit( + &packet, self.cliserv.is_client(), &self.algo_conf, &self.remote_version, - &packet, + s, )?; - if let Some(r) = r { - resp.push(r.into()).trap()?; - } } Packet::KexDHInit(p) => { match self.state { @@ -241,9 +223,7 @@ impl<'a> Conn<'a> { } else { let kex = core::mem::replace(&mut self.kex, kex::Kex::new()?); - *output = Some(kex.handle_kexdhinit(&p, &self.sess_id)?); - let reply = output.as_mut().trap()?.make_kexdhreply(b.server()?).await?; - resp.push(reply.into()).trap()?; + *output = Some(kex.handle_kexdhinit(&p, &self.sess_id, s, b.server()?)?); } } _ => return Err(Error::PacketWrong), @@ -258,8 +238,7 @@ impl<'a> Conn<'a> { } else { let kex = core::mem::replace(&mut self.kex, kex::Kex::new()?); - *output = Some(kex.handle_kexdhreply(&p, &self.sess_id, b.client()?).await?); - resp.push(Packet::NewKeys(packets::NewKeys {}).into()).trap()?; + *output = Some(kex.handle_kexdhreply(&p, &self.sess_id, s, b.client()?).await?); } } else { // TODO: client/server validity checks should move somewhere more general @@ -274,7 +253,7 @@ impl<'a> Conn<'a> { ConnState::InKex { done_auth, ref mut output } => { // NewKeys shouldn't be received before kexdhinit/kexdhreply let output = output.take().ok_or(Error::PacketWrong)?; - keys.rekey(output.keys); + s.rekey(output.keys); self.sess_id.get_or_insert(output.h); self.state = if done_auth { ConnState::Authed @@ -313,7 +292,7 @@ impl<'a> Conn<'a> { Packet::UserauthFailure(p) => { // TODO: client only if let ClientServer::Client(cli) = &mut self.cliserv { - cli.auth.failure(&p, b.client()?, &mut resp, &mut self.parse_ctx).await?; + cli.auth.failure(&p, &mut self.parse_ctx, s, b.client()?).await?; } else { debug!("Received UserauthFailure as a server"); return Err(Error::SSHProtoError) @@ -324,7 +303,7 @@ impl<'a> Conn<'a> { if let ClientServer::Client(cli) = &mut self.cliserv { if matches!(self.state, ConnState::PreAuth) { self.state = ConnState::Authed; - cli.auth_success(&mut resp, &mut self.parse_ctx, b.client()?)?; + cli.auth_success(&mut self.parse_ctx, s, b.client()?)?; event = Some(EventMaker::CliAuthed); } else { debug!("Received UserauthSuccess unrequested") @@ -346,7 +325,7 @@ impl<'a> Conn<'a> { Packet::Userauth60(p) => { // TODO: client only if let ClientServer::Client(cli) = &mut self.cliserv { - cli.auth.auth60(&p, &mut resp, self.sess_id.as_ref().trap()?, &mut self.parse_ctx).await?; + cli.auth.auth60(&p, self.sess_id.as_ref().trap()?, &mut self.parse_ctx, s).await?; } else { debug!("Received userauth60 as a server"); return Err(Error::SSHProtoError) @@ -365,11 +344,11 @@ impl<'a> Conn<'a> { | Packet::ChannelFailure(_) // TODO: maybe needs a conn or cliserv argument. => { - let chev = self.channels.dispatch(packet, &mut resp, b).await?; + let chev = self.channels.dispatch(packet, s, b).await?; event = chev.map(|c| EventMaker::Channel(c)) } }; - Ok(Dispatched { resp, event }) + Ok(Dispatched { event }) } /// creates an `Event` that borrows data from the payload. Some `Event` variants don't @@ -394,13 +373,8 @@ impl<'a> Conn<'a> { } -// pub(crate) struct Dispatched<'r, 'e> { -// pub resp: RespPackets<'r>, -// pub event: Option<Event<'e>>, -// } - -pub(crate) struct Dispatched<'r> { - pub resp: RespPackets<'r>, +// TODO: delete this +pub(crate) struct Dispatched { pub event: Option<EventMaker>, } diff --git a/sshproto/src/kex.rs b/sshproto/src/kex.rs index 88543e83cc90ed8c8cf544fa4c25936d85d8ff94..431f68d63b00614a6b92b2516348cc9b6a80f644 100644 --- a/sshproto/src/kex.rs +++ b/sshproto/src/kex.rs @@ -14,6 +14,7 @@ use digest::Digest; use crate::*; use encrypt::{Cipher, Integ, Keys}; use ident::RemoteVersion; +use traffic::TrafSend; use namelist::LocalNames; use packets::{Packet, PubKey, Signature}; use sign::SigType; @@ -198,11 +199,11 @@ impl Kex { Ok(Kex { our_cookie, algos: None, kex_hash: None }) } - /// Returns `Option<Packet>` with an optional kexdhinit message to send pub fn handle_kexinit( - &mut self, is_client: bool, algo_conf: &AlgoConfig, - remote_version: &RemoteVersion, p: &packets::Packet, - ) -> Result<Option<Packet>> { + &mut self, p: &packets::Packet, is_client: bool, algo_conf: &AlgoConfig, + remote_version: &RemoteVersion, + s: &TrafSend, + ) -> Result<()> { let remote_kexinit = if let Packet::KexInit(k) = p { k } else { return Err(Error::bug()) }; let algos = Self::algo_negotiation(is_client, remote_kexinit, algo_conf)?; @@ -212,10 +213,12 @@ impl Kex { self.algos = Some(algos); if is_client { - Ok(Some(self.algos.as_ref().trap()?.kex.make_kexdhinit()?)) - } else { - Ok(None) + // unwrap safe: was just set + let p = self.algos.as_ref().unwrap().kex.make_kexdhinit()?; + s.send(p)?; } + + Ok(()) } pub fn maybe_discard_packet(&mut self) -> bool { @@ -226,8 +229,8 @@ impl Kex { } } - pub fn make_kexinit<'a>(&self, conf: &'a AlgoConfig) -> packets::Packet<'a> { - packets::KexInit { + pub fn send_kexinit<'a>(&self, conf: &'a AlgoConfig, s: &TrafSend) -> Result<()> { + s.send(packets::KexInit { cookie: self.our_cookie, kex: (&conf.kexs).into(), hostkey: (&conf.hostsig).into(), @@ -241,7 +244,7 @@ impl Kex { lang_s2c: (&EMPTY_LOCALNAMES).into(), first_follows: false, reserved: 0, - }.into() + }) } fn make_kexdhinit(&self) -> Result<Packet> { @@ -252,27 +255,32 @@ impl Kex { algos.kex.make_kexdhinit() } - // returns packet to send, and kex output - // consumes self. + // returns kex output, consumes self. pub fn handle_kexdhinit<'a>( self, p: &packets::KexDHInit, sess_id: &Option<SessId>, + s: &TrafSend, b: &mut dyn ServBehaviour, ) -> Result<KexOutput> { if self.algos.as_ref().trap()?.is_client { return Err(Error::bug()); } - SharedSecret::handle_kexdhinit(self, p, sess_id) + let kex_out = SharedSecret::handle_kexdhinit(self, p, sess_id, s, b)?; + s.send(packets::NewKeys {})?; + Ok(kex_out) } // returns packet to send, and H exchange hash. // consumes self. pub async fn handle_kexdhreply<'f>( self, p: &packets::KexDHReply<'f>, sess_id: &Option<SessId>, + s: &TrafSend<'_>, b: &mut dyn CliBehaviour, ) -> Result<KexOutput> { if !self.algos.as_ref().trap()?.is_client { return Err(Error::bug()); } - SharedSecret::handle_kexdhreply(self, p, sess_id, b).await + let kex_out = SharedSecret::handle_kexdhreply(self, p, sess_id, b).await?; + s.send(packets::NewKeys {})?; + Ok(kex_out) } /// Perform SSH algorithm negotiation @@ -434,6 +442,7 @@ impl SharedSecret { // server only. consumes kex. fn handle_kexdhinit<'a>( mut kex: Kex, p: &packets::KexDHInit, sess_id: &Option<SessId>, + s: &TrafSend, b: &mut dyn ServBehaviour, ) -> Result<KexOutput> { // let mut algos = kex.algos.take().trap()?; let mut algos = kex.algos.trap()?; @@ -441,19 +450,32 @@ impl SharedSecret { // TODO let fake_hostkey = PubKey::Ed25519(packets::Ed25519PubKey{ key: BinString(&[]) }); kex_hash.prefinish(&fake_hostkey, p.q_c.0, algos.kex.pubkey())?; - let kex_out = match algos.kex { + let (kex_pub, kex_out) = match algos.kex { SharedSecret::KexCurve25519(ref k) => { let pubkey: salty::agreement::PublicKey = k.ours.as_ref().trap()?.into(); - let mut kex_out = KexCurve25519::secret(&mut algos, p.q_c.0, kex_hash, sess_id)?; - kex_out.kex_pub = Some(pubkey.to_bytes()); - kex_out + let kex_out = KexCurve25519::secret(&mut algos, p.q_c.0, kex_hash, sess_id)?; + (&pubkey.to_bytes(), kex_out) } }; + kex.send_kexdhreply(kex_pub, s, b)?; Ok(kex_out) } - fn pubkey<'a>(&'a self) -> &'a [u8] { + // server only + pub fn send_kexdhreply(&self, kex_pub: &[u8], s: &TrafSend, b: &mut dyn ServBehaviour) -> Result<()> { + let q_s = BinString(kex_pub); + + // hostkeys list must contain the signature type + let key = b.hostkeys()?.iter().find(|k| k.can_sign(&self.algos.hostsig)).trap()?; + let k_s = Blob(key.pubkey()); + self.sig = Some(key.sign(&self.h.as_slice(), None)?); + let sig: Signature = self.sig.as_ref().unwrap().into(); + let sig = Blob(sig); + Ok(packets::KexDHReply { k_s, q_s, sig }.into()) + } + + fn pubkey(&self) -> &[u8] { match self { SharedSecret::KexCurve25519(k) => k.pubkey(), } @@ -491,21 +513,9 @@ impl<'a> KexOutput { let sess_id = sess_id.as_ref().unwrap_or(&h); let keys = Keys::new_from(k, &h, &sess_id, algos)?; - Ok(KexOutput { h, keys, kex_pub: None, sig_type: algos.hostsig, sig: None }) + Ok(KexOutput { h, keys }) } - // server only - pub async fn make_kexdhreply<'b>(&'a mut self, b: &'a mut dyn ServBehaviour) -> Result<Packet<'a>> { - let q_s = BinString(self.kex_pub.as_ref().trap()?); - - // hostkeys list must contain the signature type - let key = b.hostkeys()?.iter().find(|k| k.can_sign(&self.sig_type)).trap()?; - let k_s = Blob(key.pubkey()); - self.sig = Some(key.sign(&self.h.as_slice(), None)?); - let sig: Signature = self.sig.as_ref().unwrap().into(); - let sig = Blob(sig); - Ok(packets::KexDHReply { k_s, q_s, sig }.into()) - } } pub(crate) struct KexCurve25519 { diff --git a/sshproto/src/lib.rs b/sshproto/src/lib.rs index 9a98b0cb2beff6bbf725a03a0df7ac73c777c626..9dac0a9a675c42f8a2e3b28a6992dd63be1d6b7b 100644 --- a/sshproto/src/lib.rs +++ b/sshproto/src/lib.rs @@ -47,7 +47,6 @@ pub mod config; pub use behaviour::{Behaviour, ServBehaviour, CliBehaviour, BhError, BhResult, ResponseString}; pub use runner::Runner; -pub use conn::RespPackets; pub use sign::SignKey; pub use packets::PubKey; pub use error::{Error,Result}; diff --git a/sshproto/src/runner.rs b/sshproto/src/runner.rs index 19ade4a165282d83ad6fcd804a7c78ff5d852f35..dc313634e2d580143e25656470c167ea01bf1b9a 100644 --- a/sshproto/src/runner.rs +++ b/sshproto/src/runner.rs @@ -10,7 +10,7 @@ use pretty_hex::PrettyHex; use crate::{*, channel::ChanEvent}; use encrypt::KeyState; -use traffic::Traffic; +use traffic::{Traffic, TrafSend}; use conn::{Conn, Dispatched, EventMaker, Event}; use channel::ChanEventMaker; @@ -95,16 +95,15 @@ impl<'a> Runner<'a> { // by the send_packet(). // After that progress() can perform more send_packet() itself. - let d = self.conn.handle_payload(payload, seq, &mut self.keys, behaviour).await?; + // TODO matt aug: trafsend should be constructed by traffic.split_send() or something. + let s = TrafSend::new(&mut self.traffic, &mut self.keys); + let d = self.conn.handle_payload(payload, seq, &s, behaviour).await?; self.traffic.handled_payload()?; - if !d.resp.is_empty() || d.event.is_none() { + if d.event.is_none() { // switch to using the buffer for output. self.traffic.done_payload()?; } - for r in d.resp { - r.send_packet(&mut self.traffic, &mut self.keys)?; - } d.event } else { diff --git a/sshproto/src/traffic.rs b/sshproto/src/traffic.rs index 31269034a7460be5f6a9ea387e719eacb8a07de9..a8d123f21d59c54019629f28f3cee7e6b69fe947 100644 --- a/sshproto/src/traffic.rs +++ b/sshproto/src/traffic.rs @@ -78,33 +78,6 @@ enum RxState { }, } -#[derive(Debug)] -pub enum PacketMaker<'a> { - Packet(Packet<'a>), - ChanReq(channel::Req), -} - -impl<'a> From<Packet<'a>> for PacketMaker<'a> { - fn from(p: Packet<'a>) -> Self { - PacketMaker::Packet(p) - } -} - -impl From<channel::Req> for PacketMaker<'_> { - fn from(r: channel::Req) -> Self { - PacketMaker::ChanReq(r) - } -} - -impl<'a> PacketMaker<'a> { - pub(crate) fn send_packet(self, traffic: &mut Traffic, keys: &mut KeyState) -> Result<()> { - match self { - Self::Packet(p) => traffic.send_packet(p, keys), - Self::ChanReq(r) => traffic.send_packet(r.packet()?, keys), - } - } -} - impl<'a> Traffic<'a> { pub fn new(rx_buf: &'a mut [u8], tx_buf: &'a mut [u8]) -> Self { Traffic { tx_buf, rx_buf, @@ -415,3 +388,25 @@ impl<'a> Traffic<'a> { } } + +pub(crate) struct TrafSend<'a> { + traffic: &'a mut Traffic<'a>, + keys: &'a mut KeyState, +} + +impl<'a> TrafSend<'a> { + pub fn new(traffic: &mut Traffic, keys: &mut KeyState) -> Self { + Self { + traffic, + keys, + } + } + + pub fn send<'p, P: Into<packets::Packet<'p>>>(&self, p: P) -> Result<()> { + self.traffic.send_packet(p.into(), self.keys) + } + + pub fn rekey(&self, keys: encrypt::Keys) { + self.keys.rekey(keys) + } +}