fix(websocket): Fix PermissionDenied error being caught in constructor (#8402)

This commit is contained in:
crowlKats 2020-11-25 15:17:46 +01:00 committed by GitHub
parent fb13967d1d
commit d40b0711a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 2 deletions

View File

@ -8,12 +8,12 @@ use deno_core::error::AnyError;
use deno_core::futures::future::poll_fn;
use deno_core::futures::StreamExt;
use deno_core::futures::{ready, SinkExt};
use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::url;
use deno_core::BufVec;
use deno_core::OpState;
use deno_core::{serde_json, ZeroCopyBuf};
use http::{Method, Request, Uri};
use serde::Deserialize;
use std::borrow::Cow;
@ -34,6 +34,7 @@ use tokio_tungstenite::{client_async, WebSocketStream};
use webpki::DNSNameRef;
pub fn init(rt: &mut deno_core::JsRuntime) {
super::reg_json_sync(rt, "op_ws_check_permission", op_ws_check_permission);
super::reg_json_async(rt, "op_ws_create", op_ws_create);
super::reg_json_async(rt, "op_ws_send", op_ws_send);
super::reg_json_async(rt, "op_ws_close", op_ws_close);
@ -45,6 +46,29 @@ type MaybeTlsStream =
type WsStream = WebSocketStream<MaybeTlsStream>;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct CheckPermissionArgs {
url: String,
}
// This op is needed because creating a WS instance in JavaScript is a sync
// operation and should throw error when permissions are not fullfiled,
// but actual op that connects WS is async.
pub fn op_ws_check_permission(
state: &mut OpState,
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let args: CheckPermissionArgs = serde_json::from_value(args)?;
state
.borrow::<Permissions>()
.check_net_url(&url::Url::parse(&args.url)?)?;
Ok(json!({}))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct CreateArgs {
@ -58,11 +82,16 @@ pub async fn op_ws_create(
_bufs: BufVec,
) -> Result<Value, AnyError> {
let args: CreateArgs = serde_json::from_value(args)?;
{
let s = state.borrow();
s.borrow::<Permissions>()
.check_net_url(&url::Url::parse(&args.url)?)?;
.check_net_url(&url::Url::parse(&args.url)?)
.expect(
"Permission check should have been done in op_ws_check_permission",
);
}
let ca_file = {
let cli_state = super::global_state2(&state);
cli_state.flags.ca_file.clone()

View File

@ -33,6 +33,10 @@
this.#url = wsURL.href;
core.jsonOpSync("op_ws_check_permission", {
url: this.#url,
});
if (protocols && typeof protocols === "string") {
protocols = [protocols];
}

View File

@ -79,3 +79,4 @@ import "./write_file_test.ts";
import "./write_text_file_test.ts";
import "./performance_test.ts";
import "./version_test.ts";
import "./websocket_test.ts";

View File

@ -0,0 +1,9 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { assertThrows, unitTest } from "./test_util.ts";
unitTest(function websocketPermissionless() {
assertThrows(
() => new WebSocket("ws://localhost"),
Deno.errors.PermissionDenied,
);
});