From dec0b97a0df91fa4156f8e3b79ffd52f978937cb Mon Sep 17 00:00:00 2001 From: Nicolas SEYS Date: Tue, 26 Sep 2023 11:33:42 +0200 Subject: [PATCH 1/4] Fix redirection with a relative location --- warpgate-protocol-http/Cargo.toml | 1 + warpgate-protocol-http/src/proxy.rs | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/warpgate-protocol-http/Cargo.toml b/warpgate-protocol-http/Cargo.toml index 18239e969..7f8fe03c8 100644 --- a/warpgate-protocol-http/Cargo.toml +++ b/warpgate-protocol-http/Cargo.toml @@ -39,3 +39,4 @@ warpgate-sso = { version = "*", path = "../warpgate-sso" } percent-encoding = "2.1" uuid = { version = "1.2", features = ["v4"] } regex = "1.6" +url = "2.4.1" diff --git a/warpgate-protocol-http/src/proxy.rs b/warpgate-protocol-http/src/proxy.rs index 127d6fe54..5cb2990ab 100644 --- a/warpgate-protocol-http/src/proxy.rs +++ b/warpgate-protocol-http/src/proxy.rs @@ -14,6 +14,7 @@ use poem::web::websocket::{Message, WebSocket}; use poem::{Body, IntoResponse, Request, Response}; use tokio_tungstenite::{connect_async_with_config, tungstenite}; use tracing::*; +use url::Url; use warpgate_common::{try_block, TargetHTTPOptions, TlsMode, WarpgateError}; use warpgate_web::lookup_built_file; @@ -149,12 +150,18 @@ fn rewrite_request(mut req: B, options: &TargetHTTPOption Ok(req) } -fn rewrite_response(resp: &mut Response, options: &TargetHTTPOptions) -> Result<()> { +fn rewrite_response( + resp: &mut Response, + options: &TargetHTTPOptions, + source_uri: &Uri, +) -> Result<()> { let target_uri = Uri::try_from(options.url.clone())?; let headers = resp.headers_mut(); if let Some(value) = headers.get_mut(http::header::LOCATION) { - let redirect_uri = Uri::try_from(value.as_bytes())?; + let location = Url::parse(&source_uri.to_string())?.join(value.to_str()?)?; + let redirect_uri = Uri::try_from(location.to_string())?; + if redirect_uri.authority() == target_uri.authority() { let old_value = value.clone(); *value = Uri::builder() @@ -285,7 +292,7 @@ pub async fn proxy_normal_request( log_request_result(req.method(), req.original_uri(), &status); - rewrite_response(&mut response, options)?; + rewrite_response(&mut response, options, &uri)?; Ok(response) } @@ -470,6 +477,6 @@ async fn proxy_ws_inner( .into_response(); copy_client_response(&client_response, &mut response); - rewrite_response(&mut response, options)?; + rewrite_response(&mut response, options, &uri)?; Ok(response) } From 1cdd29b6b8e6a1366e5431512f0011a36a6ab148 Mon Sep 17 00:00:00 2001 From: Eugene Date: Tue, 26 Sep 2023 15:53:25 +0200 Subject: [PATCH 2/4] bumped Docker build image --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b170522d9..25c32ee13 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1.3-labs -FROM rust:1.64.0-bullseye AS build +FROM rust:1.72.1-bullseye AS build ENV DEBIAN_FRONTEND noninteractive From a4df7f7a21395cfaee7a9789d1e3846290caeb63 Mon Sep 17 00:00:00 2001 From: Eugene Date: Wed, 27 Sep 2023 21:14:41 +0200 Subject: [PATCH 3/4] fixed GHSA-3cjp-w4cp-m9c8 - interpreting SSH public key offers as a successful authentication --- Cargo.lock | 45 +++++----- warpgate-protocol-ssh/Cargo.toml | 2 +- .../src/server/russh_handler.rs | 28 +++++++ warpgate-protocol-ssh/src/server/session.rs | 83 ++++++++++++++++--- 4 files changed, 122 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b658e577..2f1611f08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1473,9 +1473,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -2057,9 +2057,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2978,9 +2978,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "phf" @@ -3625,9 +3625,9 @@ dependencies = [ [[package]] name = "russh" -version = "0.38.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae0efcc0f4cd6c062c07e572ce4b806e3967fa029fcbfcc0aa98fb5910a37925" +checksum = "7878311587d0353a854d5be954fbe68bdf6e77873933b484d1e45db12bb2f8cf" dependencies = [ "aes", "aes-gcm", @@ -5162,9 +5162,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -5256,7 +5256,7 @@ dependencies = [ [[package]] name = "warpgate" -version = "0.7.4" +version = "0.8.0" dependencies = [ "ansi_term", "anyhow", @@ -5292,7 +5292,7 @@ dependencies = [ [[package]] name = "warpgate-admin" -version = "0.7.4" +version = "0.8.0" dependencies = [ "anyhow", "async-trait", @@ -5321,7 +5321,7 @@ dependencies = [ [[package]] name = "warpgate-common" -version = "0.7.4" +version = "0.8.0" dependencies = [ "anyhow", "argon2", @@ -5357,7 +5357,7 @@ dependencies = [ [[package]] name = "warpgate-core" -version = "0.7.4" +version = "0.8.0" dependencies = [ "anyhow", "argon2", @@ -5397,7 +5397,7 @@ dependencies = [ [[package]] name = "warpgate-database-protocols" -version = "0.7.4" +version = "0.8.0" dependencies = [ "bitflags 1.3.2", "bytes", @@ -5410,7 +5410,7 @@ dependencies = [ [[package]] name = "warpgate-db-entities" -version = "0.7.4" +version = "0.8.0" dependencies = [ "chrono", "poem-openapi", @@ -5423,7 +5423,7 @@ dependencies = [ [[package]] name = "warpgate-db-migrations" -version = "0.7.4" +version = "0.8.0" dependencies = [ "async-std", "chrono", @@ -5435,7 +5435,7 @@ dependencies = [ [[package]] name = "warpgate-protocol-http" -version = "0.7.4" +version = "0.8.0" dependencies = [ "anyhow", "async-trait", @@ -5456,6 +5456,7 @@ dependencies = [ "tokio", "tokio-tungstenite 0.17.2", "tracing", + "url", "uuid", "warpgate-admin", "warpgate-common", @@ -5467,7 +5468,7 @@ dependencies = [ [[package]] name = "warpgate-protocol-mysql" -version = "0.7.4" +version = "0.8.0" dependencies = [ "anyhow", "async-trait", @@ -5494,7 +5495,7 @@ dependencies = [ [[package]] name = "warpgate-protocol-ssh" -version = "0.7.4" +version = "0.8.0" dependencies = [ "ansi_term", "anyhow", @@ -5519,7 +5520,7 @@ dependencies = [ [[package]] name = "warpgate-sso" -version = "0.7.4" +version = "0.8.0" dependencies = [ "bytes", "data-encoding", @@ -5535,7 +5536,7 @@ dependencies = [ [[package]] name = "warpgate-web" -version = "0.7.4" +version = "0.8.0" dependencies = [ "rust-embed", "serde", diff --git a/warpgate-protocol-ssh/Cargo.toml b/warpgate-protocol-ssh/Cargo.toml index cb2bc7a62..c3c9d3e68 100644 --- a/warpgate-protocol-ssh/Cargo.toml +++ b/warpgate-protocol-ssh/Cargo.toml @@ -12,7 +12,7 @@ bimap = "0.6" bytes = "1.3" dialoguer = "0.10" futures = "0.3" -russh = { version = "0.38.0", features = ["vendored-openssl"] } +russh = { version = "0.39.0", features = ["vendored-openssl"] } # russh = { version = "0.35.0-beta.6", features = ["vendored-openssl"], path = "../../russh/russh"} russh-keys = { version = "0.38.0", features = ["vendored-openssl"] } # russh-keys = { version = "0.23.0-beta.1", features = ["vendored-openssl"], path = "../../russh/russh-keys" } diff --git a/warpgate-protocol-ssh/src/server/russh_handler.rs b/warpgate-protocol-ssh/src/server/russh_handler.rs index a3f3ccbfc..7dc0eb7d9 100644 --- a/warpgate-protocol-ssh/src/server/russh_handler.rs +++ b/warpgate-protocol-ssh/src/server/russh_handler.rs @@ -29,6 +29,7 @@ pub enum ServerHandlerEvent { PtyRequest(ServerChannelId, PtyRequest, oneshot::Sender<()>), ShellRequest(ServerChannelId, oneshot::Sender), AuthPublicKey(Secret, PublicKey, oneshot::Sender), + AuthPublicKeyOffer(Secret, PublicKey, oneshot::Sender), AuthPassword(Secret, Secret, oneshot::Sender), AuthKeyboardInteractive( Secret, @@ -178,6 +179,33 @@ impl russh::server::Handler for ServerHandler { Ok((self, session)) } + async fn auth_publickey_offered( + self, + user: &str, + key: &russh_keys::key::PublicKey, + ) -> Result<(Self, Auth), Self::Error> { + let user = Secret::new(user.to_string()); + let (tx, rx) = oneshot::channel(); + + self.send_event(ServerHandlerEvent::AuthPublicKeyOffer( + user, + key.clone(), + tx, + ))?; + + let result = rx.await.unwrap_or(false); + Ok(( + self, + if result { + Auth::Accept + } else { + Auth::Reject { + proceed_with_methods: None, + } + }, + )) + } + async fn auth_publickey( self, user: &str, diff --git a/warpgate-protocol-ssh/src/server/session.rs b/warpgate-protocol-ssh/src/server/session.rs index cff6b9ab3..5158537c8 100644 --- a/warpgate-protocol-ssh/src/server/session.rs +++ b/warpgate-protocol-ssh/src/server/session.rs @@ -466,6 +466,10 @@ impl ServerSession { let _ = reply.send(self._auth_publickey(username, key).await); } + ServerHandlerEvent::AuthPublicKeyOffer(username, key, reply) => { + let _ = reply.send(self._auth_publickey_offer(username, key).await); + } + ServerHandlerEvent::AuthPassword(username, password, reply) => { let _ = reply.send(self._auth_password(username, password).await); } @@ -1149,19 +1153,7 @@ impl ServerSession { .map_err(anyhow::Error::from) } - async fn _auth_publickey( - &mut self, - ssh_username: Secret, - key: PublicKey, - ) -> russh::server::Auth { - let selector: AuthSelector = ssh_username.expose_secret().into(); - - info!( - "Public key auth as {:?} with key {}", - selector, - key.public_key_base64() - ); - + fn _get_public_keys_from_of(&self, key: PublicKey) -> Vec { let mut keys = vec![key.clone()]; // Try all supported hash algorithms if let PublicKey::RSA { key, hash } = &key { @@ -1178,6 +1170,48 @@ impl ServerSession { } } } + keys + } + + async fn _auth_publickey_offer( + &mut self, + ssh_username: Secret, + key: PublicKey, + ) -> bool { + let keys = self._get_public_keys_from_of(key); + let selector: AuthSelector = ssh_username.expose_secret().into(); + + for key in keys { + if let Ok(true) = self + .try_validate_public_key_offer( + &selector, + Some(AuthCredential::PublicKey { + kind: key.name().to_string(), + public_key_bytes: Bytes::from(key.public_key_bytes()), + }), + ) + .await + { + return true; + } + } + false + } + + async fn _auth_publickey( + &mut self, + ssh_username: Secret, + key: PublicKey, + ) -> russh::server::Auth { + let selector: AuthSelector = ssh_username.expose_secret().into(); + + info!( + "Public key auth as {:?} with key {}", + selector, + key.public_key_base64() + ); + + let keys = self._get_public_keys_from_of(key); let mut result = Ok(AuthResult::Rejected); for key in keys { @@ -1361,6 +1395,29 @@ impl ServerSession { m } + async fn try_validate_public_key_offer( + &mut self, + selector: &AuthSelector, + credential: Option, + ) -> Result { + match selector { + AuthSelector::User { username, .. } => { + let cp = self.services.config_provider.clone(); + + if let Some(credential) = credential { + return Ok(cp + .lock() + .await + .validate_credential(username, &credential) + .await?); + } + + Ok(false) + } + _ => Ok(false), + } + } + async fn try_auth( &mut self, selector: &AuthSelector, From 8b91e4a328d54b30ce0b9b994c1eada833f886de Mon Sep 17 00:00:00 2001 From: Eugene Date: Wed, 27 Sep 2023 22:09:03 +0200 Subject: [PATCH 4/4] =?UTF-8?q?Bump=20version:=200.8.0=20=E2=86=92=200.8.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- warpgate-admin/Cargo.toml | 2 +- warpgate-common/Cargo.toml | 2 +- warpgate-core/Cargo.toml | 2 +- warpgate-database-protocols/Cargo.toml | 2 +- warpgate-db-entities/Cargo.toml | 2 +- warpgate-db-migrations/Cargo.toml | 2 +- warpgate-protocol-http/Cargo.toml | 2 +- warpgate-protocol-mysql/Cargo.toml | 2 +- warpgate-protocol-ssh/Cargo.toml | 2 +- warpgate-sso/Cargo.toml | 2 +- warpgate-web/Cargo.toml | 2 +- warpgate/Cargo.toml | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index b6f09a8fb..183c2c085 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.8.0 +current_version = 0.8.1 commit = True tag = True diff --git a/warpgate-admin/Cargo.toml b/warpgate-admin/Cargo.toml index b43484b5b..6d687b980 100644 --- a/warpgate-admin/Cargo.toml +++ b/warpgate-admin/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-admin" -version = "0.8.0" +version = "0.8.1" [dependencies] anyhow = { version = "1.0", features = ["std"] } diff --git a/warpgate-common/Cargo.toml b/warpgate-common/Cargo.toml index b88cf6d17..faf4cad97 100644 --- a/warpgate-common/Cargo.toml +++ b/warpgate-common/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-common" -version = "0.8.0" +version = "0.8.1" [dependencies] anyhow = "1.0" diff --git a/warpgate-core/Cargo.toml b/warpgate-core/Cargo.toml index 70058fa8c..fb91dbcba 100644 --- a/warpgate-core/Cargo.toml +++ b/warpgate-core/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-core" -version = "0.8.0" +version = "0.8.1" [dependencies] warpgate-common = { version = "*", path = "../warpgate-common" } diff --git a/warpgate-database-protocols/Cargo.toml b/warpgate-database-protocols/Cargo.toml index aae58387d..ba129c9ff 100644 --- a/warpgate-database-protocols/Cargo.toml +++ b/warpgate-database-protocols/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "warpgate-database-protocols" -version = "0.8.0" +version = "0.8.1" description = "Core of SQLx, the rust SQL toolkit. Just the database protocol parts." license = "MIT OR Apache-2.0" edition = "2021" diff --git a/warpgate-db-entities/Cargo.toml b/warpgate-db-entities/Cargo.toml index 269ca72e5..42571ef59 100644 --- a/warpgate-db-entities/Cargo.toml +++ b/warpgate-db-entities/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-db-entities" -version = "0.8.0" +version = "0.8.1" [dependencies] chrono = { version = "0.4", default_features = false, features = ["serde"] } diff --git a/warpgate-db-migrations/Cargo.toml b/warpgate-db-migrations/Cargo.toml index 6093c79bb..e5defffc6 100644 --- a/warpgate-db-migrations/Cargo.toml +++ b/warpgate-db-migrations/Cargo.toml @@ -3,7 +3,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-db-migrations" publish = false -version = "0.8.0" +version = "0.8.1" [lib] diff --git a/warpgate-protocol-http/Cargo.toml b/warpgate-protocol-http/Cargo.toml index 7f8fe03c8..cba81bc60 100644 --- a/warpgate-protocol-http/Cargo.toml +++ b/warpgate-protocol-http/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-protocol-http" -version = "0.8.0" +version = "0.8.1" [dependencies] anyhow = "1.0" diff --git a/warpgate-protocol-mysql/Cargo.toml b/warpgate-protocol-mysql/Cargo.toml index 8de6c6817..e2d4f94f6 100644 --- a/warpgate-protocol-mysql/Cargo.toml +++ b/warpgate-protocol-mysql/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-protocol-mysql" -version = "0.8.0" +version = "0.8.1" [dependencies] warpgate-common = { version = "*", path = "../warpgate-common" } diff --git a/warpgate-protocol-ssh/Cargo.toml b/warpgate-protocol-ssh/Cargo.toml index c3c9d3e68..847c19dc0 100644 --- a/warpgate-protocol-ssh/Cargo.toml +++ b/warpgate-protocol-ssh/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-protocol-ssh" -version = "0.8.0" +version = "0.8.1" [dependencies] ansi_term = "0.12" diff --git a/warpgate-sso/Cargo.toml b/warpgate-sso/Cargo.toml index 04b7154f5..2db3b306d 100644 --- a/warpgate-sso/Cargo.toml +++ b/warpgate-sso/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-sso" -version = "0.8.0" +version = "0.8.1" [dependencies] bytes = "1.3" diff --git a/warpgate-web/Cargo.toml b/warpgate-web/Cargo.toml index a8e7402d1..af153fbbf 100644 --- a/warpgate-web/Cargo.toml +++ b/warpgate-web/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate-web" -version = "0.8.0" +version = "0.8.1" [dependencies] rust-embed = "6.3" diff --git a/warpgate/Cargo.toml b/warpgate/Cargo.toml index 0857d1190..9fcef6bed 100644 --- a/warpgate/Cargo.toml +++ b/warpgate/Cargo.toml @@ -2,7 +2,7 @@ edition = "2021" license = "Apache-2.0" name = "warpgate" -version = "0.8.0" +version = "0.8.1" [dependencies] ansi_term = "0.12"