[WIP] Security work While on holiday
This commit is contained in:
parent
a81ac4efca
commit
7f0231e3f1
109 changed files with 19694 additions and 5210 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use mtp_codec::{CommunicationValue, Version};
|
||||
use mtp_codec::{CommunicationValue, Version, registry::VersionedCodec};
|
||||
#[cfg(feature = "pipes")]
|
||||
use mtp_codec::{DataType, DataValue};
|
||||
use mtp_common::CommunicationError;
|
||||
|
|
@ -17,6 +17,7 @@ use crate::pipe::{PendingRequest, PipeDispatcher, run_dispatcher};
|
|||
|
||||
pub struct MTPConnection {
|
||||
pub version: Version,
|
||||
pub codec: VersionedCodec,
|
||||
pub sender: mtp_transport::Sender,
|
||||
pub receiver: mtp_transport::Receiver,
|
||||
pub description: Option<String>,
|
||||
|
|
@ -45,12 +46,19 @@ impl MTPConnection {
|
|||
request: &CommunicationValue,
|
||||
expected_response: Option<mtp_codec::CommunicationType>,
|
||||
) -> Result<CommunicationValue, CommunicationError> {
|
||||
let request_id = request.get_id();
|
||||
let request_id = request
|
||||
.id()
|
||||
.ok_or_else(|| CommunicationError::Other("request frame must contain an id".into()))?;
|
||||
if request_id == 0 {
|
||||
return Err(CommunicationError::Other(
|
||||
"request frame must have a non-zero id".into(),
|
||||
));
|
||||
}
|
||||
if crate::pipe::is_expired_request(&self.pipe_dispatcher, request_id).await {
|
||||
return Err(CommunicationError::Other(format!(
|
||||
"request id {request_id} recently timed out; use a new request id"
|
||||
)));
|
||||
}
|
||||
|
||||
let (sender, receiver) = tokio::sync::oneshot::channel();
|
||||
let token = Arc::new(());
|
||||
|
|
@ -86,7 +94,7 @@ impl MTPConnection {
|
|||
result?
|
||||
}
|
||||
Err(_) => {
|
||||
crate::pipe::remove_pending_request(&self.pipe_dispatcher, request_id, &token)
|
||||
crate::pipe::expire_pending_request(&self.pipe_dispatcher, request_id, &token)
|
||||
.await;
|
||||
return Err(CommunicationError::Other(format!(
|
||||
"request {request_id} timed out after {:?}",
|
||||
|
|
@ -96,7 +104,7 @@ impl MTPConnection {
|
|||
};
|
||||
|
||||
if let Some(expected) = expected_response {
|
||||
let expected_type = expected.try_to_id(&mtp_codec::TypeMap::latest());
|
||||
let expected_type = expected.try_to_id(self.codec.type_map());
|
||||
if Some(response.get_type()) != expected_type {
|
||||
return Err(CommunicationError::Other(format!(
|
||||
"unexpected response type: expected {:?}, got {:?}; parsed {}",
|
||||
|
|
@ -125,23 +133,35 @@ impl MTPConnection {
|
|||
&self,
|
||||
description: &str,
|
||||
) -> Result<crate::pipe::PipeHandle, mtp_common::PipeError> {
|
||||
let pipe_id = rand::random::<u32>();
|
||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||
|
||||
{
|
||||
let pipe_id = {
|
||||
let mut pending = self.pipe_dispatcher.pending_creations.lock().await;
|
||||
let pipe_id = loop {
|
||||
let candidate = rand::random::<u32>();
|
||||
if candidate != 0 && !pending.contains_key(&candidate) {
|
||||
break candidate;
|
||||
}
|
||||
};
|
||||
pending.insert(pipe_id, tx);
|
||||
pipe_id
|
||||
};
|
||||
|
||||
let request = CommunicationValue::new_with_type_map(
|
||||
mtp_codec::CommunicationType::PipeRequest,
|
||||
self.codec.type_map(),
|
||||
)
|
||||
.with_id(pipe_id)
|
||||
.add_typed_default(DataType::Description, DataValue::Str(description.into()));
|
||||
|
||||
if let Err(error) = self.sender.send(&request).await {
|
||||
self.pipe_dispatcher
|
||||
.pending_creations
|
||||
.lock()
|
||||
.await
|
||||
.remove(&pipe_id);
|
||||
return Err(mtp_common::PipeError::from(error));
|
||||
}
|
||||
|
||||
let request = CommunicationValue::new(mtp_codec::CommunicationType::PipeRequest)
|
||||
.with_id(pipe_id)
|
||||
.add_typed_default(DataType::Description, DataValue::Str(description.into()));
|
||||
|
||||
self.sender
|
||||
.send(&request)
|
||||
.await
|
||||
.map_err(mtp_common::PipeError::from)?;
|
||||
|
||||
Ok(crate::pipe::PipeHandle {
|
||||
pipe_id,
|
||||
description: description.to_string(),
|
||||
|
|
@ -164,11 +184,26 @@ pub(crate) async fn connection_from_parts(
|
|||
sender: mtp_transport::Sender,
|
||||
receiver: mtp_transport::Receiver,
|
||||
version: Version,
|
||||
codec: VersionedCodec,
|
||||
#[cfg(feature = "crypto")] auth_state: AuthState,
|
||||
#[cfg(feature = "crypto")] client_id: u64,
|
||||
) -> MTPConnection {
|
||||
#[cfg(feature = "pipes")]
|
||||
let type_map = codec.type_map().clone();
|
||||
receiver.set_type_map(codec.type_map()).await;
|
||||
let remote_addr = sender.handle().remote_addr();
|
||||
let ping = start_ping_session(&config, sender.clone(), &receiver).await;
|
||||
#[cfg(feature = "crypto")]
|
||||
let ping_client_id = client_id;
|
||||
#[cfg(not(feature = "crypto"))]
|
||||
let ping_client_id = config.client_id;
|
||||
let ping = start_ping_session(
|
||||
&config,
|
||||
sender.clone(),
|
||||
&receiver,
|
||||
codec.type_map(),
|
||||
ping_client_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
#[cfg(feature = "pipes")]
|
||||
{
|
||||
|
|
@ -180,6 +215,9 @@ pub(crate) async fn connection_from_parts(
|
|||
|
||||
let dispatcher = Arc::new(PipeDispatcher {
|
||||
pending_requests: Mutex::new(std::collections::HashMap::new()),
|
||||
expired_requests: Mutex::new(std::collections::HashMap::new()),
|
||||
#[cfg(feature = "pipes")]
|
||||
type_map: type_map.clone(),
|
||||
pending_creations: Mutex::new(std::collections::HashMap::new()),
|
||||
pending_pipes: Mutex::new(std::collections::HashMap::new()),
|
||||
policy: Arc::new(config.policy),
|
||||
|
|
@ -197,6 +235,7 @@ pub(crate) async fn connection_from_parts(
|
|||
|
||||
MTPConnection {
|
||||
version,
|
||||
codec,
|
||||
sender,
|
||||
receiver,
|
||||
app_rx: Mutex::new(app_rx),
|
||||
|
|
@ -221,11 +260,15 @@ pub(crate) async fn connection_from_parts(
|
|||
);
|
||||
let dispatcher = Arc::new(PipeDispatcher {
|
||||
pending_requests: Mutex::new(std::collections::HashMap::new()),
|
||||
expired_requests: Mutex::new(std::collections::HashMap::new()),
|
||||
#[cfg(feature = "pipes")]
|
||||
type_map,
|
||||
});
|
||||
let task = tokio::spawn(run_dispatcher(receiver.clone(), app_tx, dispatcher.clone()));
|
||||
|
||||
MTPConnection {
|
||||
version,
|
||||
codec,
|
||||
sender,
|
||||
receiver,
|
||||
app_rx: Mutex::new(app_rx),
|
||||
|
|
|
|||
Loading…
Reference in a new issue