-
Notifications
You must be signed in to change notification settings - Fork 2
Object capabilities for capsec-std and capsec-tokio? #62
Description
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?