From c475e127223592770533b711034ec6c945bd2a0c Mon Sep 17 00:00:00 2001 From: Arnaldo Garcia Rincon Date: Thu, 28 Sep 2023 00:16:57 +0000 Subject: [PATCH] apiclient: update tungstenite to v0.20.1 Newer versions of tungstenite implemented the v13 version of the Web Sockets protocol (described in https://www.rfc-editor.org/rfc/rfc6455). In this version, new headers are required in the upgrade request. With this update, now the upgrade request sent by apiclient include the missing headers. In the same version, the 'frame' message was added. Neither apiserver nor apiclient send this type of message, so they are ignored by apiclient. Signed-off-by: Arnaldo Garcia Rincon --- sources/Cargo.lock | 58 +++++------------------ sources/api/apiclient/Cargo.toml | 3 +- sources/api/apiclient/src/exec.rs | 5 ++ sources/api/apiclient/src/exec/connect.rs | 32 ++++++++++++- sources/deny.toml | 7 +-- 5 files changed, 53 insertions(+), 52 deletions(-) diff --git a/sources/Cargo.lock b/sources/Cargo.lock index e28d4337143..6304bdc3765 100644 --- a/sources/Cargo.lock +++ b/sources/Cargo.lock @@ -327,6 +327,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" name = "apiclient" version = "0.1.0" dependencies = [ + "base64 0.21.2", "constants", "datastore", "futures", @@ -1021,15 +1022,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -1488,22 +1480,13 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", "subtle", ] @@ -1988,7 +1971,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -2825,12 +2808,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "openssl-probe" version = "0.1.5" @@ -3584,19 +3561,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha1" version = "0.10.5" @@ -3605,7 +3569,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -3616,7 +3580,7 @@ checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -4117,9 +4081,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.16.1" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e80b39df6afcc12cdf752398ade96a6b9e99c903dfdc36e53ad10b9c366bca72" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", @@ -4247,18 +4211,18 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tungstenite" -version = "0.16.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ad3713a14ae247f22a728a0456a545df14acf3867f905adff84be99e23b3ad1" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ - "base64 0.13.1", "byteorder", "bytes", + "data-encoding", "http", "httparse", "log", "rand", - "sha-1", + "sha1", "thiserror", "url", "utf-8", diff --git a/sources/api/apiclient/Cargo.toml b/sources/api/apiclient/Cargo.toml index ffe43154b71..f737b0f72f2 100644 --- a/sources/api/apiclient/Cargo.toml +++ b/sources/api/apiclient/Cargo.toml @@ -10,6 +10,7 @@ build = "build.rs" exclude = ["README.md"] [dependencies] +base64 = "0.21" constants = { path = "../../constants", version = "0.1" } datastore = { path = "../datastore", version = "0.1" } futures = { version = "0.3", default-features = false } @@ -31,7 +32,7 @@ signal-hook = "0.3" simplelog = "0.12" snafu = { version = "0.7", features = ["futures"] } tokio = { version = "~1.25", default-features = false, features = ["fs", "io-std", "io-util", "macros", "rt-multi-thread", "time"] } # LTS -tokio-tungstenite = { version = "0.16", default-features = false, features = ["connect"] } +tokio-tungstenite = { version = "0.20", default-features = false, features = ["connect"] } toml = "0.5" unindent = "0.1" url = "2" diff --git a/sources/api/apiclient/src/exec.rs b/sources/api/apiclient/src/exec.rs index 5cf696b971e..410d25364a4 100644 --- a/sources/api/apiclient/src/exec.rs +++ b/sources/api/apiclient/src/exec.rs @@ -313,6 +313,11 @@ impl ReadFromServer { } } } + // The API server doesn't use frames, but still logging out a + // warning in case a message of this type is received + Message::Frame(_) => { + warn!("Received an unexpected frame message"); + } } Ok(()) } diff --git a/sources/api/apiclient/src/exec/connect.rs b/sources/api/apiclient/src/exec/connect.rs index 77fc4e7a68f..b89a09bfb7c 100644 --- a/sources/api/apiclient/src/exec/connect.rs +++ b/sources/api/apiclient/src/exec/connect.rs @@ -1,9 +1,13 @@ //! The 'connect' module provides a function for connecting to a WebSocket over a Unix-domain //! socket, which is a bit more finicky than normal. +use base64::{engine, Engine as _}; +use http::header::{CONNECTION, HOST, SEC_WEBSOCKET_KEY, SEC_WEBSOCKET_VERSION, UPGRADE}; +use httparse::Header; use hyper::service::Service; use hyper_unix_connector::{UnixClient, Uri, UDS}; use log::debug; +use rand::{thread_rng, Rng}; use snafu::{ensure, ResultExt}; use std::path::Path; use tokio_tungstenite::{client_async, tungstenite::http::StatusCode, WebSocketStream}; @@ -37,6 +41,32 @@ where .build() })?; + // The base64 websocket key for the connection + let ws_key = engine::general_purpose::STANDARD_NO_PAD.encode(thread_rng().gen::<[u8; 16]>()); + // Create the headers required for a valid client handshake and websocket upgrade request + let mut headers = [ + Header { + name: HOST.as_str(), + value: "localhost".as_bytes(), + }, + Header { + name: CONNECTION.as_str(), + value: "Upgrade".as_bytes(), + }, + Header { + name: UPGRADE.as_str(), + value: "websocket".as_bytes(), + }, + Header { + name: SEC_WEBSOCKET_VERSION.as_str(), + value: "13".as_bytes(), + }, + Header { + name: SEC_WEBSOCKET_KEY.as_str(), + value: ws_key.as_bytes(), + }, + ]; + // Create a request object that tokio-tungstenite understands, pointed at a local WebSocket // URI. This is used to create the WebSocket client. let ws_uri = format!("ws://localhost{}", path); @@ -44,7 +74,7 @@ where method: Some("GET"), path: Some(&ws_uri), version: Some(1), // HTTP/1.1 - headers: &mut [], + headers: &mut headers, }; // Now we can use tokio-tungstenite to upgrade the connection to a WebSocket. We get back a diff --git a/sources/deny.toml b/sources/deny.toml index 1f1c1e3fc23..7a47c10e055 100644 --- a/sources/deny.toml +++ b/sources/deny.toml @@ -65,8 +65,6 @@ skip = [ ] skip-tree = [ - # tungstenite is using an older sha-1 - { name = "tungstenite", version = "=0.16" }, # windows-sys is not a direct dependency. mio and schannel # are using different versions of windows-sys. we skip the # dependency tree because windows-sys has many sub-crates @@ -78,7 +76,10 @@ skip-tree = [ # serde_yaml actually uses a newer hashbrown dependency, # but several crates in the graph pull in an older one, so skip for now # until they can be updated - { name = "hashbrown", version = "=0.13.2" } + { name = "hashbrown", version = "=0.13.2" }, + # tungstenite uses a newer version of base64, but many of the + # first party crates are still in this version + { name = "base64", version = "=0.13.1" } ] [sources]