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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions