mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-08 22:12:56 +00:00
proxy: decode username and password (#6700)
## Problem usernames and passwords can be URL 'percent' encoded in the connection string URL provided by serverless driver. ## Summary of changes Decode the parameters when getting conn info
This commit is contained in:
@@ -60,6 +60,8 @@ scopeguard.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
sha2.workspace = true
|
||||
smol_str.workspace = true
|
||||
smallvec.workspace = true
|
||||
socket2.workspace = true
|
||||
sync_wrapper.workspace = true
|
||||
task-local-extensions.workspace = true
|
||||
@@ -76,6 +78,7 @@ tracing-subscriber.workspace = true
|
||||
tracing-utils.workspace = true
|
||||
tracing.workspace = true
|
||||
url.workspace = true
|
||||
urlencoding.workspace = true
|
||||
utils.workspace = true
|
||||
uuid.workspace = true
|
||||
webpki-roots.workspace = true
|
||||
@@ -84,7 +87,6 @@ native-tls.workspace = true
|
||||
postgres-native-tls.workspace = true
|
||||
postgres-protocol.workspace = true
|
||||
redis.workspace = true
|
||||
smol_str.workspace = true
|
||||
|
||||
workspace_hack.workspace = true
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ impl PoolingBackend {
|
||||
}
|
||||
};
|
||||
let auth_outcome =
|
||||
crate::auth::validate_password_and_exchange(conn_info.password.as_bytes(), secret)?;
|
||||
crate::auth::validate_password_and_exchange(&conn_info.password, secret)?;
|
||||
match auth_outcome {
|
||||
crate::sasl::Outcome::Success(key) => Ok(key),
|
||||
crate::sasl::Outcome::Failure(reason) => {
|
||||
|
||||
@@ -3,6 +3,7 @@ use futures::{future::poll_fn, Future};
|
||||
use metrics::IntCounterPairGuard;
|
||||
use parking_lot::RwLock;
|
||||
use rand::Rng;
|
||||
use smallvec::SmallVec;
|
||||
use smol_str::SmolStr;
|
||||
use std::{collections::HashMap, pin::pin, sync::Arc, sync::Weak, time::Duration};
|
||||
use std::{
|
||||
@@ -36,7 +37,7 @@ pub const APP_NAME: SmolStr = SmolStr::new_inline("/sql_over_http");
|
||||
pub struct ConnInfo {
|
||||
pub user_info: ComputeUserInfo,
|
||||
pub dbname: DbName,
|
||||
pub password: SmolStr,
|
||||
pub password: SmallVec<[u8; 16]>,
|
||||
}
|
||||
|
||||
impl ConnInfo {
|
||||
@@ -731,7 +732,7 @@ mod tests {
|
||||
options: Default::default(),
|
||||
},
|
||||
dbname: "dbname".into(),
|
||||
password: "password".into(),
|
||||
password: "password".as_bytes().into(),
|
||||
};
|
||||
let ep_pool =
|
||||
Arc::downgrade(&pool.get_or_create_endpoint_pool(&conn_info.endpoint_cache_key()));
|
||||
@@ -788,7 +789,7 @@ mod tests {
|
||||
options: Default::default(),
|
||||
},
|
||||
dbname: "dbname".into(),
|
||||
password: "password".into(),
|
||||
password: "password".as_bytes().into(),
|
||||
};
|
||||
let ep_pool =
|
||||
Arc::downgrade(&pool.get_or_create_endpoint_pool(&conn_info.endpoint_cache_key()));
|
||||
|
||||
@@ -100,6 +100,8 @@ pub enum ConnInfoError {
|
||||
InvalidDbName,
|
||||
#[error("missing username")]
|
||||
MissingUsername,
|
||||
#[error("invalid username: {0}")]
|
||||
InvalidUsername(#[from] std::string::FromUtf8Error),
|
||||
#[error("missing password")]
|
||||
MissingPassword,
|
||||
#[error("missing hostname")]
|
||||
@@ -134,7 +136,7 @@ fn get_conn_info(
|
||||
|
||||
let dbname = url_path.next().ok_or(ConnInfoError::InvalidDbName)?;
|
||||
|
||||
let username = RoleName::from(connection_url.username());
|
||||
let username = RoleName::from(urlencoding::decode(connection_url.username())?);
|
||||
if username.is_empty() {
|
||||
return Err(ConnInfoError::MissingUsername);
|
||||
}
|
||||
@@ -143,6 +145,7 @@ fn get_conn_info(
|
||||
let password = connection_url
|
||||
.password()
|
||||
.ok_or(ConnInfoError::MissingPassword)?;
|
||||
let password = urlencoding::decode_binary(password.as_bytes());
|
||||
|
||||
let hostname = connection_url
|
||||
.host_str()
|
||||
@@ -172,7 +175,10 @@ fn get_conn_info(
|
||||
Ok(ConnInfo {
|
||||
user_info,
|
||||
dbname: dbname.into(),
|
||||
password: password.into(),
|
||||
password: match password {
|
||||
std::borrow::Cow::Borrowed(b) => b.into(),
|
||||
std::borrow::Cow::Owned(b) => b.into(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user