Skip to content

Commit

Permalink
Ergonomics: Prompt TTY for permission escalation
Browse files Browse the repository at this point in the history
  • Loading branch information
hayd authored and ry committed Oct 26, 2018
1 parent 9b8f77f commit 55fb52c
Show file tree
Hide file tree
Showing 12 changed files with 353 additions and 58 deletions.
15 changes: 8 additions & 7 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,25 @@ config("deno_config") {
}

main_extern = [
"$rust_build:atty",
"$rust_build:dirs",
"$rust_build:futures",
"$rust_build:getopts",
"$rust_build:hyper",
"$rust_build:hyper_rustls",
"$rust_build:futures",
"$rust_build:lazy_static",
"$rust_build:libc",
"$rust_build:log",
"$rust_build:rand",
"$rust_build:remove_dir_all",
"$rust_build:ring",
"$rust_build:tempfile",
"$rust_build:rand",
"$rust_build:tokio",
"$rust_build:tokio_io",
"$rust_build:tokio_fs",
"$rust_build:tokio_executor",
"$rust_build:tokio_fs",
"$rust_build:tokio_io",
"$rust_build:tokio_threadpool",
"$rust_build:url",
"$rust_build:remove_dir_all",
"$rust_build:dirs",
"$rust_build:getopts",
"//build_extra/flatbuffers/rust:flatbuffers",
":msg_rs",
]
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ name = "deno"
version = "0.0.0"

