From 93604000c76ee6b661051746451ce3f996e21a19 Mon Sep 17 00:00:00 2001 From: sh7dm Date: Sat, 26 Jan 2019 17:33:57 +0300 Subject: [PATCH 01/10] Add --deny flag support --- src/flags.rs | 5 +++++ src/permissions.rs | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/flags.rs b/src/flags.rs index 970aceb3c55164..48aa963ef3442b 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -27,6 +27,7 @@ pub struct DenoFlags { pub allow_net: bool, pub allow_env: bool, pub allow_run: bool, + pub deny: bool, pub types: bool, pub prefetch: bool, } @@ -105,6 +106,9 @@ fn set_recognized_flags( flags.allow_run = true; flags.allow_write = true; } + if matches.opt_present("deny") { + flags.deny = true; + } if matches.opt_present("types") { flags.types = true; } @@ -139,6 +143,7 @@ pub fn set_flags( opts.optflag("", "allow-env", "Allow environment access."); opts.optflag("", "allow-run", "Allow running subprocesses."); opts.optflag("A", "allow-all", "Allow all permissions"); + opts.optflag("", "deny", "Deny all permission requests"); opts.optflag("", "recompile", "Force recompilation of TypeScript code."); opts.optflag("h", "help", "Print this message."); opts.optflag("D", "log-debug", "Log debug output."); diff --git a/src/permissions.rs b/src/permissions.rs index fc14bea769d157..289df413061d28 100644 --- a/src/permissions.rs +++ b/src/permissions.rs @@ -15,6 +15,7 @@ pub struct DenoPermissions { pub allow_net: AtomicBool, pub allow_env: AtomicBool, pub allow_run: AtomicBool, + deny: bool } impl DenoPermissions { @@ -24,6 +25,7 @@ impl DenoPermissions { allow_env: AtomicBool::new(flags.allow_env), allow_net: AtomicBool::new(flags.allow_net), allow_run: AtomicBool::new(flags.allow_run), + deny: flags.deny } } @@ -31,6 +33,9 @@ impl DenoPermissions { if self.allow_run.load(Ordering::SeqCst) { return Ok(()); }; + if self.deny { + return Err(permission_denied()); + }; // TODO get location (where access occurred) let r = permission_prompt("Deno requests access to run a subprocess."); if r.is_ok() { @@ -43,6 +48,9 @@ impl DenoPermissions { if self.allow_write.load(Ordering::SeqCst) { return Ok(()); }; + if self.deny { + return Err(permission_denied()); + }; // TODO get location (where access occurred) let r = permission_prompt(&format!( "Deno requests write access to \"{}\".", @@ -58,6 +66,9 @@ impl DenoPermissions { if self.allow_net.load(Ordering::SeqCst) { return Ok(()); }; + if self.deny { + return Err(permission_denied()); + }; // TODO get location (where access occurred) let r = permission_prompt(&format!( "Deno requests network access to \"{}\".", @@ -73,6 +84,9 @@ impl DenoPermissions { if self.allow_env.load(Ordering::SeqCst) { return Ok(()); }; + if self.deny { + return Err(permission_denied()); + }; // TODO get location (where access occurred) let r = permission_prompt(&"Deno requests access to environment variables."); From 2e99561a5ec32d9c8ddcbe34de456e08cb8cb037 Mon Sep 17 00:00:00 2001 From: sh7dm Date: Sat, 26 Jan 2019 18:01:12 +0300 Subject: [PATCH 02/10] --deny should disable all permissions --- src/permissions.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/permissions.rs b/src/permissions.rs index 289df413061d28..85d8c01b4d2a89 100644 --- a/src/permissions.rs +++ b/src/permissions.rs @@ -30,12 +30,12 @@ impl DenoPermissions { } pub fn check_run(&self) -> DenoResult<()> { - if self.allow_run.load(Ordering::SeqCst) { - return Ok(()); - }; if self.deny { return Err(permission_denied()); }; + if self.allow_run.load(Ordering::SeqCst) { + return Ok(()); + }; // TODO get location (where access occurred) let r = permission_prompt("Deno requests access to run a subprocess."); if r.is_ok() { @@ -45,12 +45,12 @@ impl DenoPermissions { } pub fn check_write(&self, filename: &str) -> DenoResult<()> { - if self.allow_write.load(Ordering::SeqCst) { - return Ok(()); - }; if self.deny { return Err(permission_denied()); }; + if self.allow_write.load(Ordering::SeqCst) { + return Ok(()); + }; // TODO get location (where access occurred) let r = permission_prompt(&format!( "Deno requests write access to \"{}\".", @@ -63,12 +63,12 @@ impl DenoPermissions { } pub fn check_net(&self, domain_name: &str) -> DenoResult<()> { - if self.allow_net.load(Ordering::SeqCst) { - return Ok(()); - }; if self.deny { return Err(permission_denied()); }; + if self.allow_net.load(Ordering::SeqCst) { + return Ok(()); + }; // TODO get location (where access occurred) let r = permission_prompt(&format!( "Deno requests network access to \"{}\".", @@ -81,12 +81,12 @@ impl DenoPermissions { } pub fn check_env(&self) -> DenoResult<()> { - if self.allow_env.load(Ordering::SeqCst) { - return Ok(()); - }; if self.deny { return Err(permission_denied()); }; + if self.allow_env.load(Ordering::SeqCst) { + return Ok(()); + }; // TODO get location (where access occurred) let r = permission_prompt(&"Deno requests access to environment variables."); From 56fc7d674b58a747d396b2f29dca4fd5c7bcefa9 Mon Sep 17 00:00:00 2001 From: sh7dm Date: Sat, 26 Jan 2019 18:28:57 +0300 Subject: [PATCH 03/10] Revert 2e99561 --- src/permissions.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/permissions.rs b/src/permissions.rs index 85d8c01b4d2a89..289df413061d28 100644 --- a/src/permissions.rs +++ b/src/permissions.rs @@ -30,12 +30,12 @@ impl DenoPermissions { } pub fn check_run(&self) -> DenoResult<()> { - if self.deny { - return Err(permission_denied()); - }; if self.allow_run.load(Ordering::SeqCst) { return Ok(()); }; + if self.deny { + return Err(permission_denied()); + }; // TODO get location (where access occurred) let r = permission_prompt("Deno requests access to run a subprocess."); if r.is_ok() { @@ -45,12 +45,12 @@ impl DenoPermissions { } pub fn check_write(&self, filename: &str) -> DenoResult<()> { - if self.deny { - return Err(permission_denied()); - }; if self.allow_write.load(Ordering::SeqCst) { return Ok(()); }; + if self.deny { + return Err(permission_denied()); + }; // TODO get location (where access occurred) let r = permission_prompt(&format!( "Deno requests write access to \"{}\".", @@ -63,12 +63,12 @@ impl DenoPermissions { } pub fn check_net(&self, domain_name: &str) -> DenoResult<()> { - if self.deny { - return Err(permission_denied()); - }; if self.allow_net.load(Ordering::SeqCst) { return Ok(()); }; + if self.deny { + return Err(permission_denied()); + }; // TODO get location (where access occurred) let r = permission_prompt(&format!( "Deno requests network access to \"{}\".", @@ -81,12 +81,12 @@ impl DenoPermissions { } pub fn check_env(&self) -> DenoResult<()> { - if self.deny { - return Err(permission_denied()); - }; if self.allow_env.load(Ordering::SeqCst) { return Ok(()); }; + if self.deny { + return Err(permission_denied()); + }; // TODO get location (where access occurred) let r = permission_prompt(&"Deno requests access to environment variables."); From ba27ae0beb8f92b2ef12c6b16059d1a1ca0cc9ae Mon Sep 17 00:00:00 2001 From: sh7dm Date: Sat, 26 Jan 2019 21:40:50 +0300 Subject: [PATCH 04/10] Add test for --deny option --- tests/021_deny.test | 4 ++++ tests/021_deny.ts | 10 ++++++++++ tests/021_deny.ts.out | 6 ++++++ 3 files changed, 20 insertions(+) create mode 100644 tests/021_deny.test create mode 100644 tests/021_deny.ts create mode 100644 tests/021_deny.ts.out diff --git a/tests/021_deny.test b/tests/021_deny.test new file mode 100644 index 00000000000000..49e39ff560fcd1 --- /dev/null +++ b/tests/021_deny.test @@ -0,0 +1,4 @@ +args: tests/021_deny.ts --deny +check_stderr: true +exit_code: 1 +output: tests/021_deny.ts.out diff --git a/tests/021_deny.ts b/tests/021_deny.ts new file mode 100644 index 00000000000000..20693dd1ecddbf --- /dev/null +++ b/tests/021_deny.ts @@ -0,0 +1,10 @@ +import { serve } from "https://deno.land/x/http/mod.ts"; +const s = serve("0.0.0.0:8000"); + +async function main() { + for await (const req of s) { + req.respond({ body: new TextEncoder().encode("Hello World\n") }); + } +} + +main(); \ No newline at end of file diff --git a/tests/021_deny.ts.out b/tests/021_deny.ts.out new file mode 100644 index 00000000000000..16ae3591d6f950 --- /dev/null +++ b/tests/021_deny.ts.out @@ -0,0 +1,6 @@ +[WILDCARD]PermissionDenied: permission denied + at DenoError (deno/js/errors.ts:19:5) + at maybeError (deno/js/errors.ts:38:12) + at maybeThrowError (deno/js/errors.ts:26:15) + at sendSync (deno/js/dispatch.ts:67:5) + at listen (deno/js/net.ts:147:19)[WILDCARD] From fb667d369442cb229b4a94e3c47af9575821f6b4 Mon Sep 17 00:00:00 2001 From: sh7dm Date: Sun, 27 Jan 2019 08:41:28 +0300 Subject: [PATCH 05/10] Move permission_prompt to DenoPermissions; Move deny to permission_prompt --- src/permissions.rs | 56 ++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/src/permissions.rs b/src/permissions.rs index 289df413061d28..b49ccd0b65c187 100644 --- a/src/permissions.rs +++ b/src/permissions.rs @@ -29,15 +29,30 @@ impl DenoPermissions { } } + fn permission_prompt(&self, message: &str) -> DenoResult<()> { + if !atty::is(atty::Stream::Stdin) || !atty::is(atty::Stream::Stderr) || self.deny { + return Err(permission_denied()); + }; + // print to stderr so that if deno is > to a file this is still displayed. + eprint!("{} Grant? [yN] ", message); + let mut input = String::new(); + let stdin = io::stdin(); + let _nread = stdin.read_line(&mut input)?; + let ch = input.chars().next().unwrap(); + let is_yes = ch == 'y' || ch == 'Y'; + if is_yes { + Ok(()) + } else { + Err(permission_denied()) + } + } + pub fn check_run(&self) -> DenoResult<()> { if self.allow_run.load(Ordering::SeqCst) { return Ok(()); }; - if self.deny { - return Err(permission_denied()); - }; // TODO get location (where access occurred) - let r = permission_prompt("Deno requests access to run a subprocess."); + let r = self.permission_prompt("Deno requests access to run a subprocess."); if r.is_ok() { self.allow_run.store(true, Ordering::SeqCst); } @@ -48,11 +63,8 @@ impl DenoPermissions { if self.allow_write.load(Ordering::SeqCst) { return Ok(()); }; - if self.deny { - return Err(permission_denied()); - }; // TODO get location (where access occurred) - let r = permission_prompt(&format!( + let r = self.permission_prompt(&format!( "Deno requests write access to \"{}\".", filename ));; @@ -66,11 +78,8 @@ impl DenoPermissions { if self.allow_net.load(Ordering::SeqCst) { return Ok(()); }; - if self.deny { - return Err(permission_denied()); - }; // TODO get location (where access occurred) - let r = permission_prompt(&format!( + let r = self.permission_prompt(&format!( "Deno requests network access to \"{}\".", domain_name )); @@ -84,33 +93,12 @@ impl DenoPermissions { if self.allow_env.load(Ordering::SeqCst) { return Ok(()); }; - if self.deny { - return Err(permission_denied()); - }; // TODO get location (where access occurred) let r = - permission_prompt(&"Deno requests access to environment variables."); + self.permission_prompt(&"Deno requests access to environment variables."); if r.is_ok() { self.allow_env.store(true, Ordering::SeqCst); } r } } - -fn permission_prompt(message: &str) -> DenoResult<()> { - if !atty::is(atty::Stream::Stdin) || !atty::is(atty::Stream::Stderr) { - return Err(permission_denied()); - }; - // print to stderr so that if deno is > to a file this is still displayed. - eprint!("{} Grant? [yN] ", message); - let mut input = String::new(); - let stdin = io::stdin(); - let _nread = stdin.read_line(&mut input)?; - let ch = input.chars().next().unwrap(); - let is_yes = ch == 'y' || ch == 'Y'; - if is_yes { - Ok(()) - } else { - Err(permission_denied()) - } -} From 9de7d504aff44b97bd68f39182949476f094e6cf Mon Sep 17 00:00:00 2001 From: sh7dm Date: Sun, 27 Jan 2019 08:48:12 +0300 Subject: [PATCH 06/10] Move deny tests to permission_prompt_test.py --- tests/021_deny.test | 4 ---- tests/021_deny.ts | 10 ---------- tests/021_deny.ts.out | 6 ------ tools/permission_prompt_test.py | 15 ++++++++++++++- 4 files changed, 14 insertions(+), 21 deletions(-) delete mode 100644 tests/021_deny.test delete mode 100644 tests/021_deny.ts delete mode 100644 tests/021_deny.ts.out diff --git a/tests/021_deny.test b/tests/021_deny.test deleted file mode 100644 index 49e39ff560fcd1..00000000000000 --- a/tests/021_deny.test +++ /dev/null @@ -1,4 +0,0 @@ -args: tests/021_deny.ts --deny -check_stderr: true -exit_code: 1 -output: tests/021_deny.ts.out diff --git a/tests/021_deny.ts b/tests/021_deny.ts deleted file mode 100644 index 20693dd1ecddbf..00000000000000 --- a/tests/021_deny.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { serve } from "https://deno.land/x/http/mod.ts"; -const s = serve("0.0.0.0:8000"); - -async function main() { - for await (const req of s) { - req.respond({ body: new TextEncoder().encode("Hello World\n") }); - } -} - -main(); \ No newline at end of file diff --git a/tests/021_deny.ts.out b/tests/021_deny.ts.out deleted file mode 100644 index 16ae3591d6f950..00000000000000 --- a/tests/021_deny.ts.out +++ /dev/null @@ -1,6 +0,0 @@ -[WILDCARD]PermissionDenied: permission denied - at DenoError (deno/js/errors.ts:19:5) - at maybeError (deno/js/errors.ts:38:12) - at maybeThrowError (deno/js/errors.ts:26:15) - at sendSync (deno/js/dispatch.ts:67:5) - at listen (deno/js/net.ts:147:19)[WILDCARD] diff --git a/tools/permission_prompt_test.py b/tools/permission_prompt_test.py index 5eae5beda7d0f0..1088c1efc2f214 100755 --- a/tools/permission_prompt_test.py +++ b/tools/permission_prompt_test.py @@ -53,7 +53,8 @@ def run(self, allow_write=False, allow_net=False, allow_env=False, - allow_run=False): + allow_run=False, + deny=False): "Returns (return_code, stdout, stderr)." cmd = [self.deno_exe, PERMISSIONS_PROMPT_TEST_TS, arg] if allow_write: @@ -142,6 +143,18 @@ def test_run_no(self): assert b'PermissionDenied: permission denied' in stderr assert b'Deno requests access to run' in stderr + def test_deny_run(self): + code, _stdout, stderr = self.run('needsRun', b'', deny=True) + assert code == 1 + assert b'PermissionDenied: permission denied' in stderr + assert b'Deno requests access to run' in stderr + + def test_deny_net(self): + code, _stdout, stderr = self.run('needsNet', b'', deny=True) + assert code == 1 + assert b'PermissionDenied: permission denied' in stderr + assert b'Deno requests network access' in stderr + def permission_prompt_test(deno_exe): p = Prompt(deno_exe) From b33572929ac92248b957f32fc90e88715112f631 Mon Sep 17 00:00:00 2001 From: sh7dm Date: Fri, 1 Feb 2019 18:55:48 +0300 Subject: [PATCH 07/10] Fix deny test --- tools/permission_prompt_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/permission_prompt_test.py b/tools/permission_prompt_test.py index 1088c1efc2f214..b85ba911a4a10a 100755 --- a/tools/permission_prompt_test.py +++ b/tools/permission_prompt_test.py @@ -57,6 +57,8 @@ def run(self, deny=False): "Returns (return_code, stdout, stderr)." cmd = [self.deno_exe, PERMISSIONS_PROMPT_TEST_TS, arg] + if deny: + cmd.append("--deny") if allow_write: cmd.append("--allow-write") if allow_net: @@ -147,13 +149,11 @@ def test_deny_run(self): code, _stdout, stderr = self.run('needsRun', b'', deny=True) assert code == 1 assert b'PermissionDenied: permission denied' in stderr - assert b'Deno requests access to run' in stderr def test_deny_net(self): code, _stdout, stderr = self.run('needsNet', b'', deny=True) assert code == 1 assert b'PermissionDenied: permission denied' in stderr - assert b'Deno requests network access' in stderr def permission_prompt_test(deno_exe): @@ -171,6 +171,8 @@ def permission_prompt_test(deno_exe): p.test_run_yes() p.test_run_arg() p.test_run_no() + p.test_deny_run() + p.test_deny_net() def main(): From daea1c6f7b9757b7cf5a2613d42bc507e8f96093 Mon Sep 17 00:00:00 2001 From: sh7dm Date: Fri, 1 Feb 2019 18:56:12 +0300 Subject: [PATCH 08/10] Format code --- src/permissions.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/permissions.rs b/src/permissions.rs index b49ccd0b65c187..de8817dad6f80f 100644 --- a/src/permissions.rs +++ b/src/permissions.rs @@ -15,7 +15,7 @@ pub struct DenoPermissions { pub allow_net: AtomicBool, pub allow_env: AtomicBool, pub allow_run: AtomicBool, - deny: bool + deny: bool, } impl DenoPermissions { @@ -25,12 +25,15 @@ impl DenoPermissions { allow_env: AtomicBool::new(flags.allow_env), allow_net: AtomicBool::new(flags.allow_net), allow_run: AtomicBool::new(flags.allow_run), - deny: flags.deny + deny: flags.deny, } } fn permission_prompt(&self, message: &str) -> DenoResult<()> { - if !atty::is(atty::Stream::Stdin) || !atty::is(atty::Stream::Stderr) || self.deny { + if !atty::is(atty::Stream::Stdin) + || !atty::is(atty::Stream::Stderr) + || self.deny + { return Err(permission_denied()); }; // print to stderr so that if deno is > to a file this is still displayed. From 36211d9b13dd88514f3db7674265a02872266489 Mon Sep 17 00:00:00 2001 From: sh7dm Date: Fri, 1 Feb 2019 21:50:10 +0300 Subject: [PATCH 09/10] Make deny permission public --- src/permissions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/permissions.rs b/src/permissions.rs index de8817dad6f80f..4b8281d47879cb 100644 --- a/src/permissions.rs +++ b/src/permissions.rs @@ -15,7 +15,7 @@ pub struct DenoPermissions { pub allow_net: AtomicBool, pub allow_env: AtomicBool, pub allow_run: AtomicBool, - deny: bool, + pub deny: bool, } impl DenoPermissions { From bc71665cd3a3a5f703a7ee1b49e77c464171d71f Mon Sep 17 00:00:00 2001 From: sh7dm Date: Fri, 1 Feb 2019 22:08:33 +0300 Subject: [PATCH 10/10] Add tests for --deny with --allow-x --- tools/permission_prompt_test.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/permission_prompt_test.py b/tools/permission_prompt_test.py index b85ba911a4a10a..6b84a763f5818a 100755 --- a/tools/permission_prompt_test.py +++ b/tools/permission_prompt_test.py @@ -155,6 +155,24 @@ def test_deny_net(self): assert code == 1 assert b'PermissionDenied: permission denied' in stderr + def test_deny_but_allow_run(self): + code, stdout, stderr = self.run('needsRun', + b'', + allow_run=True, + deny=True) + assert code == 0 + assert stdout == b'hello' + assert stderr == b'' + + def test_deny_but_allow_net(self): + code, stdout, stderr = self.run('needsNet', + b'', + allow_net=True, + deny=True) + assert code == 0 + assert stdout == b'' + assert stderr == b'' + def permission_prompt_test(deno_exe): p = Prompt(deno_exe) @@ -173,6 +191,8 @@ def permission_prompt_test(deno_exe): p.test_run_no() p.test_deny_run() p.test_deny_net() + p.test_deny_but_allow_run() + p.test_deny_but_allow_net() def main():