diff options
Diffstat (limited to 'runtime/ops/worker_host.rs')
-rw-r--r-- | runtime/ops/worker_host.rs | 239 |
1 files changed, 165 insertions, 74 deletions
diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index 6b375605f..df624cd44 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -1,9 +1,14 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -use crate::permissions::resolve_fs_allowlist; +use crate::permissions::resolve_read_allowlist; +use crate::permissions::resolve_write_allowlist; +use crate::permissions::BooleanPermission; +use crate::permissions::NetPermission; use crate::permissions::PermissionState; use crate::permissions::Permissions; +use crate::permissions::ReadPermission; use crate::permissions::UnaryPermission; +use crate::permissions::WritePermission; use crate::web_worker::run_web_worker; use crate::web_worker::WebWorker; use crate::web_worker::WebWorkerHandle; @@ -105,49 +110,54 @@ pub fn init( ); } -fn merge_permission_state( - target: &PermissionState, +fn merge_boolean_permission( + target: &BooleanPermission, incoming: Option<PermissionState>, -) -> Result<PermissionState, AnyError> { - match target { +) -> Result<BooleanPermission, AnyError> { + let mut perm = target.clone(); + perm.state = match target.state { PermissionState::Granted => match incoming { - Some(x) => Ok(x), - None => Ok(*target), + Some(state) => state, + None => perm.state, }, _ => match incoming { - Some(x) => match x { - PermissionState::Denied => Ok(x), - _ => Err(custom_error( - "PermissionDenied", - "Can't escalate parent thread permissions", - )), + Some(state) => match state { + PermissionState::Denied => state, + _ => { + return Err(custom_error( + "PermissionDenied", + "Can't escalate parent thread permissions", + )) + } }, - None => Ok(*target), + None => perm.state, }, - } + }; + Ok(perm) } fn check_net_permission_contains( - a: &HashSet<String>, - b: &HashSet<String>, + a: &HashSet<NetPermission>, + b: &HashSet<NetPermission>, ) -> bool { b.iter().all(|x| a.contains(x)) } fn merge_net_permissions( - target: &UnaryPermission<String>, - incoming: Option<UnaryPermission<String>>, -) -> Result<UnaryPermission<String>, AnyError> { + target: &UnaryPermission<NetPermission>, + incoming: Option<UnaryPermission<NetPermission>>, +) -> Result<UnaryPermission<NetPermission>, AnyError> { if incoming.is_none() { return Ok(target.clone()); }; let new_permissions = incoming.unwrap(); match &target.global_state { - PermissionState::Granted => Ok(UnaryPermission::<String> { + PermissionState::Granted => Ok(UnaryPermission::<NetPermission> { global_state: new_permissions.global_state, granted_list: new_permissions.granted_list, denied_list: new_permissions.denied_list, + ..Permissions::new_net(&None) }), PermissionState::Prompt => match new_permissions.global_state { //Throw @@ -161,10 +171,11 @@ fn merge_net_permissions( &target.granted_list, &new_permissions.granted_list, ) { - Ok(UnaryPermission::<String> { + Ok(UnaryPermission::<NetPermission> { global_state: new_permissions.global_state, granted_list: new_permissions.granted_list, denied_list: target.denied_list.clone(), + ..Permissions::new_net(&None) }) } else { Err(custom_error( @@ -174,17 +185,19 @@ fn merge_net_permissions( } } //Copy - PermissionState::Denied => Ok(UnaryPermission::<String> { + PermissionState::Denied => Ok(UnaryPermission::<NetPermission> { global_state: new_permissions.global_state, granted_list: new_permissions.granted_list, denied_list: new_permissions.denied_list, + ..Permissions::new_net(&None) }), }, PermissionState::Denied => match new_permissions.global_state { - PermissionState::Denied => Ok(UnaryPermission::<String> { + PermissionState::Denied => Ok(UnaryPermission::<NetPermission> { global_state: new_permissions.global_state, granted_list: new_permissions.granted_list, denied_list: new_permissions.denied_list, + ..Permissions::new_net(&None) }), _ => Err(custom_error( "PermissionDenied", @@ -194,45 +207,105 @@ fn merge_net_permissions( } } -enum WorkerPermissionType { - READ, - WRITE, -} - fn check_read_permissions( - allow_list: &HashSet<PathBuf>, + allow_list: &HashSet<ReadPermission>, current_permissions: &Permissions, ) -> bool { allow_list .iter() - .all(|x| current_permissions.check_read(&x).is_ok()) + .all(|x| current_permissions.read.check(&x.0).is_ok()) } fn check_write_permissions( - allow_list: &HashSet<PathBuf>, + allow_list: &HashSet<WritePermission>, current_permissions: &Permissions, ) -> bool { allow_list .iter() - .all(|x| current_permissions.check_write(&x).is_ok()) + .all(|x| current_permissions.write.check(&x.0).is_ok()) +} + +fn merge_read_permissions( + target: &UnaryPermission<ReadPermission>, + incoming: Option<UnaryPermission<ReadPermission>>, + current_permissions: &Permissions, +) -> Result<UnaryPermission<ReadPermission>, AnyError> { + if incoming.is_none() { + return Ok(target.clone()); + }; + + let new_permissions = incoming.unwrap(); + match &target.global_state { + PermissionState::Granted => Ok(UnaryPermission::<ReadPermission> { + global_state: new_permissions.global_state, + granted_list: new_permissions.granted_list, + denied_list: new_permissions.denied_list, + ..Permissions::new_read(&None) + }), + PermissionState::Prompt => match new_permissions.global_state { + //Throw + PermissionState::Granted => Err(custom_error( + "PermissionDenied", + "Can't escalate parent thread permissions", + )), + //Merge + PermissionState::Prompt => { + if check_read_permissions( + &new_permissions.granted_list, + current_permissions, + ) { + Ok(UnaryPermission::<ReadPermission> { + global_state: new_permissions.global_state, + granted_list: new_permissions.granted_list, + denied_list: target.denied_list.clone(), + ..Permissions::new_read(&None) + }) + } else { + Err(custom_error( + "PermissionDenied", + "Can't escalate parent thread permissions", + )) + } + } + //Copy + PermissionState::Denied => Ok(UnaryPermission::<ReadPermission> { + global_state: new_permissions.global_state, + granted_list: new_permissions.granted_list, + denied_list: new_permissions.denied_list, + ..Permissions::new_read(&None) + }), + }, + PermissionState::Denied => match new_permissions.global_state { + PermissionState::Denied => Ok(UnaryPermission::<ReadPermission> { + global_state: new_permissions.global_state, + granted_list: new_permissions.granted_list, + denied_list: new_permissions.denied_list, + ..Permissions::new_read(&None) + }), + _ => Err(custom_error( + "PermissionDenied", + "Can't escalate parent thread permissions", + )), + }, + } } -fn merge_read_write_permissions( - permission_type: WorkerPermissionType, - target: &UnaryPermission<PathBuf>, - incoming: Option<UnaryPermission<PathBuf>>, +fn merge_write_permissions( + target: &UnaryPermission<WritePermission>, + incoming: Option<UnaryPermission<WritePermission>>, current_permissions: &Permissions, -) -> Result<UnaryPermission<PathBuf>, AnyError> { +) -> Result<UnaryPermission<WritePermission>, AnyError> { if incoming.is_none() { return Ok(target.clone()); }; let new_permissions = incoming.unwrap(); match &target.global_state { - PermissionState::Granted => Ok(UnaryPermission::<PathBuf> { + PermissionState::Granted => Ok(UnaryPermission::<WritePermission> { global_state: new_permissions.global_state, granted_list: new_permissions.granted_list, denied_list: new_permissions.denied_list, + ..Permissions::new_write(&None) }), PermissionState::Prompt => match new_permissions.global_state { //Throw @@ -242,20 +315,15 @@ fn merge_read_write_permissions( )), //Merge PermissionState::Prompt => { - if match permission_type { - WorkerPermissionType::READ => check_read_permissions( - &new_permissions.granted_list, - current_permissions, - ), - WorkerPermissionType::WRITE => check_write_permissions( - &new_permissions.granted_list, - current_permissions, - ), - } { - Ok(UnaryPermission::<PathBuf> { + if check_write_permissions( + &new_permissions.granted_list, + current_permissions, + ) { + Ok(UnaryPermission::<WritePermission> { global_state: new_permissions.global_state, granted_list: new_permissions.granted_list, denied_list: target.denied_list.clone(), + ..Permissions::new_write(&None) }) } else { Err(custom_error( @@ -265,17 +333,19 @@ fn merge_read_write_permissions( } } //Copy - PermissionState::Denied => Ok(UnaryPermission::<PathBuf> { + PermissionState::Denied => Ok(UnaryPermission::<WritePermission> { global_state: new_permissions.global_state, granted_list: new_permissions.granted_list, denied_list: new_permissions.denied_list, + ..Permissions::new_write(&None) }), }, PermissionState::Denied => match new_permissions.global_state { - PermissionState::Denied => Ok(UnaryPermission::<PathBuf> { + PermissionState::Denied => Ok(UnaryPermission::<WritePermission> { global_state: new_permissions.global_state, granted_list: new_permissions.granted_list, denied_list: new_permissions.denied_list, + ..Permissions::new_write(&None) }), _ => Err(custom_error( "PermissionDenied", @@ -290,11 +360,11 @@ fn create_worker_permissions( permission_args: PermissionsArg, ) -> Result<Permissions, AnyError> { Ok(Permissions { - env: merge_permission_state( + env: merge_boolean_permission( &main_thread_permissions.env, permission_args.env, )?, - hrtime: merge_permission_state( + hrtime: merge_boolean_permission( &main_thread_permissions.hrtime, permission_args.hrtime, )?, @@ -302,22 +372,20 @@ fn create_worker_permissions( &main_thread_permissions.net, permission_args.net, )?, - plugin: merge_permission_state( + plugin: merge_boolean_permission( &main_thread_permissions.plugin, permission_args.plugin, )?, - read: merge_read_write_permissions( - WorkerPermissionType::READ, + read: merge_read_permissions( &main_thread_permissions.read, permission_args.read, &main_thread_permissions, )?, - run: merge_permission_state( + run: merge_boolean_permission( &main_thread_permissions.run, permission_args.run, )?, - write: merge_read_write_permissions( - WorkerPermissionType::WRITE, + write: merge_write_permissions( &main_thread_permissions.write, permission_args.write, &main_thread_permissions, @@ -331,16 +399,16 @@ struct PermissionsArg { env: Option<PermissionState>, #[serde(default, deserialize_with = "as_permission_state")] hrtime: Option<PermissionState>, - #[serde(default, deserialize_with = "as_unary_string_permission")] - net: Option<UnaryPermission<String>>, + #[serde(default, deserialize_with = "as_unary_net_permission")] + net: Option<UnaryPermission<NetPermission>>, #[serde(default, deserialize_with = "as_permission_state")] plugin: Option<PermissionState>, - #[serde(default, deserialize_with = "as_unary_path_permission")] - read: Option<UnaryPermission<PathBuf>>, + #[serde(default, deserialize_with = "as_unary_read_permission")] + read: Option<UnaryPermission<ReadPermission>>, #[serde(default, deserialize_with = "as_permission_state")] run: Option<PermissionState>, - #[serde(default, deserialize_with = "as_unary_path_permission")] - write: Option<UnaryPermission<PathBuf>>, + #[serde(default, deserialize_with = "as_unary_write_permission")] + write: Option<UnaryPermission<WritePermission>>, } fn as_permission_state<'de, D>( @@ -402,27 +470,50 @@ impl<'de> de::Visitor<'de> for ParseBooleanOrStringVec { } } -fn as_unary_string_permission<'de, D>( +fn as_unary_net_permission<'de, D>( deserializer: D, -) -> Result<Option<UnaryPermission<String>>, D::Error> +) -> Result<Option<UnaryPermission<NetPermission>>, D::Error> where D: Deserializer<'de>, { let value: UnaryPermissionBase = deserializer.deserialize_any(ParseBooleanOrStringVec)?; - let allowed: HashSet<String> = value.paths.into_iter().collect(); + let allowed: HashSet<NetPermission> = value + .paths + .into_iter() + .map(NetPermission::from_string) + .collect(); - Ok(Some(UnaryPermission::<String> { + Ok(Some(UnaryPermission::<NetPermission> { global_state: value.global_state, granted_list: allowed, ..Default::default() })) } -fn as_unary_path_permission<'de, D>( +fn as_unary_read_permission<'de, D>( + deserializer: D, +) -> Result<Option<UnaryPermission<ReadPermission>>, D::Error> +where + D: Deserializer<'de>, +{ + let value: UnaryPermissionBase = + deserializer.deserialize_any(ParseBooleanOrStringVec)?; + + let paths: Vec<PathBuf> = + value.paths.into_iter().map(PathBuf::from).collect(); + + Ok(Some(UnaryPermission::<ReadPermission> { + global_state: value.global_state, + granted_list: resolve_read_allowlist(&Some(paths)), + ..Default::default() + })) +} + +fn as_unary_write_permission<'de, D>( deserializer: D, -) -> Result<Option<UnaryPermission<PathBuf>>, D::Error> +) -> Result<Option<UnaryPermission<WritePermission>>, D::Error> where D: Deserializer<'de>, { @@ -432,9 +523,9 @@ where let paths: Vec<PathBuf> = value.paths.into_iter().map(PathBuf::from).collect(); - Ok(Some(UnaryPermission::<PathBuf> { + Ok(Some(UnaryPermission::<WritePermission> { global_state: value.global_state, - granted_list: resolve_fs_allowlist(&Some(paths)), + granted_list: resolve_write_allowlist(&Some(paths)), ..Default::default() })) } |