Merge branch 'master' of ssh://git.methanium.net/methanium/mtp
All checks were successful
CI / checks (push) Successful in 5m56s

This commit is contained in:
Alex 2026-07-28 18:50:04 +02:00
commit 590810ce59
Signed by: alex
SSH key fingerprint: SHA256:D1+Ub8o0v4K5y1JNivW8IxEOelqLSvPmUzBbDIoZkRQ
10 changed files with 195 additions and 158 deletions

View file

@ -3,6 +3,7 @@ use mtp_codec::{CommunicationType, DataType, DataValue};
use mtp_codec::{CommunicationValue, Version, registry::VersionedCodec};
use mtp_common::CommunicationError;
use std::net::SocketAddr;
#[cfg(feature = "pipes")]
use std::sync::Arc;
#[cfg(feature = "pipes")]
use tokio::sync::{Mutex, mpsc};
@ -11,6 +12,7 @@ use tokio::sync::{Mutex, mpsc};
use crate::error::random_client_id;
#[cfg(feature = "pipes")]
use crate::pipe::{PipeDispatcher, PipeReceiver, PipeRequest, PipeSender, run_dispatcher};
#[cfg(feature = "pipes")]
use mtp_transport::Policy;
mod connection_capability {
@ -161,6 +163,9 @@ where
}
/// Construct an MTP connection with an explicit policy for pipe dispatch.
// The shared transport constructor keeps its argument order aligned with
// `from_transport_parts_with_remote_addr`; policy is required only here.
#[allow(clippy::too_many_arguments)]
pub fn from_transport_parts_with_policy(
version: Version,
codec: VersionedCodec,
@ -255,35 +260,6 @@ impl<S, R, P> MTPConnection<S, R, P> {
client_public_key: None,
}
}
pub fn from_transport_parts_with_policy(
version: Version,
codec: VersionedCodec,
sender: S,
receiver: R,
path: String,
description: Option<String>,
remote_addr: Option<SocketAddr>,
_policy: Arc<Policy>,
) -> Self {
Self {
version,
codec,
sender,
receiver,
path,
remote_addr,
description,
_pipe_stream: std::marker::PhantomData,
_dispatcher_task: tokio::spawn(async {}),
#[cfg(feature = "crypto")]
auth_state: crate::error::AuthState::Unauthenticated,
#[cfg(feature = "crypto")]
client_id: random_client_id(),
#[cfg(feature = "crypto")]
client_public_key: None,
}
}
}
#[cfg(not(feature = "pipes"))]

View file

@ -33,8 +33,7 @@ pub trait HandshakeSender: Send + Sync {
pub trait HandshakeReceiver: Send + Sync {
fn receive(
&self,
) -> impl std::future::Future<Output = Result<CommunicationValue, CommunicationError>>
+ Send;
) -> impl std::future::Future<Output = Result<CommunicationValue, CommunicationError>> + Send;
}
/// The result of a successful handshake, containing everything needed to
@ -136,7 +135,10 @@ impl HandshakeEngine {
}
};
let negotiated = match self.registry.negotiate(std::slice::from_ref(&client_version)) {
let negotiated = match self
.registry
.negotiate(std::slice::from_ref(&client_version))
{
Some(v) => v,
None => {
send_rejection_generic(
@ -300,24 +302,23 @@ impl HandshakeEngine {
_ => 0,
};
if cid > 0 {
if let Some(bundle) =
if cid > 0
&& let Some(bundle) =
(self.config.get_existing_client)(cid, description.clone()).await
{
return self
.complete_auth_handshake(
sender,
receiver,
Flow::Login { id: cid, bundle },
CommunicationType::IdentificationResponse,
&negotiated,
&codec,
description,
version_str,
client_version,
)
.await;
}
{
return self
.complete_auth_handshake(
sender,
receiver,
Flow::Login { id: cid, bundle },
CommunicationType::IdentificationResponse,
&negotiated,
&codec,
description,
version_str,
client_version,
)
.await;
}
// Unknown or zero ID: fall back to guest
@ -634,8 +635,8 @@ impl HandshakeEngine {
DataValue::UnsignedNumber(client_nonce),
)
.add_typed_default(DataType::Signature, DataValue::Bytes(host_sig));
response = response
.add_typed_default(DataType::Version, DataValue::Str(negotiated.to_string()));
response =
response.add_typed_default(DataType::Version, DataValue::Str(negotiated.to_string()));
if pq_enabled {
response =
response.add_typed_default(DataType::PqSignature, DataValue::Bytes(host_pq_sig));
@ -722,19 +723,15 @@ fn extract_register_bundle(
msg: &CommunicationValue,
) -> Result<mtp_crypto::PublicKeyBundle, AcceptError> {
match msg.get_data(DataType::PublicKeys) {
DataValue::Bytes(b) => mtp_crypto::PublicKeyBundle::from_bytes(b).map_err(|_| {
AcceptError::AuthenticationFailed("invalid public key bundle".into())
}),
DataValue::Bytes(b) => mtp_crypto::PublicKeyBundle::from_bytes(b)
.map_err(|_| AcceptError::AuthenticationFailed("invalid public key bundle".into())),
_ => Err(AcceptError::AuthenticationFailed(
"missing public keys".into(),
)),
}
}
async fn send_rejection_generic<S: HandshakeSender>(
sender: &S,
reason: RejectionReason,
) {
async fn send_rejection_generic<S: HandshakeSender>(sender: &S, reason: RejectionReason) {
let response = match &reason {
RejectionReason::BadVersion { supported_versions } => {
CommunicationValue::new(CommunicationType::ErrorBadVersion)
@ -815,7 +812,9 @@ impl<C: mtp_transport::TransportConnection> HandshakeSender for mtp_transport::G
}
}
impl<C: mtp_transport::TransportConnection> HandshakeReceiver for mtp_transport::GenericReceiver<C> {
impl<C: mtp_transport::TransportConnection> HandshakeReceiver
for mtp_transport::GenericReceiver<C>
{
fn receive(
&self,
) -> impl std::future::Future<Output = Result<CommunicationValue, CommunicationError>> + Send

View file

@ -1,7 +1,10 @@
#[cfg(not(feature = "crypto"))]
use mtp_codec::{Version, registry::{Registry, VersionedCodec}};
#[cfg(feature = "crypto")]
use mtp_codec::registry::Registry;
#[cfg(not(feature = "crypto"))]
use mtp_codec::{
Version,
registry::{Registry, VersionedCodec},
};
use mtp_transport::{Receiver, Sender};
use std::sync::Arc;
use std::time::Instant;
@ -136,9 +139,7 @@ impl HandshakeContext {
#[cfg(feature = "crypto")]
{
Ok(Some(self.connection_from_handshake_result(
sender,
receiver,
result,
sender, receiver, result,
)))
}
#[cfg(not(feature = "crypto"))]

View file

@ -11,7 +11,7 @@ pub use MTPHost as Host;
pub use config::HostConfig;
pub use config::Policy;
pub use connection::{MTPConnection, MtpReceiverLike, MtpSenderLike};
pub use engine::{HandshakeEngine, HandshakeResult, HandshakeReceiver, HandshakeSender};
pub use engine::{HandshakeEngine, HandshakeReceiver, HandshakeResult, HandshakeSender};
pub use error::AcceptError;
pub use handshake::MTPHost;
pub use mtp_transport::Receiver;