Skip to content

Object capabilities for capsec-std and capsec-tokio? #62

@JonasCir

Description

@JonasCir

Hi,
thank you for creating this interesting project!

My question is if object capabilities for file/network access etc. will be eventually supported by this crate? Currently, methods in capsec-std and capsec-tokio are all guarded by a certain CapProvider. The actual arguments, however, like for example paths in capsec-std::fs are all of the form impl AsRef<Path>and can be freely chosen/are not subject to access control as provide_cap seems to discard _target in the macro and always return Ok(Cap::new()).

Being able to reason about program IO is already a great improvement, I just feel that this could also be extended to the actual (file, network, etc.) objects in the Rust program code.

So instead of having

let root = capsec::root();
let cap = root.grant::<FsRead>();
let data = capsec_std::fs::read(from_some_potentially_untrusted_input, &cap).unwrap();

I think it would be beneficial to introduce something like

struct FileObjectCap<O: AsRef<Path>, P: Permission>{
   file_object: Box<O>, // <- or anything appropriate to hold the object
   permission: Cap<P> // <- can still be zero size
}

impl <O: AsRef<Path>> CapProvider<FsRead> for FileObjectCap<O,FsRead> {
    fn provide_cap(&self) -> Result<Cap<FsRead>, CapSecError> {
        Ok(Cap::new())
    }
}

pub fn read <O: AsRef<Path>>(fs_cap: &FileObjectCap<O,FsRead>) -> Result<Vec<u8>, CapSecError> {
    let _proof: Cap<FsRead> = cap.provide_cap()?;
    Ok(std::fs::read(fs_cap.file_object())?)
}

fn main() {
    let root = capsec::root();

    let mut fs_namespace = Vec::new();

    // not just general FsRead IO of the program is subject to access control,
    // but the actual file objects in the program code as well
    let cap = root.grant::<FsRead>("/tmp/example.txt");
    fs_namespace.push(cap);

   // get untrusted path which should be subject to access control
   let untrusted_path = ...;

   // just for demonstration purposes, Namespace should be a dedicated
   // container type listing all the capabilities available to the program code
   let found_cap = fs_namsepace.iter().filter(|c| c.fs_object() == untrusted_path).one().unwrap();

   let data = capsec_std::fs::read(&found_cap).unwrap();
}

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions