mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
fix(permissions): handle ipv6 addresses correctly (#24397)
Also don't panic on invalid domain names and addresses. Extracted with cleanups up from #24080 Co-authored-by: Yazan AbdAl-Rahman <yazan.abdalrahman@exalt.ps>
This commit is contained in:
parent
80df9aec1d
commit
74ac29bae6
11 changed files with 415 additions and 138 deletions
|
@ -7859,7 +7859,7 @@ mod tests {
|
||||||
let r = flags_from_vec(svec![
|
let r = flags_from_vec(svec![
|
||||||
"deno",
|
"deno",
|
||||||
"run",
|
"run",
|
||||||
"--unsafely-ignore-certificate-errors=deno.land,localhost,::,127.0.0.1,[::1],1.2.3.4",
|
"--unsafely-ignore-certificate-errors=deno.land,localhost,[::],127.0.0.1,[::1],1.2.3.4",
|
||||||
"script.ts"
|
"script.ts"
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -7871,7 +7871,7 @@ mod tests {
|
||||||
unsafely_ignore_certificate_errors: Some(svec![
|
unsafely_ignore_certificate_errors: Some(svec![
|
||||||
"deno.land",
|
"deno.land",
|
||||||
"localhost",
|
"localhost",
|
||||||
"::",
|
"[::]",
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
"[::1]",
|
"[::1]",
|
||||||
"1.2.3.4"
|
"1.2.3.4"
|
||||||
|
@ -7887,7 +7887,7 @@ mod tests {
|
||||||
let r = flags_from_vec(svec![
|
let r = flags_from_vec(svec![
|
||||||
"deno",
|
"deno",
|
||||||
"repl",
|
"repl",
|
||||||
"--unsafely-ignore-certificate-errors=deno.land,localhost,::,127.0.0.1,[::1],1.2.3.4"]);
|
"--unsafely-ignore-certificate-errors=deno.land,localhost,[::],127.0.0.1,[::1],1.2.3.4"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
|
@ -7899,7 +7899,7 @@ mod tests {
|
||||||
unsafely_ignore_certificate_errors: Some(svec![
|
unsafely_ignore_certificate_errors: Some(svec![
|
||||||
"deno.land",
|
"deno.land",
|
||||||
"localhost",
|
"localhost",
|
||||||
"::",
|
"[::]",
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
"[::1]",
|
"[::1]",
|
||||||
"1.2.3.4"
|
"1.2.3.4"
|
||||||
|
@ -8091,7 +8091,7 @@ mod tests {
|
||||||
let r = flags_from_vec(svec![
|
let r = flags_from_vec(svec![
|
||||||
"deno",
|
"deno",
|
||||||
"run",
|
"run",
|
||||||
"--allow-net=deno.land,deno.land:80,::,127.0.0.1,[::1],1.2.3.4:5678,:5678,[::1]:8080",
|
"--allow-net=deno.land,deno.land:80,[::],127.0.0.1,[::1],1.2.3.4:5678,:5678,[::1]:8080",
|
||||||
"script.ts"
|
"script.ts"
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -8104,7 +8104,7 @@ mod tests {
|
||||||
allow_net: Some(svec![
|
allow_net: Some(svec![
|
||||||
"deno.land",
|
"deno.land",
|
||||||
"deno.land:80",
|
"deno.land:80",
|
||||||
"::",
|
"[::]",
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
"[::1]",
|
"[::1]",
|
||||||
"1.2.3.4:5678",
|
"1.2.3.4:5678",
|
||||||
|
@ -8126,7 +8126,7 @@ mod tests {
|
||||||
let r = flags_from_vec(svec![
|
let r = flags_from_vec(svec![
|
||||||
"deno",
|
"deno",
|
||||||
"run",
|
"run",
|
||||||
"--deny-net=deno.land,deno.land:80,::,127.0.0.1,[::1],1.2.3.4:5678,:5678,[::1]:8080",
|
"--deny-net=deno.land,deno.land:80,[::],127.0.0.1,[::1],1.2.3.4:5678,:5678,[::1]:8080",
|
||||||
"script.ts"
|
"script.ts"
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -8139,7 +8139,7 @@ mod tests {
|
||||||
deny_net: Some(svec![
|
deny_net: Some(svec![
|
||||||
"deno.land",
|
"deno.land",
|
||||||
"deno.land:80",
|
"deno.land:80",
|
||||||
"::",
|
"[::]",
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
"[::1]",
|
"[::1]",
|
||||||
"1.2.3.4:5678",
|
"1.2.3.4:5678",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
|
use deno_runtime::deno_permissions::NetDescriptor;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
@ -42,21 +43,17 @@ pub fn validator(host_and_port: &str) -> Result<String, String> {
|
||||||
/// `127.0.0.1:port` and `localhost:port`.
|
/// `127.0.0.1:port` and `localhost:port`.
|
||||||
pub fn parse(paths: Vec<String>) -> clap::error::Result<Vec<String>> {
|
pub fn parse(paths: Vec<String>) -> clap::error::Result<Vec<String>> {
|
||||||
let mut out: Vec<String> = vec![];
|
let mut out: Vec<String> = vec![];
|
||||||
for host_and_port in paths.iter() {
|
for host_and_port in paths.into_iter() {
|
||||||
if Url::parse(&format!("internal://{host_and_port}")).is_ok()
|
if let Ok(port) = host_and_port.parse::<BarePort>() {
|
||||||
|| host_and_port.parse::<IpAddr>().is_ok()
|
|
||||||
{
|
|
||||||
out.push(host_and_port.to_owned())
|
|
||||||
} else if let Ok(port) = host_and_port.parse::<BarePort>() {
|
|
||||||
// we got bare port, let's add default hosts
|
// we got bare port, let's add default hosts
|
||||||
for host in ["0.0.0.0", "127.0.0.1", "localhost"].iter() {
|
for host in ["0.0.0.0", "127.0.0.1", "localhost"].iter() {
|
||||||
out.push(format!("{}:{}", host, port.0));
|
out.push(format!("{}:{}", host, port.0));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(clap::Error::raw(
|
host_and_port.parse::<NetDescriptor>().map_err(|e| {
|
||||||
clap::error::ErrorKind::InvalidValue,
|
clap::Error::raw(clap::error::ErrorKind::InvalidValue, format!("{e:?}"))
|
||||||
format!("Bad host:port pair: {host_and_port}"),
|
})?;
|
||||||
));
|
out.push(host_and_port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(out)
|
Ok(out)
|
||||||
|
@ -121,8 +118,8 @@ mod tests {
|
||||||
let entries = svec![
|
let entries = svec![
|
||||||
"deno.land",
|
"deno.land",
|
||||||
"deno.land:80",
|
"deno.land:80",
|
||||||
"::",
|
"[::]",
|
||||||
"::1",
|
"[::1]",
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
"[::1]",
|
"[::1]",
|
||||||
"1.2.3.4:5678",
|
"1.2.3.4:5678",
|
||||||
|
@ -142,8 +139,8 @@ mod tests {
|
||||||
let expected = svec![
|
let expected = svec![
|
||||||
"deno.land",
|
"deno.land",
|
||||||
"deno.land:80",
|
"deno.land:80",
|
||||||
"::",
|
"[::]",
|
||||||
"::1",
|
"[::1]",
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
"[::1]",
|
"[::1]",
|
||||||
"1.2.3.4:5678",
|
"1.2.3.4:5678",
|
||||||
|
@ -174,10 +171,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_net_args_ipv6() {
|
fn parse_net_args_ipv6() {
|
||||||
let entries =
|
let entries = svec!["[::1]", "[::]:5678", "[::1]:5678"];
|
||||||
svec!["::", "::1", "[::1]", "[::]:5678", "[::1]:5678", "::cafe"];
|
let expected = svec!["[::1]", "[::]:5678", "[::1]:5678"];
|
||||||
let expected =
|
|
||||||
svec!["::", "::1", "[::1]", "[::]:5678", "[::1]:5678", "::cafe"];
|
|
||||||
let actual = parse(entries).unwrap();
|
let actual = parse(entries).unwrap();
|
||||||
assert_eq!(actual, expected);
|
assert_eq!(actual, expected);
|
||||||
}
|
}
|
||||||
|
@ -190,12 +185,36 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_net_args_ipv6_error2() {
|
fn parse_net_args_ipv6_error2() {
|
||||||
let entries = svec!["0123:4567:890a:bcde:fg::"];
|
let entries = svec!["::1"];
|
||||||
assert!(parse(entries).is_err());
|
assert!(parse(entries).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_net_args_ipv6_error3() {
|
fn parse_net_args_ipv6_error3() {
|
||||||
|
let entries = svec!["::"];
|
||||||
|
assert!(parse(entries).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_net_args_ipv6_error4() {
|
||||||
|
let entries = svec!["::cafe"];
|
||||||
|
assert!(parse(entries).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_net_args_ipv6_error5() {
|
||||||
|
let entries = svec!["1::1"];
|
||||||
|
assert!(parse(entries).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_net_args_ipv6_error6() {
|
||||||
|
let entries = svec!["0123:4567:890a:bcde:fg::"];
|
||||||
|
assert!(parse(entries).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_net_args_ipv6_error7() {
|
||||||
let entries = svec!["[::q]:8080"];
|
let entries = svec!["[::q]:8080"];
|
||||||
assert!(parse(entries).is_err());
|
assert!(parse(entries).is_err());
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,8 @@ use ::deno_permissions::parse_sys_kind;
|
||||||
use ::deno_permissions::PermissionState;
|
use ::deno_permissions::PermissionState;
|
||||||
use ::deno_permissions::PermissionsContainer;
|
use ::deno_permissions::PermissionsContainer;
|
||||||
use deno_core::error::custom_error;
|
use deno_core::error::custom_error;
|
||||||
use deno_core::error::uri_error;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
use deno_core::url;
|
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
@ -65,7 +63,7 @@ pub fn op_query_permission(
|
||||||
"net" => permissions.net.query(
|
"net" => permissions.net.query(
|
||||||
match args.host.as_deref() {
|
match args.host.as_deref() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => Some(parse_host(h)?),
|
Some(h) => Some(h.parse()?),
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
|
@ -100,7 +98,7 @@ pub fn op_revoke_permission(
|
||||||
"net" => permissions.net.revoke(
|
"net" => permissions.net.revoke(
|
||||||
match args.host.as_deref() {
|
match args.host.as_deref() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => Some(parse_host(h)?),
|
Some(h) => Some(h.parse()?),
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
|
@ -135,7 +133,7 @@ pub fn op_request_permission(
|
||||||
"net" => permissions.net.request(
|
"net" => permissions.net.request(
|
||||||
match args.host.as_deref() {
|
match args.host.as_deref() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => Some(parse_host(h)?),
|
Some(h) => Some(h.parse()?),
|
||||||
}
|
}
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
),
|
),
|
||||||
|
@ -155,13 +153,3 @@ pub fn op_request_permission(
|
||||||
};
|
};
|
||||||
Ok(PermissionStatus::from(perm))
|
Ok(PermissionStatus::from(perm))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_host(host_str: &str) -> Result<(String, Option<u16>), AnyError> {
|
|
||||||
let url = url::Url::parse(&format!("http://{host_str}/"))
|
|
||||||
.map_err(|_| uri_error("Invalid host"))?;
|
|
||||||
if url.path() != "/" {
|
|
||||||
return Err(uri_error("Invalid host"));
|
|
||||||
}
|
|
||||||
let hostname = url.host_str().unwrap();
|
|
||||||
Ok((hostname.to_string(), url.port()))
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ use deno_core::url;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
use fqdn::fqdn;
|
|
||||||
use fqdn::FQDN;
|
use fqdn::FQDN;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -25,6 +24,8 @@ use std::ffi::OsStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
use std::net::Ipv6Addr;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -691,13 +692,48 @@ impl Descriptor for WriteDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub struct NetDescriptor(pub FQDN, pub Option<u16>);
|
pub enum Host {
|
||||||
|
Fqdn(FQDN),
|
||||||
|
Ip(IpAddr),
|
||||||
|
}
|
||||||
|
|
||||||
impl NetDescriptor {
|
impl FromStr for Host {
|
||||||
fn new<T: AsRef<str>>(host: &&(T, Option<u16>)) -> Self {
|
type Err = AnyError;
|
||||||
NetDescriptor(fqdn!(host.0.as_ref()), host.1)
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
if s.starts_with('[') && s.ends_with(']') {
|
||||||
|
let ip = s[1..s.len() - 1]
|
||||||
|
.parse::<Ipv6Addr>()
|
||||||
|
.map_err(|_| uri_error(format!("invalid IPv6 address: '{s}'")))?;
|
||||||
|
return Ok(Host::Ip(IpAddr::V6(ip)));
|
||||||
|
}
|
||||||
|
let (without_trailing_dot, has_trailing_dot) =
|
||||||
|
s.strip_suffix('.').map_or((s, false), |s| (s, true));
|
||||||
|
if let Ok(ip) = without_trailing_dot.parse::<IpAddr>() {
|
||||||
|
if has_trailing_dot {
|
||||||
|
return Err(uri_error(format!(
|
||||||
|
"invalid host: '{without_trailing_dot}'"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
Ok(Host::Ip(ip))
|
||||||
|
} else {
|
||||||
|
let lower = if s.chars().all(|c| c.is_ascii_lowercase()) {
|
||||||
|
Cow::Borrowed(s)
|
||||||
|
} else {
|
||||||
|
Cow::Owned(s.to_ascii_lowercase())
|
||||||
|
};
|
||||||
|
let fqdn = FQDN::from_str(&lower)
|
||||||
|
.with_context(|| format!("invalid host: '{s}'"))?;
|
||||||
|
if fqdn.is_root() {
|
||||||
|
return Err(uri_error(format!("invalid empty host: '{s}'")));
|
||||||
|
}
|
||||||
|
Ok(Host::Fqdn(fqdn))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
|
pub struct NetDescriptor(pub Host, pub Option<u16>);
|
||||||
|
|
||||||
impl Descriptor for NetDescriptor {
|
impl Descriptor for NetDescriptor {
|
||||||
type Arg = String;
|
type Arg = String;
|
||||||
|
@ -731,26 +767,72 @@ impl Descriptor for NetDescriptor {
|
||||||
impl FromStr for NetDescriptor {
|
impl FromStr for NetDescriptor {
|
||||||
type Err = AnyError;
|
type Err = AnyError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(hostname: &str) -> Result<Self, Self::Err> {
|
||||||
// Set the scheme to `unknown` to parse the URL, as we really don't know
|
// If this is a IPv6 address enclosed in square brackets, parse it as such.
|
||||||
// what the scheme is. We only using Url::parse to parse the host and port
|
if hostname.starts_with('[') {
|
||||||
// and don't care about the scheme.
|
if let Some((ip, after)) = hostname.split_once(']') {
|
||||||
let url = url::Url::parse(&format!("unknown://{s}"))?;
|
let ip = ip[1..].parse::<Ipv6Addr>().map_err(|_| {
|
||||||
let hostname = url
|
uri_error(format!("invalid IPv6 address in '{hostname}': '{ip}'"))
|
||||||
.host_str()
|
})?;
|
||||||
.ok_or(url::ParseError::EmptyHost)?
|
let port = if let Some(port) = after.strip_prefix(':') {
|
||||||
.to_string();
|
let port = port.parse::<u16>().map_err(|_| {
|
||||||
|
uri_error(format!("invalid port in '{hostname}': '{port}'"))
|
||||||
|
})?;
|
||||||
|
Some(port)
|
||||||
|
} else if after.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
return Err(uri_error(format!("invalid host: '{hostname}'")));
|
||||||
|
};
|
||||||
|
return Ok(NetDescriptor(Host::Ip(IpAddr::V6(ip)), port));
|
||||||
|
} else {
|
||||||
|
return Err(uri_error(format!("invalid host: '{hostname}'")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(NetDescriptor(fqdn!(&hostname), url.port()))
|
// Otherwise it is an IPv4 address or a FQDN with an optional port.
|
||||||
|
let (host, port) = match hostname.split_once(':') {
|
||||||
|
Some((_, "")) => {
|
||||||
|
return Err(uri_error(format!("invalid empty port in '{hostname}'")));
|
||||||
|
}
|
||||||
|
Some((host, port)) => (host, port),
|
||||||
|
None => (hostname, ""),
|
||||||
|
};
|
||||||
|
let host = host.parse::<Host>()?;
|
||||||
|
|
||||||
|
let port = if port.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let port = port.parse::<u16>().map_err(|_| {
|
||||||
|
// If the user forgot to enclose an IPv6 address in square brackets, we
|
||||||
|
// should give them a hint. There are always at least two colons in an
|
||||||
|
// IPv6 address, so this heuristic finds likely a bare IPv6 address.
|
||||||
|
if port.contains(':') {
|
||||||
|
uri_error(format!(
|
||||||
|
"ipv6 addresses must be enclosed in square brackets: '{hostname}'"
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
uri_error(format!("invalid port in '{hostname}': '{port}'"))
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
Some(port)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(NetDescriptor(host, port))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for NetDescriptor {
|
impl fmt::Display for NetDescriptor {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.write_str(&match self.1 {
|
match &self.0 {
|
||||||
None => self.0.to_string(),
|
Host::Fqdn(fqdn) => write!(f, "{fqdn}"),
|
||||||
Some(port) => format!("{}:{}", self.0, port),
|
Host::Ip(IpAddr::V4(ip)) => write!(f, "{ip}"),
|
||||||
})
|
Host::Ip(IpAddr::V6(ip)) => write!(f, "[{ip}]"),
|
||||||
|
}?;
|
||||||
|
if let Some(port) = self.1 {
|
||||||
|
write!(f, ":{}", port)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1107,37 +1189,25 @@ impl UnaryPermission<WriteDescriptor> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnaryPermission<NetDescriptor> {
|
impl UnaryPermission<NetDescriptor> {
|
||||||
pub fn query<T: AsRef<str>>(
|
pub fn query(&self, host: Option<&NetDescriptor>) -> PermissionState {
|
||||||
&self,
|
self.query_desc(host, AllowPartial::TreatAsPartialGranted)
|
||||||
host: Option<&(T, Option<u16>)>,
|
|
||||||
) -> PermissionState {
|
|
||||||
self.query_desc(
|
|
||||||
host.map(|h| NetDescriptor::new(&h)).as_ref(),
|
|
||||||
AllowPartial::TreatAsPartialGranted,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request<T: AsRef<str>>(
|
pub fn request(&mut self, host: Option<&NetDescriptor>) -> PermissionState {
|
||||||
&mut self,
|
self.request_desc(host, || None)
|
||||||
host: Option<&(T, Option<u16>)>,
|
|
||||||
) -> PermissionState {
|
|
||||||
self.request_desc(host.map(|h| NetDescriptor::new(&h)).as_ref(), || None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn revoke<T: AsRef<str>>(
|
pub fn revoke(&mut self, host: Option<&NetDescriptor>) -> PermissionState {
|
||||||
&mut self,
|
self.revoke_desc(host)
|
||||||
host: Option<&(T, Option<u16>)>,
|
|
||||||
) -> PermissionState {
|
|
||||||
self.revoke_desc(host.map(|h| NetDescriptor::new(&h)).as_ref())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check<T: AsRef<str>>(
|
pub fn check(
|
||||||
&mut self,
|
&mut self,
|
||||||
host: &(T, Option<u16>),
|
host: &NetDescriptor,
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
skip_check_if_is_permission_fully_granted!(self);
|
skip_check_if_is_permission_fully_granted!(self);
|
||||||
self.check_desc(Some(&NetDescriptor::new(&host)), false, api_name, || None)
|
self.check_desc(Some(host), false, api_name, || None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_url(
|
pub fn check_url(
|
||||||
|
@ -1146,17 +1216,14 @@ impl UnaryPermission<NetDescriptor> {
|
||||||
api_name: Option<&str>,
|
api_name: Option<&str>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
skip_check_if_is_permission_fully_granted!(self);
|
skip_check_if_is_permission_fully_granted!(self);
|
||||||
let hostname = url
|
let host = url
|
||||||
.host_str()
|
.host_str()
|
||||||
.ok_or_else(|| uri_error("Missing host"))?
|
.ok_or_else(|| type_error(format!("Missing host in url: '{}'", url)))?;
|
||||||
.to_string();
|
let host = host.parse::<Host>()?;
|
||||||
let host = &(&hostname, url.port_or_known_default());
|
let port = url.port_or_known_default();
|
||||||
let display_host = match url.port() {
|
let descriptor = NetDescriptor(host, port);
|
||||||
None => hostname.clone(),
|
self.check_desc(Some(&descriptor), false, api_name, || {
|
||||||
Some(port) => format!("{hostname}:{port}"),
|
Some(format!("\"{descriptor}\""))
|
||||||
};
|
|
||||||
self.check_desc(Some(&NetDescriptor::new(&host)), false, api_name, || {
|
|
||||||
Some(format!("\"{}\"", display_host))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1782,7 +1849,9 @@ impl PermissionsContainer {
|
||||||
host: &(T, Option<u16>),
|
host: &(T, Option<u16>),
|
||||||
api_name: &str,
|
api_name: &str,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self.0.lock().net.check(host, Some(api_name))
|
let hostname = host.0.as_ref().parse::<Host>()?;
|
||||||
|
let descriptor = NetDescriptor(hostname, host.1);
|
||||||
|
self.0.lock().net.check(&descriptor, Some(api_name))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -2209,7 +2278,9 @@ pub fn create_child_permissions(
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
|
use fqdn::fqdn;
|
||||||
use prompter::tests::*;
|
use prompter::tests::*;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
// Creates vector of strings, Vec<String>
|
// Creates vector of strings, Vec<String>
|
||||||
macro_rules! svec {
|
macro_rules! svec {
|
||||||
|
@ -2363,12 +2434,12 @@ mod tests {
|
||||||
];
|
];
|
||||||
|
|
||||||
for (host, port, is_ok) in domain_tests {
|
for (host, port, is_ok) in domain_tests {
|
||||||
|
let host = host.parse().unwrap();
|
||||||
|
let descriptor = NetDescriptor(host, Some(port));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
is_ok,
|
is_ok,
|
||||||
perms.net.check(&(host, Some(port)), None).is_ok(),
|
perms.net.check(&descriptor, None).is_ok(),
|
||||||
"{}:{}",
|
"{descriptor}",
|
||||||
host,
|
|
||||||
port,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2404,8 +2475,13 @@ mod tests {
|
||||||
("192.168.0.1", 0),
|
("192.168.0.1", 0),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (host, port) in domain_tests {
|
for (host_str, port) in domain_tests {
|
||||||
assert!(perms.net.check(&(host, Some(port)), None).is_ok());
|
let host = host_str.parse().unwrap();
|
||||||
|
let descriptor = NetDescriptor(host, Some(port));
|
||||||
|
assert!(
|
||||||
|
perms.net.check(&descriptor, None).is_ok(),
|
||||||
|
"expected {host_str}:{port} to pass"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2440,8 +2516,13 @@ mod tests {
|
||||||
("192.168.0.1", 0),
|
("192.168.0.1", 0),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (host, port) in domain_tests {
|
for (host_str, port) in domain_tests {
|
||||||
assert!(perms.net.check(&(host, Some(port)), None).is_err());
|
let host = host_str.parse().unwrap();
|
||||||
|
let descriptor = NetDescriptor(host, Some(port));
|
||||||
|
assert!(
|
||||||
|
perms.net.check(&descriptor, None).is_err(),
|
||||||
|
"expected {host_str}:{port} to fail"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2716,15 +2797,15 @@ mod tests {
|
||||||
assert_eq!(perms4.ffi.query(Some(Path::new("/foo"))), PermissionState::Denied);
|
assert_eq!(perms4.ffi.query(Some(Path::new("/foo"))), PermissionState::Denied);
|
||||||
assert_eq!(perms4.ffi.query(Some(Path::new("/foo/bar"))), PermissionState::Denied);
|
assert_eq!(perms4.ffi.query(Some(Path::new("/foo/bar"))), PermissionState::Denied);
|
||||||
assert_eq!(perms4.ffi.query(Some(Path::new("/bar"))), PermissionState::Granted);
|
assert_eq!(perms4.ffi.query(Some(Path::new("/bar"))), PermissionState::Granted);
|
||||||
assert_eq!(perms1.net.query::<&str>(None), PermissionState::Granted);
|
assert_eq!(perms1.net.query(None), PermissionState::Granted);
|
||||||
assert_eq!(perms1.net.query(Some(&("127.0.0.1", None))), PermissionState::Granted);
|
assert_eq!(perms1.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Granted);
|
||||||
assert_eq!(perms2.net.query::<&str>(None), PermissionState::Prompt);
|
assert_eq!(perms2.net.query(None), PermissionState::Prompt);
|
||||||
assert_eq!(perms2.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
assert_eq!(perms2.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
|
||||||
assert_eq!(perms3.net.query::<&str>(None), PermissionState::Prompt);
|
assert_eq!(perms3.net.query(None), PermissionState::Prompt);
|
||||||
assert_eq!(perms3.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Denied);
|
assert_eq!(perms3.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Denied);
|
||||||
assert_eq!(perms4.net.query::<&str>(None), PermissionState::GrantedPartial);
|
assert_eq!(perms4.net.query(None), PermissionState::GrantedPartial);
|
||||||
assert_eq!(perms4.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Denied);
|
assert_eq!(perms4.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Denied);
|
||||||
assert_eq!(perms4.net.query(Some(&("192.168.0.1", Some(8000)))), PermissionState::Granted);
|
assert_eq!(perms4.net.query(Some(&NetDescriptor("192.168.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
|
||||||
assert_eq!(perms1.env.query(None), PermissionState::Granted);
|
assert_eq!(perms1.env.query(None), PermissionState::Granted);
|
||||||
assert_eq!(perms1.env.query(Some("HOME")), PermissionState::Granted);
|
assert_eq!(perms1.env.query(Some("HOME")), PermissionState::Granted);
|
||||||
assert_eq!(perms2.env.query(None), PermissionState::Prompt);
|
assert_eq!(perms2.env.query(None), PermissionState::Prompt);
|
||||||
|
@ -2782,9 +2863,9 @@ mod tests {
|
||||||
prompt_value.set(true);
|
prompt_value.set(true);
|
||||||
assert_eq!(perms.ffi.request(None), PermissionState::Denied);
|
assert_eq!(perms.ffi.request(None), PermissionState::Denied);
|
||||||
prompt_value.set(true);
|
prompt_value.set(true);
|
||||||
assert_eq!(perms.net.request(Some(&("127.0.0.1", None))), PermissionState::Granted);
|
assert_eq!(perms.net.request(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Granted);
|
||||||
prompt_value.set(false);
|
prompt_value.set(false);
|
||||||
assert_eq!(perms.net.request(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
assert_eq!(perms.net.request(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
|
||||||
prompt_value.set(true);
|
prompt_value.set(true);
|
||||||
assert_eq!(perms.env.request(Some("HOME")), PermissionState::Granted);
|
assert_eq!(perms.env.request(Some("HOME")), PermissionState::Granted);
|
||||||
assert_eq!(perms.env.query(None), PermissionState::Prompt);
|
assert_eq!(perms.env.query(None), PermissionState::Prompt);
|
||||||
|
@ -2853,9 +2934,9 @@ mod tests {
|
||||||
assert_eq!(perms.ffi.revoke(Some(Path::new("/foo/bar"))), PermissionState::Prompt);
|
assert_eq!(perms.ffi.revoke(Some(Path::new("/foo/bar"))), PermissionState::Prompt);
|
||||||
assert_eq!(perms.ffi.query(Some(Path::new("/foo"))), PermissionState::Prompt);
|
assert_eq!(perms.ffi.query(Some(Path::new("/foo"))), PermissionState::Prompt);
|
||||||
assert_eq!(perms.ffi.query(Some(Path::new("/foo/baz"))), PermissionState::Granted);
|
assert_eq!(perms.ffi.query(Some(Path::new("/foo/baz"))), PermissionState::Granted);
|
||||||
assert_eq!(perms.net.revoke(Some(&("127.0.0.1", Some(9000)))), PermissionState::Prompt);
|
assert_eq!(perms.net.revoke(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(9000)))), PermissionState::Prompt);
|
||||||
assert_eq!(perms.net.query(Some(&("127.0.0.1", None))), PermissionState::Prompt);
|
assert_eq!(perms.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), None))), PermissionState::Prompt);
|
||||||
assert_eq!(perms.net.query(Some(&("127.0.0.1", Some(8000)))), PermissionState::Granted);
|
assert_eq!(perms.net.query(Some(&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)))), PermissionState::Granted);
|
||||||
assert_eq!(perms.env.revoke(Some("HOME")), PermissionState::Prompt);
|
assert_eq!(perms.env.revoke(Some("HOME")), PermissionState::Prompt);
|
||||||
assert_eq!(perms.env.revoke(Some("hostname")), PermissionState::Prompt);
|
assert_eq!(perms.env.revoke(Some("hostname")), PermissionState::Prompt);
|
||||||
assert_eq!(perms.run.revoke(Some("deno")), PermissionState::Prompt);
|
assert_eq!(perms.run.revoke(Some("deno")), PermissionState::Prompt);
|
||||||
|
@ -2888,13 +2969,43 @@ mod tests {
|
||||||
assert!(perms.ffi.check(Path::new("/bar"), None).is_err());
|
assert!(perms.ffi.check(Path::new("/bar"), None).is_err());
|
||||||
|
|
||||||
prompt_value.set(true);
|
prompt_value.set(true);
|
||||||
assert!(perms.net.check(&("127.0.0.1", Some(8000)), None).is_ok());
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
prompt_value.set(false);
|
prompt_value.set(false);
|
||||||
assert!(perms.net.check(&("127.0.0.1", Some(8000)), None).is_ok());
|
assert!(perms
|
||||||
assert!(perms.net.check(&("127.0.0.1", Some(8001)), None).is_err());
|
.net
|
||||||
assert!(perms.net.check(&("127.0.0.1", None), None).is_err());
|
.check(
|
||||||
assert!(perms.net.check(&("deno.land", Some(8000)), None).is_err());
|
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
|
||||||
assert!(perms.net.check(&("deno.land", None), None).is_err());
|
None
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_err());
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(&NetDescriptor("127.0.0.1".parse().unwrap(), None), None)
|
||||||
|
.is_err());
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_err());
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(&NetDescriptor("deno.land".parse().unwrap(), None), None)
|
||||||
|
.is_err());
|
||||||
|
|
||||||
prompt_value.set(true);
|
prompt_value.set(true);
|
||||||
assert!(perms.run.check("cat", None).is_ok());
|
assert!(perms.run.check("cat", None).is_ok());
|
||||||
|
@ -2948,14 +3059,50 @@ mod tests {
|
||||||
assert!(perms.ffi.check(Path::new("/bar"), None).is_ok());
|
assert!(perms.ffi.check(Path::new("/bar"), None).is_ok());
|
||||||
|
|
||||||
prompt_value.set(false);
|
prompt_value.set(false);
|
||||||
assert!(perms.net.check(&("127.0.0.1", Some(8000)), None).is_err());
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_err());
|
||||||
prompt_value.set(true);
|
prompt_value.set(true);
|
||||||
assert!(perms.net.check(&("127.0.0.1", Some(8000)), None).is_err());
|
assert!(perms
|
||||||
assert!(perms.net.check(&("127.0.0.1", Some(8001)), None).is_ok());
|
.net
|
||||||
assert!(perms.net.check(&("deno.land", Some(8000)), None).is_ok());
|
.check(
|
||||||
|
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8000)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_err());
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
prompt_value.set(false);
|
prompt_value.set(false);
|
||||||
assert!(perms.net.check(&("127.0.0.1", Some(8001)), None).is_ok());
|
assert!(perms
|
||||||
assert!(perms.net.check(&("deno.land", Some(8000)), None).is_ok());
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("127.0.0.1".parse().unwrap(), Some(8001)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("deno.land".parse().unwrap(), Some(8000)),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
|
|
||||||
prompt_value.set(false);
|
prompt_value.set(false);
|
||||||
assert!(perms.run.check("cat", None).is_err());
|
assert!(perms.run.check("cat", None).is_err());
|
||||||
|
@ -3044,10 +3191,28 @@ mod tests {
|
||||||
..Permissions::none_without_prompt()
|
..Permissions::none_without_prompt()
|
||||||
};
|
};
|
||||||
|
|
||||||
perms.net.check(&("allowed.domain.", None), None).unwrap();
|
perms
|
||||||
perms.net.check(&("1.1.1.1.", None), None).unwrap();
|
.net
|
||||||
assert!(perms.net.check(&("denied.domain.", None), None).is_err());
|
.check(
|
||||||
assert!(perms.net.check(&("2.2.2.2.", None), None).is_err());
|
&NetDescriptor("allowed.domain.".parse().unwrap(), None),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
perms
|
||||||
|
.net
|
||||||
|
.check(&NetDescriptor("1.1.1.1".parse().unwrap(), None), None)
|
||||||
|
.unwrap();
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(
|
||||||
|
&NetDescriptor("denied.domain.".parse().unwrap(), None),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.is_err());
|
||||||
|
assert!(perms
|
||||||
|
.net
|
||||||
|
.check(&NetDescriptor("2.2.2.2".parse().unwrap(), None), None)
|
||||||
|
.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -3333,4 +3498,109 @@ mod tests {
|
||||||
)
|
)
|
||||||
.is_err());
|
.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_host_parse() {
|
||||||
|
let hosts = &[
|
||||||
|
("deno.land", Some(Host::Fqdn(fqdn!("deno.land")))),
|
||||||
|
("DENO.land", Some(Host::Fqdn(fqdn!("deno.land")))),
|
||||||
|
("deno.land.", Some(Host::Fqdn(fqdn!("deno.land")))),
|
||||||
|
(
|
||||||
|
"1.1.1.1",
|
||||||
|
Some(Host::Ip(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"::1",
|
||||||
|
Some(Host::Ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"[::1]",
|
||||||
|
Some(Host::Ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)))),
|
||||||
|
),
|
||||||
|
("[::1", None),
|
||||||
|
("::1]", None),
|
||||||
|
("deno. land", None),
|
||||||
|
("1. 1.1.1", None),
|
||||||
|
("1.1.1.1.", None),
|
||||||
|
("1::1.", None),
|
||||||
|
("deno.land.", Some(Host::Fqdn(fqdn!("deno.land")))),
|
||||||
|
(".deno.land", None),
|
||||||
|
(
|
||||||
|
"::ffff:1.1.1.1",
|
||||||
|
Some(Host::Ip(IpAddr::V6(Ipv6Addr::new(
|
||||||
|
0, 0, 0, 0, 0, 0xffff, 0x0101, 0x0101,
|
||||||
|
)))),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (host_str, expected) in hosts {
|
||||||
|
assert_eq!(host_str.parse::<Host>().ok(), *expected, "{host_str}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_net_descriptor_parse() {
|
||||||
|
let cases = &[
|
||||||
|
(
|
||||||
|
"deno.land",
|
||||||
|
Some(NetDescriptor(Host::Fqdn(fqdn!("deno.land")), None)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"DENO.land",
|
||||||
|
Some(NetDescriptor(Host::Fqdn(fqdn!("deno.land")), None)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"deno.land:8000",
|
||||||
|
Some(NetDescriptor(Host::Fqdn(fqdn!("deno.land")), Some(8000))),
|
||||||
|
),
|
||||||
|
("deno.land:", None),
|
||||||
|
("deno.land:a", None),
|
||||||
|
("deno. land:a", None),
|
||||||
|
("deno.land.: a", None),
|
||||||
|
(
|
||||||
|
"1.1.1.1",
|
||||||
|
Some(NetDescriptor(
|
||||||
|
Host::Ip(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1))),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
("1.1.1.1.", None),
|
||||||
|
("1.1.1.1..", None),
|
||||||
|
(
|
||||||
|
"1.1.1.1:8000",
|
||||||
|
Some(NetDescriptor(
|
||||||
|
Host::Ip(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1))),
|
||||||
|
Some(8000),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
("::", None),
|
||||||
|
(":::80", None),
|
||||||
|
("::80", None),
|
||||||
|
(
|
||||||
|
"[::]",
|
||||||
|
Some(NetDescriptor(
|
||||||
|
Host::Ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0))),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
("[::1", None),
|
||||||
|
("::1]", None),
|
||||||
|
("::1]", None),
|
||||||
|
("[::1]:", None),
|
||||||
|
("[::1]:a", None),
|
||||||
|
(
|
||||||
|
"[::1]:443",
|
||||||
|
Some(NetDescriptor(
|
||||||
|
Host::Ip(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))),
|
||||||
|
Some(443),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
("", None),
|
||||||
|
("deno.land..", None),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (input, expected) in cases {
|
||||||
|
assert_eq!(input.parse::<NetDescriptor>().ok(), *expected, "'{input}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag
|
||||||
at blob:null/[WILDCARD]:1:8
|
at blob:null/[WILDCARD]:1:8
|
||||||
await import(URL.createObjectURL(blob));
|
await import(URL.createObjectURL(blob));
|
||||||
^
|
^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag
|
||||||
at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8
|
at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8
|
||||||
await import(`data:application/javascript;base64,${btoa(code)}`);
|
await import(`data:application/javascript;base64,${btoa(code)}`);
|
||||||
^
|
^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag
|
||||||
at http://localhost:4545/dynamic_import/static_remote.ts:2:8
|
at http://localhost:4545/dynamic_import/static_remote.ts:2:8
|
||||||
await import(
|
await import(
|
||||||
^
|
^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag
|
||||||
at blob:null/[WILDCARD]:1:8
|
at blob:null/[WILDCARD]:1:8
|
||||||
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
||||||
at Worker.#pollControl[WILDCARD]
|
at Worker.#pollControl[WILDCARD]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag
|
||||||
at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8
|
at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8
|
||||||
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
||||||
at Worker.#pollControl[WILDCARD]
|
at Worker.#pollControl[WILDCARD]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "example.com:443", run again with the --allow-net flag
|
||||||
await import("" + "https://example.com/some/file.ts");
|
await import("" + "https://example.com/some/file.ts");
|
||||||
^
|
^
|
||||||
at async http://localhost:4545/workers/dynamic_remote.ts:2:1
|
at async http://localhost:4545/workers/dynamic_remote.ts:2:1
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") Requires net access to "example.com:443", run again with the --allow-net flag
|
||||||
at http://localhost:4545/workers/static_remote.ts:2:8
|
at http://localhost:4545/workers/static_remote.ts:2:8
|
||||||
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
error: Uncaught (in promise) Error: Unhandled error in child worker.
|
||||||
at Worker.#pollControl [WILDCARD]
|
at Worker.#pollControl [WILDCARD]
|
||||||
|
|
Loading…
Reference in a new issue