diff --git a/Cargo.lock b/Cargo.lock
index 06565342f7..67098e798e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -486,6 +486,14 @@ dependencies = [
"typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "generic-array"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "getrandom"
version = "0.1.13"
@@ -1132,8 +1140,7 @@ dependencies = [
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1522,6 +1529,7 @@ dependencies = [
"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76"
"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d"
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
+"checksum generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7"
diff --git a/sqlx-core/Cargo.toml b/sqlx-core/Cargo.toml
index af32dd2da5..a2798821be 100644
--- a/sqlx-core/Cargo.toml
+++ b/sqlx-core/Cargo.toml
@@ -15,7 +15,7 @@ authors = [
[features]
default = []
unstable = []
-postgres = [ "md-5", "sha2", "base64", "sha-1", "rand" ]
+postgres = [ "md-5", "sha2", "base64", "sha-1", "rand", "hmac" ]
mysql = [ "sha-1", "sha2", "generic-array", "num-bigint", "base64", "digest", "rand" ]
[dependencies]
@@ -28,7 +28,7 @@ chrono = { version = "0.4.10", default-features = false, features = [ "clock" ],
digest = { version = "0.8.1", default-features = false, optional = true, features = [ "std" ] }
futures-core = { version = "0.3.1", default-features = false }
futures-util = { version = "0.3.1", default-features = false }
-generic-array = { version = "0.12.3", default-features = false, optional = true }
+generic-array = { version = "0.13.2", default-features = false, optional = true }
log = { version = "0.4.8", default-features = false }
md-5 = { version = "0.8.0", default-features = false, optional = true }
memchr = { version = "2.2.1", default-features = false }
@@ -38,8 +38,7 @@ sha-1 = { version = "0.8.1", default-features = false, optional = true }
sha2 = { version = "0.8.0", default-features = false, optional = true }
url = { version = "2.1.0", default-features = false }
uuid = { version = "0.8.1", default-features = false, optional = true }
-hex = "0.4.0"
-hmac = "0.7.1"
+hmac = { version = "0.7.1", default-features = false, optional = true }
[dev-dependencies]
matches = "0.1.8"
diff --git a/sqlx-core/src/postgres/connection.rs b/sqlx-core/src/postgres/connection.rs
index f965cf28e6..14c17c2553 100644
--- a/sqlx-core/src/postgres/connection.rs
+++ b/sqlx-core/src/postgres/connection.rs
@@ -7,10 +7,16 @@ use futures_core::future::BoxFuture;
use crate::cache::StatementCache;
use crate::connection::Connection;
use crate::io::{Buf, BufStream};
-use crate::postgres::protocol::{self, Decode, Encode, Message, StatementId};
+use crate::postgres::protocol::{
+ self, hi, Authentication, Decode, Encode, Message, SaslInitialResponse, SaslResponse,
+ StatementId,
+};
use crate::postgres::PgError;
use crate::url::Url;
-use std::ops::Deref;
+use crate::Result;
+use hmac::{Hmac, Mac};
+use rand::Rng;
+use sha2::{Digest, Sha256};
/// An asynchronous connection to a [Postgres] database.
///
@@ -38,7 +44,7 @@ pub struct PgConnection {
impl PgConnection {
// https://www.postgresql.org/docs/12/protocol-flow.html#id-1.10.5.7.3
- async fn startup(&mut self, url: Url) -> crate::Result<()> {
+ async fn startup(&mut self, url: Url) -> Result<()> {
// Defaults to postgres@.../postgres
let username = url.username().unwrap_or("postgres");
let database = url.database().unwrap_or("postgres");
@@ -94,26 +100,20 @@ impl PgConnection {
}
protocol::Authentication::Sasl { mechanisms } => {
- let mechanism = (*mechanisms)
- .get(0)
- .ok_or(protocol_err!(
- "Expected mechanisms SCRAM-SHA-256, but received {:?}",
- mechanisms
- ))?
- .deref();
- if "SCRAM-SHA-256" == &*mechanism {
- protocol::sasl_auth(
- self,
- username,
- url.password().unwrap_or_default(),
- )
- .await
- } else {
- Err(protocol_err!(
- "Expected mechanisms SCRAM-SHA-256, but received {:?}",
- mechanisms
- ))?
- }?;
+ match mechanisms.get(0).map(|m| &**m) {
+ Some("SCRAM-SHA-256") => {
+ sasl_auth(self, username, url.password().unwrap_or_default())
+ .await?;
+ }
+
+ _ => {
+ return Err(protocol_err!(
+ "Expected mechanisms SCRAM-SHA-256, but received {:?}",
+ mechanisms
+ )
+ .into())
+ }
+ }
}
auth => {
@@ -146,7 +146,7 @@ impl PgConnection {
}
// https://www.postgresql.org/docs/devel/protocol-flow.html#id-1.10.5.7.10
- async fn terminate(mut self) -> crate::Result<()> {
+ async fn terminate(mut self) -> Result<()> {
protocol::Terminate.encode(self.stream.buffer_mut());
self.stream.flush().await?;
@@ -156,7 +156,7 @@ impl PgConnection {
}
// Wait and return the next message to be received from Postgres.
- pub(super) async fn receive(&mut self) -> crate::Result