summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/flags.rs22
-rw-r--r--src/isolate.rs5
-rw-r--r--src/main.rs1
-rw-r--r--src/ops.rs60
-rw-r--r--src/permissions.rs17
5 files changed, 93 insertions, 12 deletions
diff --git a/src/flags.rs b/src/flags.rs
index d68bb5e09..a680c8aa1 100644
--- a/src/flags.rs
+++ b/src/flags.rs
@@ -23,6 +23,7 @@ pub struct DenoFlags {
pub version: bool,
pub reload: bool,
pub recompile: bool,
+ pub allow_read: bool,
pub allow_write: bool,
pub allow_net: bool,
pub allow_env: bool,
@@ -89,6 +90,9 @@ fn set_recognized_flags(
if matches.opt_present("recompile") {
flags.recompile = true;
}
+ if matches.opt_present("allow-read") {
+ flags.allow_read = true;
+ }
if matches.opt_present("allow-write") {
flags.allow_write = true;
}
@@ -102,9 +106,11 @@ fn set_recognized_flags(
flags.allow_run = true;
}
if matches.opt_present("allow-all") {
+ flags.allow_read = true;
flags.allow_env = true;
flags.allow_net = true;
flags.allow_run = true;
+ flags.allow_read = true;
flags.allow_write = true;
}
if matches.opt_present("types") {
@@ -142,6 +148,7 @@ pub fn set_flags(
// TODO(kevinkassimo): v8_set_flags intercepts '-help' with single '-'
// Resolve that and then uncomment line below (enabling Go style -long-flag)
// opts.long_only(true);
+ opts.optflag("", "allow-read", "Allow file system read access.");
opts.optflag("", "allow-write", "Allow file system write access.");
opts.optflag("", "allow-net", "Allow network access.");
opts.optflag("", "allow-env", "Allow environment access.");
@@ -262,12 +269,27 @@ fn test_set_flags_7() {
allow_net: true,
allow_env: true,
allow_run: true,
+ allow_read: true,
allow_write: true,
..DenoFlags::default()
}
)
}
+#[test]
+fn test_set_flags_8() {
+ let (flags, rest, _) =
+ set_flags(svec!["deno", "gist.ts", "--allow-read"]).unwrap();
+ assert_eq!(rest, svec!["deno", "gist.ts"]);
+ assert_eq!(
+ flags,
+ DenoFlags {
+ allow_read: true,
+ ..DenoFlags::default()
+ }
+ )
+}
+
// Returns args passed to V8, followed by args passed to JS
fn v8_set_flags_preprocess(args: Vec<String>) -> (Vec<String>, Vec<String>) {
let (rest, mut v8_args) =
diff --git a/src/isolate.rs b/src/isolate.rs
index 3c9cec797..fbe65a54e 100644
--- a/src/isolate.rs
+++ b/src/isolate.rs
@@ -114,6 +114,11 @@ impl IsolateState {
}
#[inline]
+ pub fn check_read(&self, filename: &str) -> DenoResult<()> {
+ self.permissions.check_read(filename)
+ }
+
+ #[inline]
pub fn check_write(&self, filename: &str) -> DenoResult<()> {
self.permissions.check_write(filename)
}
diff --git a/src/main.rs b/src/main.rs
index 3daea0d31..25e68e344 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -86,6 +86,7 @@ fn main() {
if flags.fmt {
rest_argv.insert(1, "https://deno.land/x/std/prettier/main.ts".to_string());
+ flags.allow_read = true;
flags.allow_write = true;
}
diff --git a/src/ops.rs b/src/ops.rs
index 82d79fc2f..86bc6efad 100644
--- a/src/ops.rs
+++ b/src/ops.rs
@@ -685,10 +685,24 @@ fn op_open(
}
}
- if mode != "r" {
- // Write permission is needed except "r" mode
- if let Err(e) = state.check_write(&filename_str) {
- return odd_future(e);
+ match mode {
+ "r" => {
+ if let Err(e) = state.check_read(&filename_str) {
+ return odd_future(e);
+ }
+ }
+ "w" | "a" | "x" => {
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
+ }
+ &_ => {
+ if let Err(e) = state.check_read(&filename_str) {
+ return odd_future(e);
+ }
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
}
}
@@ -862,15 +876,19 @@ fn op_remove(
// Prototype https://github.com/denoland/deno/blob/golang/os.go#L171-L184
fn op_read_file(
- _state: &Arc<IsolateState>,
+ state: &Arc<IsolateState>,
base: &msg::Base<'_>,
data: libdeno::deno_buf,
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_read_file().unwrap();
let cmd_id = base.cmd_id();
- let filename = PathBuf::from(inner.filename().unwrap());
+ let filename_ = inner.filename().unwrap();
+ let filename = PathBuf::from(filename_);
debug!("op_read_file {}", filename.display());
+ if let Err(e) = state.check_read(&filename_) {
+ return odd_future(e);
+ }
blocking(base.sync(), move || {
let vec = fs::read(&filename)?;
// Build the response message. memcpy data into inner.
@@ -902,10 +920,14 @@ fn op_copy_file(
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_copy_file().unwrap();
- let from = PathBuf::from(inner.from().unwrap());
+ let from_ = inner.from().unwrap();
+ let from = PathBuf::from(from_);
let to_ = inner.to().unwrap();
let to = PathBuf::from(to_);
+ if let Err(e) = state.check_read(&from_) {
+ return odd_future(e);
+ }
if let Err(e) = state.check_write(&to_) {
return odd_future(e);
}
@@ -974,16 +996,21 @@ fn op_cwd(
}
fn op_stat(
- _state: &Arc<IsolateState>,
+ state: &Arc<IsolateState>,
base: &msg::Base<'_>,
data: libdeno::deno_buf,
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_stat().unwrap();
let cmd_id = base.cmd_id();
- let filename = PathBuf::from(inner.filename().unwrap());
+ let filename_ = inner.filename().unwrap();
+ let filename = PathBuf::from(filename_);
let lstat = inner.lstat();
+ if let Err(e) = state.check_read(&filename_) {
+ return odd_future(e);
+ }
+
blocking(base.sync(), move || {
let builder = &mut FlatBufferBuilder::new();
debug!("op_stat {} {}", filename.display(), lstat);
@@ -1021,7 +1048,7 @@ fn op_stat(
}
fn op_read_dir(
- _state: &Arc<IsolateState>,
+ state: &Arc<IsolateState>,
base: &msg::Base<'_>,
data: libdeno::deno_buf,
) -> Box<Op> {
@@ -1030,6 +1057,10 @@ fn op_read_dir(
let cmd_id = base.cmd_id();
let path = String::from(inner.path().unwrap());
+ if let Err(e) = state.check_read(&path) {
+ return odd_future(e);
+ }
+
blocking(base.sync(), move || -> OpResult {
debug!("op_read_dir {}", path);
let builder = &mut FlatBufferBuilder::new();
@@ -1157,14 +1188,19 @@ fn op_symlink(
}
fn op_read_link(
- _state: &Arc<IsolateState>,
+ state: &Arc<IsolateState>,
base: &msg::Base<'_>,
data: libdeno::deno_buf,
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_readlink().unwrap();
let cmd_id = base.cmd_id();
- let name = PathBuf::from(inner.name().unwrap());
+ let name_ = inner.name().unwrap();
+ let name = PathBuf::from(name_);
+
+ if let Err(e) = state.check_read(&name_) {
+ return odd_future(e);
+ }
blocking(base.sync(), move || -> OpResult {
debug!("op_read_link {}", name.display());
diff --git a/src/permissions.rs b/src/permissions.rs
index c05ea4ee5..8546e4ee9 100644
--- a/src/permissions.rs
+++ b/src/permissions.rs
@@ -12,6 +12,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
#[derive(Debug, Default)]
pub struct DenoPermissions {
+ pub allow_read: AtomicBool,
pub allow_write: AtomicBool,
pub allow_net: AtomicBool,
pub allow_env: AtomicBool,
@@ -21,6 +22,7 @@ pub struct DenoPermissions {
impl DenoPermissions {
pub fn new(flags: &DenoFlags) -> Self {
Self {
+ allow_read: AtomicBool::new(flags.allow_read),
allow_write: AtomicBool::new(flags.allow_write),
allow_env: AtomicBool::new(flags.allow_env),
allow_net: AtomicBool::new(flags.allow_net),
@@ -40,6 +42,21 @@ impl DenoPermissions {
r
}
+ pub fn check_read(&self, filename: &str) -> DenoResult<()> {
+ if self.allow_read.load(Ordering::SeqCst) {
+ return Ok(());
+ };
+ // TODO get location (where access occurred)
+ let r = permission_prompt(&format!(
+ "Deno requests read access to \"{}\".",
+ filename
+ ));;
+ if r.is_ok() {
+ self.allow_read.store(true, Ordering::SeqCst);
+ }
+ r
+ }
+
pub fn check_write(&self, filename: &str) -> DenoResult<()> {
if self.allow_write.load(Ordering::SeqCst) {
return Ok(());