[dependencies]
atty = "0.2.11"
dirs = "1.0.4"
flatbuffers = { path = "third_party/flatbuffers/rust/flatbuffers/" }
futures = "0.1.25"
Expand Down
14 changes: 13 additions & 1 deletion build_extra/rust/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,15 @@ rust_crate("winapi") {
"basetsd",
"cfg",
"cfgmgr32",
"consoleapi",
"combaseapi",
"errhandlingapi",
"excpt",
"fileapi",
"guiddef",
"handleapi",
"inaddr",
"in6addr",
"inaddr",
"knownfolders",
"ktmtypes",
"libloaderapi",
Expand All @@ -134,6 +135,7 @@ rust_crate("winapi") {
"objbase",
"objidl",
"objidlbase",
"processenv",
"processthreadsapi",
"profileapi",
"propidl",
Expand All @@ -152,8 +154,10 @@ rust_crate("winapi") {
"vadefs",
"vcruntime",
"winbase",
"wincon",
"wincred",
"windef",
"wingdi",
"winerror",
"winnt",
"winreg",
Expand Down Expand Up @@ -865,6 +869,14 @@ rust_crate("sct") {
]
}

rust_crate("atty") {
source_root = "$registry_github/atty-0.2.11/src/lib.rs"
extern = [
":libc",
":winapi",
]
}

rust_crate("base64") {
source_root = "$registry_github/base64-0.9.2/src/lib.rs"
extern = [
Expand Down
19 changes: 19 additions & 0 deletions src/isolate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

use deno_dir;
use errors::DenoError;
use errors::DenoResult;
use flags;
use libdeno;
use permissions::DenoPermissions;
use snapshot;

use futures::Future;
Expand Down Expand Up @@ -56,6 +58,7 @@ pub struct Isolate {
pub struct IsolateState {
pub dir: deno_dir::DenoDir,
pub argv: Vec<String>,
pub permissions: Mutex<DenoPermissions>,
pub flags: flags::DenoFlags,
tx: Mutex<Option<mpsc::Sender<(i32, Buf)>>>,
pub metrics: Mutex<Metrics>,
Expand All @@ -71,6 +74,21 @@ impl IsolateState {
tx.send((req_id, buf)).expect("tx.send error");
}

pub fn check_write(&self, filename: &str) -> DenoResult<()> {
let mut perm = self.permissions.lock().unwrap();
perm.check_write(filename)
}

pub fn check_env(&self) -> DenoResult<()> {
let mut perm = self.permissions.lock().unwrap();
perm.check_env()
}

pub fn check_net(&self, filename: &str) -> DenoResult<()> {
let mut perm = self.permissions.lock().unwrap();
perm.check_net(filename)
}

fn metrics_op_dispatched(
&self,
bytes_sent_control: u64,
Expand Down Expand Up @@ -143,6 +161,7 @@ impl Isolate {
state: Arc::new(IsolateState {
dir: deno_dir::DenoDir::new(flags.reload, custom_root).unwrap(),
argv: argv_rest,
permissions: Mutex::new(DenoPermissions::new(&flags)),
flags,
tx: Mutex::new(Some(tx)),
metrics: Mutex::new(Metrics::default()),
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ mod http_util;
mod isolate;
mod libdeno;
pub mod ops;
mod permissions;
mod resources;
mod snapshot;
mod tokio_util;
Expand Down
96 changes: 49 additions & 47 deletions src/ops.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
use errors;
use errors::permission_denied;
use errors::{DenoError, DenoResult, ErrorKind};
use fs as deno_fs;
use http_util;
Expand Down Expand Up @@ -332,11 +331,9 @@ fn op_set_env(
let inner = base.inner_as_set_env().unwrap();
let key = inner.key().unwrap();
let value = inner.value().unwrap();

if !state.flags.allow_env {
return odd_future(permission_denied());
if let Err(e) = state.check_env() {
return odd_future(e);
}

std::env::set_var(key, value);
ok_future(empty_buf())
}
Expand All @@ -349,8 +346,8 @@ fn op_env(
assert_eq!(data.len(), 0);
let cmd_id = base.cmd_id();

if !state.flags.allow_env {
return odd_future(permission_denied());
if let Err(e) = state.check_env() {
return odd_future(e);
}

let builder = &mut FlatBufferBuilder::new();
Expand Down Expand Up @@ -398,8 +395,9 @@ fn op_fetch_req(
let id = inner.id();
let url = inner.url().unwrap();

if !state.flags.allow_net {
return odd_future(permission_denied());
// FIXME use domain (or use this inside check_net)
if let Err(e) = state.check_net(url) {
return odd_future(e);
}

let url = url.parse::<hyper::Uri>().unwrap();
Expand Down Expand Up @@ -512,8 +510,9 @@ fn op_make_temp_dir(
let inner = base.inner_as_make_temp_dir().unwrap();
let cmd_id = base.cmd_id();

if !state.flags.allow_write {
return odd_future(permission_denied());
// FIXME
if let Err(e) = state.check_write("make_temp") {
return odd_future(e);
}

let dir = inner.dir().map(PathBuf::from);
Expand Down Expand Up @@ -561,10 +560,9 @@ fn op_mkdir(
let mode = inner.mode();
let path = String::from(inner.path().unwrap());

if !state.flags.allow_write {
return odd_future(permission_denied());
if let Err(e) = state.check_write(&path) {
return odd_future(e);
}

blocking!(base.sync(), || {
debug!("op_mkdir {}", path);
deno_fs::mkdir(Path::new(&path), mode)?;
Expand Down Expand Up @@ -735,11 +733,14 @@ fn op_remove(
) -> Box<Op> {
assert_eq!(data.len(), 0);
let inner = base.inner_as_remove().unwrap();
let path = PathBuf::from(inner.path().unwrap());
let path_ = inner.path().unwrap();
let path = PathBuf::from(path_);
let recursive = inner.recursive();
if !state.flags.allow_write {
return odd_future(permission_denied());

if let Err(e) = state.check_write(path.to_str().unwrap()) {
return odd_future(e);
}

blocking!(base.sync(), || {
debug!("op_remove {}", path.display());
let metadata = fs::metadata(&path)?;
Expand Down Expand Up @@ -800,10 +801,11 @@ fn op_copy_file(
assert_eq!(data.len(), 0);
let inner = base.inner_as_copy_file().unwrap();
let from = PathBuf::from(inner.from().unwrap());
let to = PathBuf::from(inner.to().unwrap());
let to_ = inner.to().unwrap();
let to = PathBuf::from(to_);

if !state.flags.allow_write {
return odd_future(permission_denied());
if let Err(e) = state.check_write(&to_) {
return odd_future(e);
}

debug!("op_copy_file {} {}", from.display(), to.display());
Expand Down Expand Up @@ -984,14 +986,13 @@ fn op_write_file(
data: &'static mut [u8],
) -> Box<Op> {
let inner = base.inner_as_write_file().unwrap();

if !state.flags.allow_write {
return odd_future(permission_denied());
}

let filename = String::from(inner.filename().unwrap());
let perm = inner.perm();

if let Err(e) = state.check_write(&filename) {
return odd_future(e);
}

blocking!(base.sync(), || -> OpResult {
debug!("op_write_file {} {}", filename, data.len());
deno_fs::write_file(Path::new(&filename), data, perm)?;
Expand All @@ -1005,12 +1006,13 @@ fn op_rename(
data: &'static mut [u8],
) -> Box<Op> {
assert_eq!(data.len(), 0);
if !state.flags.allow_write {
return odd_future(permission_denied());
}
let inner = base.inner_as_rename().unwrap();
let oldpath = PathBuf::from(inner.oldpath().unwrap());
let newpath = PathBuf::from(inner.newpath().unwrap());
let newpath_ = inner.newpath().unwrap();
let newpath = PathBuf::from(newpath_);
if let Err(e) = state.check_write(&newpath_) {
return odd_future(e);
}
blocking!(base.sync(), || -> OpResult {
debug!("op_rename {} {}", oldpath.display(), newpath.display());
fs::rename(&oldpath, &newpath)?;
Expand All @@ -1024,8 +1026,13 @@ fn op_symlink(
data: &'static mut [u8],
) -> Box<Op> {
assert_eq!(data.len(), 0);
if !state.flags.allow_write {
return odd_future(permission_denied());
let inner = base.inner_as_symlink().unwrap();
let oldname = PathBuf::from(inner.oldname().unwrap());
let newname_ = inner.newname().unwrap();
let newname = PathBuf::from(newname_);

if let Err(e) = state.check_write(&newname_) {
return odd_future(e);
}
// TODO Use type for Windows.
if cfg!(windows) {
Expand All @@ -1034,10 +1041,6 @@ fn op_symlink(
"Not implemented".to_string(),
));
}

let inner = base.inner_as_symlink().unwrap();
let oldname = PathBuf::from(inner.oldname().unwrap());
let newname = PathBuf::from(inner.newname().unwrap());
blocking!(base.sync(), || -> OpResult {
debug!("op_symlink {} {}", oldname.display(), newname.display());
#[cfg(any(unix))]
Expand Down Expand Up @@ -1087,13 +1090,14 @@ fn op_truncate(
) -> Box<Op> {
assert_eq!(data.len(), 0);

if !state.flags.allow_write {
return odd_future(permission_denied());
}

let inner = base.inner_as_truncate().unwrap();
let filename = String::from(inner.name().unwrap());
let len = inner.len();

if let Err(e) = state.check_write(&filename) {
return odd_future(e);
}

blocking!(base.sync(), || {
debug!("op_truncate {} {}", filename, len);
let f = fs::OpenOptions::new().write(true).open(&filename)?;
Expand All @@ -1108,8 +1112,8 @@ fn op_listen(
data: &'static mut [u8],
) -> Box<Op> {
assert_eq!(data.len(), 0);
if !state.flags.allow_net {
return odd_future(permission_denied());
if let Err(e) = state.check_net("listen") {
return odd_future(e);
}

let cmd_id = base.cmd_id();
Expand Down Expand Up @@ -1174,10 +1178,9 @@ fn op_accept(
data: &'static mut [u8],
) -> Box<Op> {
assert_eq!(data.len(), 0);
if !state.flags.allow_net {
return odd_future(permission_denied());
if let Err(e) = state.check_net("accept") {
return odd_future(e);
}

let cmd_id = base.cmd_id();
let inner = base.inner_as_accept().unwrap();
let server_rid = inner.rid();
Expand All @@ -1201,10 +1204,9 @@ fn op_dial(
data: &'static mut [u8],
) -> Box<Op> {
assert_eq!(data.len(), 0);
if !state.flags.allow_net {
return odd_future(permission_denied());
if let Err(e) = state.check_net("dial") {
return odd_future(e);
}

let cmd_id = base.cmd_id();
let inner = base.inner_as_dial().unwrap();
let network = inner.network().unwrap();
Expand Down
Loading

0 comments on commit 55fb52c

Please sign in to comment.