mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-29 21:00:54 +00:00
Merge pull request #41 from launchbadge/ab/tls
implement TLS for Postgres and MySQL
This commit is contained in:
commit
684068aa9e
11
.github/workflows/mysql.yml
vendored
11
.github/workflows/mysql.yml
vendored
@ -25,7 +25,10 @@ jobs:
|
||||
# will assign a random free host port
|
||||
- 3306/tcp
|
||||
# needed because the container does not provide a healthcheck
|
||||
options: --health-cmd "mysqladmin ping --silent" --health-interval 30s --health-timeout 30s --health-retries 10
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping --silent" --health-interval 30s --health-timeout 30s
|
||||
--health-retries 10 -v /data/mysql:/var/lib/mysql
|
||||
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
@ -48,9 +51,11 @@ jobs:
|
||||
|
||||
# -----------------------------------------------------
|
||||
|
||||
- run: cargo test -p sqlx --no-default-features --features 'mysql macros chrono'
|
||||
- run: cargo test -p sqlx --no-default-features --features 'mysql macros chrono tls'
|
||||
env:
|
||||
DATABASE_URL: mysql://root:password@localhost:${{ job.services.mysql.ports[3306] }}/sqlx
|
||||
# pass the path to the CA that the MySQL service generated
|
||||
# Github Actions' YML parser doesn't handle multiline strings correctly
|
||||
DATABASE_URL: mysql://root:password@localhost:${{ job.services.mysql.ports[3306] }}/sqlx?ssl-mode=VERIFY_CA&ssl-ca=%2Fdata%2Fmysql%2Fca.pem
|
||||
|
||||
# Rust ------------------------------------------------
|
||||
|
||||
|
||||
3
.github/workflows/postgres.yml
vendored
3
.github/workflows/postgres.yml
vendored
@ -49,6 +49,9 @@ jobs:
|
||||
|
||||
# -----------------------------------------------------
|
||||
|
||||
# Check that we build with TLS support (TODO: we need a postgres image with SSL certs to test)
|
||||
- run: cargo check -p sqlx-core --no-default-features --features 'postgres macros uuid chrono tls'
|
||||
|
||||
- run: cargo test -p sqlx --no-default-features --features 'postgres macros uuid chrono'
|
||||
env:
|
||||
DATABASE_URL: postgres://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/postgres
|
||||
|
||||
181
Cargo.lock
generated
181
Cargo.lock
generated
@ -32,6 +32,16 @@ dependencies = [
|
||||
"syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-native-tls"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-std"
|
||||
version = "1.4.0"
|
||||
@ -247,6 +257,20 @@ name = "constant_time_eq"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.4.0"
|
||||
@ -376,6 +400,19 @@ name = "fnv"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
@ -831,6 +868,23 @@ dependencies = [
|
||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.33"
|
||||
@ -887,6 +941,36 @@ name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.9.0"
|
||||
@ -931,6 +1015,11 @@ name = "pin-utils"
|
||||
version = "0.1.0-alpha.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.6"
|
||||
@ -1030,6 +1119,14 @@ name = "regex-syntax"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.14.6"
|
||||
@ -1077,11 +1174,39 @@ name = "ryu"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
@ -1186,6 +1311,7 @@ dependencies = [
|
||||
"anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1197,6 +1323,7 @@ dependencies = [
|
||||
name = "sqlx-core"
|
||||
version = "0.1.4"
|
||||
dependencies = [
|
||||
"async-native-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"async-stream 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1278,6 +1405,19 @@ dependencies = [
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.0.5"
|
||||
@ -1286,6 +1426,24 @@ dependencies = [
|
||||
"wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.0"
|
||||
@ -1496,6 +1654,11 @@ name = "uuid"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.1.5"
|
||||
@ -1577,6 +1740,7 @@ dependencies = [
|
||||
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
|
||||
"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||
"checksum async-attributes 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "efd3d156917d94862e779f356c5acae312b08fd3121e792c857d7928c8088423"
|
||||
"checksum async-native-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d40a615e861c981117e15c28c577daf9918cabd2e2d588a5e06811ae79c9da1a"
|
||||
"checksum async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bf6039b315300e057d198b9d3ab92ee029e31c759b7f1afae538145e6f18a3e"
|
||||
"checksum async-stream 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58982858be7540a465c790b95aaea6710e5139bf8956b1d1344d014fa40100b0"
|
||||
"checksum async-stream-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393356ed99aa7bff0ac486dde592633b83ab02bd254d8c209d5b9f1d0f533480"
|
||||
@ -1602,6 +1766,8 @@ dependencies = [
|
||||
"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
|
||||
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
|
||||
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
||||
"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
|
||||
"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
|
||||
"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
|
||||
@ -1618,6 +1784,8 @@ dependencies = [
|
||||
"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
|
||||
@ -1669,6 +1837,7 @@ dependencies = [
|
||||
"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
|
||||
"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e"
|
||||
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||
"checksum num-bigint 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f115de20ad793e857f76da2563ff4a09fbcfd6fe93cca0c5d996ab5f3ee38d"
|
||||
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
|
||||
@ -1676,12 +1845,16 @@ dependencies = [
|
||||
"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72"
|
||||
"checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed"
|
||||
"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585"
|
||||
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
||||
"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f"
|
||||
"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
|
||||
"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
"checksum pin-project-lite 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e8822eb8bb72452f038ebf6048efa02c3fe22bf83f76519c9583e47fc194a422"
|
||||
"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
|
||||
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
|
||||
"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e"
|
||||
@ -1695,13 +1868,17 @@ dependencies = [
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
"checksum regex 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5508c1941e4e7cb19965abef075d35a9a8b5cdf0846f30b4050e9b55dc55e87"
|
||||
"checksum regex-syntax 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e734e891f5b408a29efbf8309e656876276f49ab6a6ac208600b4419bd893d90"
|
||||
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||
"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c"
|
||||
"checksum route-recognizer 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ea509065eb0b3c446acdd0102f0d46567dc30902dc0be91d6552035d92b0f4f8"
|
||||
"checksum rust-argon2 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "416f5109bdd413cec4f04c029297838e7604c993f8d1483b1d438f23bdc3eb35"
|
||||
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
||||
"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021"
|
||||
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
|
||||
"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df"
|
||||
"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
|
||||
@ -1717,7 +1894,10 @@ dependencies = [
|
||||
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
|
||||
"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
|
||||
"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
|
||||
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||
"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
|
||||
"checksum thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f357d1814b33bc2dc221243f8424104bfe72dbe911d5b71b3816a2dff1c977e"
|
||||
"checksum thiserror-impl 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2e25d25307eb8436894f727aba8f65d07adf02e5b35a13cebed48bd282bfef"
|
||||
"checksum thread_local 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88ddf1ad580c7e3d1efff877d972bcc93f995556b9087a5a259630985c88ceab"
|
||||
"checksum tide 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13c99b1991db81e611a2614cd1b07fec89ae33c5f755e1f8eb70826fb5af0eea"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
@ -1739,6 +1919,7 @@ dependencies = [
|
||||
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
|
||||
"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
|
||||
"checksum uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
|
||||
"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
|
||||
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||
"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230"
|
||||
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
@ -30,6 +30,7 @@ all-features = true
|
||||
[features]
|
||||
default = [ "macros" ]
|
||||
macros = [ "sqlx-macros", "proc-macro-hack" ]
|
||||
tls = ["sqlx-core/tls"]
|
||||
|
||||
# database
|
||||
postgres = [ "sqlx-core/postgres", "sqlx-macros/postgres" ]
|
||||
@ -48,6 +49,7 @@ hex = "0.4.0"
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0.26"
|
||||
futures = "0.3.1"
|
||||
env_logger = "0.7"
|
||||
async-std = { version = "1.4.0", features = [ "attributes" ] }
|
||||
dotenv = "0.15.0"
|
||||
|
||||
|
||||
@ -20,8 +20,10 @@ default = []
|
||||
unstable = []
|
||||
postgres = [ "md-5", "sha2", "base64", "sha-1", "rand", "hmac" ]
|
||||
mysql = [ "sha-1", "sha2", "generic-array", "num-bigint", "base64", "digest", "rand" ]
|
||||
tls = ["async-native-tls"]
|
||||
|
||||
[dependencies]
|
||||
async-native-tls = { version = "0.3", optional = true }
|
||||
async-std = "1.4.0"
|
||||
async-stream = { version = "0.2.0", default-features = false }
|
||||
base64 = { version = "0.11.0", default-features = false, optional = true, features = [ "std" ] }
|
||||
|
||||
@ -44,6 +44,9 @@ pub enum Error {
|
||||
/// [Pool::close] was called while we were waiting in [Pool::acquire].
|
||||
PoolClosed,
|
||||
|
||||
/// An error occurred during a TLS upgrade.
|
||||
TlsUpgrade(Box<dyn StdError + Send + Sync>),
|
||||
|
||||
Decode(DecodeError),
|
||||
|
||||
// TODO: Remove and replace with `#[non_exhaustive]` when possible
|
||||
@ -62,6 +65,8 @@ impl StdError for Error {
|
||||
|
||||
Error::Decode(DecodeError::Other(error)) => Some(&**error),
|
||||
|
||||
Error::TlsUpgrade(error) => Some(&**error),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -100,6 +105,8 @@ impl Display for Error {
|
||||
|
||||
Error::PoolClosed => f.write_str("attempted to acquire a connection on a closed pool"),
|
||||
|
||||
Error::TlsUpgrade(ref err) => write!(f, "error during TLS upgrade: {}", err),
|
||||
|
||||
Error::__Nonexhaustive => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -140,6 +147,21 @@ impl From<ProtocolError<'_>> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
impl From<async_native_tls::Error> for Error {
|
||||
#[inline]
|
||||
fn from(err: async_native_tls::Error) -> Self {
|
||||
Error::TlsUpgrade(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TlsError<'_>> for Error {
|
||||
#[inline]
|
||||
fn from(err: TlsError<'_>) -> Self {
|
||||
Error::TlsUpgrade(err.args.to_string().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Error
|
||||
where
|
||||
T: 'static + DatabaseError,
|
||||
@ -189,6 +211,15 @@ macro_rules! protocol_err (
|
||||
}
|
||||
);
|
||||
|
||||
pub(crate) struct TlsError<'a> {
|
||||
pub args: fmt::Arguments<'a>,
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! tls_err {
|
||||
($($args:tt)*) => { crate::error::TlsError { args: format_args!($($args)*)} };
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! impl_fmt_error {
|
||||
($err:ty) => {
|
||||
|
||||
@ -3,6 +3,7 @@ use async_std::io::{
|
||||
Read, Write,
|
||||
};
|
||||
use std::io;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
const RBUF_SIZE: usize = 8 * 1024;
|
||||
|
||||
@ -51,6 +52,12 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn clear_bufs(&mut self) {
|
||||
self.rbuf_rindex = 0;
|
||||
self.rbuf_windex = 0;
|
||||
self.wbuf.clear();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn consume(&mut self, cnt: usize) {
|
||||
self.rbuf_rindex += cnt;
|
||||
@ -118,6 +125,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Deref for BufStream<S> {
|
||||
type Target = S;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.stream
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> DerefMut for BufStream<S> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.stream
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Find a nicer way to do this
|
||||
// Return `Ok(None)` immediately from a function if the wrapped value is `None`
|
||||
#[allow(unused)]
|
||||
|
||||
@ -5,11 +5,14 @@ mod buf;
|
||||
mod buf_mut;
|
||||
mod byte_str;
|
||||
|
||||
mod tls;
|
||||
|
||||
pub use self::{
|
||||
buf::{Buf, ToBuf},
|
||||
buf_mut::BufMut,
|
||||
buf_stream::BufStream,
|
||||
byte_str::ByteStr,
|
||||
tls::MaybeTlsStream,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
126
sqlx-core/src/io/tls.rs
Normal file
126
sqlx-core/src/io/tls.rs
Normal file
@ -0,0 +1,126 @@
|
||||
use std::io::{IoSlice, IoSliceMut};
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use async_std::io::{self, Read, Write};
|
||||
use async_std::net::{Shutdown, TcpStream};
|
||||
|
||||
use crate::url::Url;
|
||||
|
||||
use self::Inner::*;
|
||||
|
||||
pub struct MaybeTlsStream {
|
||||
inner: Inner,
|
||||
}
|
||||
|
||||
enum Inner {
|
||||
NotTls(TcpStream),
|
||||
#[cfg(feature = "tls")]
|
||||
Tls(async_native_tls::TlsStream<TcpStream>),
|
||||
#[cfg(feature = "tls")]
|
||||
Upgrading,
|
||||
}
|
||||
|
||||
impl MaybeTlsStream {
|
||||
pub async fn connect(url: &Url, default_port: u16) -> crate::Result<Self> {
|
||||
let conn = TcpStream::connect((url.host(), url.port(default_port))).await?;
|
||||
Ok(Self {
|
||||
inner: Inner::NotTls(conn),
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_tls(&self) -> bool {
|
||||
match self.inner {
|
||||
Inner::NotTls(_) => false,
|
||||
#[cfg(feature = "tls")]
|
||||
Inner::Tls(_) => true,
|
||||
#[cfg(feature = "tls")]
|
||||
Inner::Upgrading => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
pub async fn upgrade(
|
||||
&mut self,
|
||||
url: &Url,
|
||||
connector: async_native_tls::TlsConnector,
|
||||
) -> crate::Result<()> {
|
||||
let conn = match std::mem::replace(&mut self.inner, Upgrading) {
|
||||
NotTls(conn) => conn,
|
||||
Tls(_) => return Err(tls_err!("connection already upgraded").into()),
|
||||
Upgrading => return Err(tls_err!("connection already failed to upgrade").into()),
|
||||
};
|
||||
|
||||
self.inner = Tls(connector.connect(url.host(), conn).await?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||
match self.inner {
|
||||
NotTls(ref conn) => conn.shutdown(how),
|
||||
#[cfg(feature = "tls")]
|
||||
Tls(ref conn) => conn.get_ref().shutdown(how),
|
||||
#[cfg(feature = "tls")]
|
||||
// connection already closed
|
||||
Upgrading => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! forward_pin (
|
||||
($self:ident.$method:ident($($arg:ident),*)) => (
|
||||
match &mut $self.inner {
|
||||
NotTls(ref mut conn) => Pin::new(conn).$method($($arg),*),
|
||||
#[cfg(feature = "tls")]
|
||||
Tls(ref mut conn) => Pin::new(conn).$method($($arg),*),
|
||||
#[cfg(feature = "tls")]
|
||||
Upgrading => Err(io::Error::new(io::ErrorKind::Other, "connection broken; TLS upgrade failed")).into(),
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
impl Read for MaybeTlsStream {
|
||||
fn poll_read(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
forward_pin!(self.poll_read(cx, buf))
|
||||
}
|
||||
|
||||
fn poll_read_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
bufs: &mut [IoSliceMut],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
forward_pin!(self.poll_read_vectored(cx, bufs))
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for MaybeTlsStream {
|
||||
fn poll_write(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
forward_pin!(self.poll_write(cx, buf))
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
|
||||
forward_pin!(self.poll_flush(cx))
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
|
||||
forward_pin!(self.poll_close(cx))
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
bufs: &[IoSlice],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
forward_pin!(self.poll_write_vectored(cx, bufs))
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,18 @@
|
||||
use std::convert::TryInto;
|
||||
use std::io;
|
||||
|
||||
use async_std::net::{Shutdown, TcpStream};
|
||||
use async_std::net::Shutdown;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use futures_core::future::BoxFuture;
|
||||
use sha1::Sha1;
|
||||
|
||||
use crate::cache::StatementCache;
|
||||
use crate::connection::Connection;
|
||||
use crate::io::{Buf, BufMut, BufStream};
|
||||
use crate::io::{Buf, BufMut, BufStream, MaybeTlsStream};
|
||||
use crate::mysql::error::MySqlError;
|
||||
use crate::mysql::protocol::{
|
||||
AuthPlugin, AuthSwitch, Capabilities, Decode, Encode, EofPacket, ErrPacket, Handshake,
|
||||
HandshakeResponse, OkPacket,
|
||||
HandshakeResponse, OkPacket, SslRequest,
|
||||
};
|
||||
use crate::mysql::rsa;
|
||||
use crate::mysql::util::xor_eq;
|
||||
@ -28,8 +28,64 @@ const COLLATE_UTF8MB4_UNICODE_CI: u8 = 224;
|
||||
/// The connection string expected by [Connection::open] should be a MySQL connection
|
||||
/// string, as documented at
|
||||
/// <https://dev.mysql.com/doc/refman/8.0/en/connecting-using-uri-or-key-value-pairs.html#connecting-using-uri>
|
||||
///
|
||||
/// ### TLS Support (requires `tls` feature)
|
||||
/// This connection type supports some of the same flags as the `mysql` CLI application for SSL
|
||||
/// connections, but they must be specified via the query segment of the connection string
|
||||
/// rather than as program arguments.
|
||||
///
|
||||
/// The same options for `--ssl-mode` are supported as the `ssl-mode` query parameter:
|
||||
/// <https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-mode>
|
||||
///
|
||||
/// ```text
|
||||
/// mysql://<user>[:<password>]@<host>[:<port>]/<database>[?ssl-mode=<ssl-mode>[&ssl-ca=<path>]]
|
||||
/// ```
|
||||
/// where
|
||||
/// ```text
|
||||
/// ssl-mode = DISABLED | PREFERRED | REQUIRED | VERIFY_CA | VERIFY_IDENTITY
|
||||
/// path = percent (URL) encoded path on the local machine
|
||||
/// ```
|
||||
///
|
||||
/// If the `tls` feature is not enabled, `ssl-mode=DISABLED` and `ssl-mode=PREFERRED` are no-ops and
|
||||
/// `ssl-mode=REQUIRED`, `ssl-mode=VERIFY_CA` and `ssl-mode=VERIFY_IDENTITY` are forbidden
|
||||
/// (attempting to connect with these will return an error).
|
||||
///
|
||||
/// If the `tls` feature is enabled, an upgrade to TLS is attempted on every connection by default
|
||||
/// (equivalent to `ssl-mode=PREFERRED`). If the server does not support TLS (because `--ssl=0` was
|
||||
/// passed to the server or an invalid certificate or key was used:
|
||||
/// <https://dev.mysql.com/doc/refman/8.0/en/using-encrypted-connections.html>)
|
||||
/// then it falls back to an unsecured connection and logs a warning.
|
||||
///
|
||||
/// Add `ssl-mode=REQUIRED` to your connection string to emit an error if the TLS upgrade fails.
|
||||
///
|
||||
/// However, like with `mysql` the server certificate is **not** checked for validity by default.
|
||||
///
|
||||
/// Specifying `ssl-mode=VERIFY_CA` will cause the TLS upgrade to verify the server's SSL
|
||||
/// certificate against a local CA root certificate; this is not the system root certificate
|
||||
/// but is instead expected to be specified as a local path with the `ssl-ca` query parameter
|
||||
/// (percent-encoded so the URL remains valid).
|
||||
///
|
||||
/// If you're running MySQL locally it might look something like this (for `VERIFY_CA`):
|
||||
/// ```text
|
||||
/// mysql://root:password@localhost/my_database?ssl-mode=VERIFY_CA&ssl-ca=%2Fvar%2Flib%2Fmysql%2Fca.pem
|
||||
/// ```
|
||||
///
|
||||
/// `%2F` is the percent-encoding for forward slash (`/`). In the example we give `/var/lib/mysql/ca.pem`
|
||||
/// as the CA certificate path, which is generated by the MySQL server automatically if
|
||||
/// no certificate is manually specified. Note that the path may vary based on the default `my.cnf`
|
||||
/// packaged with MySQL for your Linux distribution. Also note that unlike MySQL, MariaDB does *not*
|
||||
/// generate certificates automatically and they must always be passed in to enable TLS.
|
||||
///
|
||||
/// If `ssl-ca` is not specified or the file cannot be read, then an error is returned.
|
||||
/// `ssl-ca` implies `ssl-mode=VERIFY_CA` so you only actually need to specify the former
|
||||
/// but you may prefer having both to be more explicit.
|
||||
///
|
||||
/// If `ssl-mode=VERIFY_IDENTITY` is specified, in addition to checking the certificate as with
|
||||
/// `ssl-mode=VERIFY_CA`, the hostname in the connection string will be verified
|
||||
/// against the hostname in the server certificate, so they must be the same for the TLS
|
||||
/// upgrade to succeed. `ssl-ca` must still be specified.
|
||||
pub struct MySqlConnection {
|
||||
pub(super) stream: BufStream<TcpStream>,
|
||||
pub(super) stream: BufStream<MaybeTlsStream>,
|
||||
|
||||
// Active capabilities of the client _&_ the server
|
||||
pub(super) capabilities: Capabilities,
|
||||
@ -171,6 +227,10 @@ impl MySqlConnection {
|
||||
client_capabilities |= Capabilities::CONNECT_WITH_DB;
|
||||
}
|
||||
|
||||
if cfg!(feature = "tls") {
|
||||
client_capabilities |= Capabilities::SSL;
|
||||
}
|
||||
|
||||
self.capabilities =
|
||||
(client_capabilities & handshake.server_capabilities) | Capabilities::PROTOCOL_41;
|
||||
|
||||
@ -197,9 +257,7 @@ impl MySqlConnection {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl MySqlConnection {
|
||||
pub(crate) fn handle_ok(&mut self) -> crate::Result<OkPacket> {
|
||||
let ok = OkPacket::decode(self.packet())?;
|
||||
|
||||
@ -301,7 +359,14 @@ impl MySqlConnection {
|
||||
) -> crate::Result<Box<[u8]>> {
|
||||
// https://mariadb.com/kb/en/caching_sha2_password-authentication-plugin/
|
||||
|
||||
// TODO: Handle SSL
|
||||
if self.stream.is_tls() {
|
||||
// If in a TLS stream, send the password directly in clear text
|
||||
let mut clear_text = String::with_capacity(password.len() + 1);
|
||||
clear_text.push_str(password);
|
||||
clear_text.push('\0');
|
||||
|
||||
return Ok(clear_text.into_bytes().into_boxed_slice());
|
||||
}
|
||||
|
||||
// client sends a public key request
|
||||
self.send(&[public_key_request_id][..]).await?;
|
||||
@ -324,11 +389,17 @@ impl MySqlConnection {
|
||||
|
||||
impl MySqlConnection {
|
||||
async fn new(url: &Url) -> crate::Result<Self> {
|
||||
let stream = TcpStream::connect((url.host(), url.port(3306))).await?;
|
||||
let stream = MaybeTlsStream::connect(url, 3306).await?;
|
||||
|
||||
let mut capabilities = Capabilities::empty();
|
||||
|
||||
if cfg!(feature = "tls") {
|
||||
capabilities |= Capabilities::SSL;
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
stream: BufStream::new(stream),
|
||||
capabilities: Capabilities::empty(),
|
||||
capabilities,
|
||||
packet: Vec::with_capacity(8192),
|
||||
packet_len: 0,
|
||||
next_seq_no: 0,
|
||||
@ -372,6 +443,35 @@ impl MySqlConnection {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
async fn try_ssl(
|
||||
&mut self,
|
||||
url: &Url,
|
||||
ca_file: Option<&str>,
|
||||
invalid_hostnames: bool,
|
||||
) -> crate::Result<()> {
|
||||
use async_native_tls::{Certificate, TlsConnector};
|
||||
use async_std::fs;
|
||||
|
||||
let mut connector = TlsConnector::new()
|
||||
.danger_accept_invalid_certs(ca_file.is_none())
|
||||
.danger_accept_invalid_hostnames(invalid_hostnames);
|
||||
|
||||
if let Some(ca_file) = ca_file {
|
||||
let root_cert = fs::read(ca_file).await?;
|
||||
connector = connector.add_root_certificate(Certificate::from_pem(&root_cert)?);
|
||||
}
|
||||
|
||||
// send upgrade request and then immediately try TLS handshake
|
||||
self.send(SslRequest {
|
||||
client_collation: COLLATE_UTF8MB4_UNICODE_CI,
|
||||
max_packet_size: MAX_PACKET_SIZE,
|
||||
})
|
||||
.await?;
|
||||
|
||||
self.stream.stream.upgrade(url, connector).await
|
||||
}
|
||||
}
|
||||
|
||||
impl MySqlConnection {
|
||||
@ -383,7 +483,72 @@ impl MySqlConnection {
|
||||
// https://mariadb.com/kb/en/connection/
|
||||
|
||||
// On connect, server immediately sends the handshake
|
||||
let handshake = self_.receive_handshake(&url).await?;
|
||||
let mut handshake = self_.receive_handshake(&url).await?;
|
||||
|
||||
let ca_file = url.get_param("ssl-ca");
|
||||
|
||||
let ssl_mode = url.get_param("ssl-mode").unwrap_or(
|
||||
if ca_file.is_some() {
|
||||
"VERIFY_CA"
|
||||
} else {
|
||||
"PREFERRED"
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
|
||||
let supports_ssl = handshake.server_capabilities.contains(Capabilities::SSL);
|
||||
|
||||
match &*ssl_mode {
|
||||
"DISABLED" => (),
|
||||
|
||||
// don't try upgrade
|
||||
#[cfg(feature = "tls")]
|
||||
"PREFERRED" if !supports_ssl => {
|
||||
log::warn!("server does not support TLS; using unencrypted connection")
|
||||
}
|
||||
|
||||
// try to upgrade
|
||||
#[cfg(feature = "tls")]
|
||||
"PREFERRED" => {
|
||||
if let Err(e) = self_.try_ssl(&url, None, true).await {
|
||||
log::warn!("TLS handshake failed, falling back to insecure: {}", e);
|
||||
// fallback, redo connection
|
||||
self_ = Self::new(&url).await?;
|
||||
handshake = self_.receive_handshake(&url).await?;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tls"))]
|
||||
"PREFERRED" => log::info!("compiled without TLS, skipping upgrade"),
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
"REQUIRED" if !supports_ssl => {
|
||||
return Err(tls_err!("server does not support TLS").into())
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
"REQUIRED" => self_.try_ssl(&url, None, true).await?,
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
"VERIFY_CA" | "VERIFY_FULL" if ca_file.is_none() => {
|
||||
return Err(
|
||||
tls_err!("`ssl-mode` of {:?} requires `ssl-ca` to be set", ssl_mode).into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
"VERIFY_CA" | "VERIFY_FULL" => {
|
||||
self_
|
||||
.try_ssl(&url, ca_file.as_deref(), ssl_mode != "VERIFY_FULL")
|
||||
.await?
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tls"))]
|
||||
"REQUIRED" | "VERIFY_CA" | "VERIFY_FULL" => {
|
||||
return Err(tls_err!("compiled without TLS").into())
|
||||
}
|
||||
_ => return Err(tls_err!("unknown `ssl-mode` value: {:?}", ssl_mode).into()),
|
||||
}
|
||||
|
||||
// Pre-generate an auth response by using the auth method in the [Handshake]
|
||||
let password = url.password().unwrap_or_default();
|
||||
|
||||
@ -41,6 +41,7 @@ mod err;
|
||||
mod handshake_response;
|
||||
mod ok;
|
||||
mod row;
|
||||
mod ssl_request;
|
||||
|
||||
pub use auth_switch::AuthSwitch;
|
||||
pub use column_count::ColumnCount;
|
||||
@ -51,3 +52,4 @@ pub use err::ErrPacket;
|
||||
pub use handshake_response::HandshakeResponse;
|
||||
pub use ok::OkPacket;
|
||||
pub use row::Row;
|
||||
pub use ssl_request::SslRequest;
|
||||
|
||||
35
sqlx-core/src/mysql/protocol/ssl_request.rs
Normal file
35
sqlx-core/src/mysql/protocol/ssl_request.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use byteorder::LittleEndian;
|
||||
|
||||
use crate::io::BufMut;
|
||||
use crate::mysql::io::BufMutExt;
|
||||
use crate::mysql::protocol::{AuthPlugin, Capabilities, Encode};
|
||||
|
||||
// https://dev.mysql.com/doc/dev/mysql-server/8.0.12/page_protocol_connection_phase_packets_protocol_handshake_response.html
|
||||
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest
|
||||
#[derive(Debug)]
|
||||
pub struct SslRequest {
|
||||
pub max_packet_size: u32,
|
||||
pub client_collation: u8,
|
||||
}
|
||||
|
||||
impl Encode for SslRequest {
|
||||
fn encode(&self, buf: &mut Vec<u8>, capabilities: Capabilities) {
|
||||
// SSL must be set or else it makes no sense to ask for an upgrade
|
||||
assert!(
|
||||
capabilities.contains(Capabilities::SSL),
|
||||
"SSL bit must be set for Capabilities"
|
||||
);
|
||||
|
||||
// client capabilities : int<4>
|
||||
buf.put_u32::<LittleEndian>(capabilities.bits() as u32);
|
||||
|
||||
// max packet size : int<4>
|
||||
buf.put_u32::<LittleEndian>(self.max_packet_size);
|
||||
|
||||
// client character collation : int<1>
|
||||
buf.put_u8(self.client_collation);
|
||||
|
||||
// reserved : string<23>
|
||||
buf.advance(23);
|
||||
}
|
||||
}
|
||||
@ -178,7 +178,6 @@ mod tests {
|
||||
use super::{BigUint, PublicKey};
|
||||
use rand::rngs::adapter::ReadRng;
|
||||
use sha1::Sha1;
|
||||
use sha2::Sha256;
|
||||
|
||||
const INPUT: &str = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv9E+l0oFIoGnZmu6bdil\nI3WK79iug/hukj5QrWRrJVVCHL8rRxNsQGYPvQfXgqEnJW0Rqy2BBebNrnSMduny\nCazz1KM1h57hSI1xHGhg/o82Us1j9fUucKo0Pt3vg7xjVVcN0j1bwr96gEbt6B4Q\nt4eKZBhtle1bgoBcqFBhGfU17cnedSzMUCutM+kXTzzOTplKoqXeJpEZDTX8AP9F\nQ9JkoA22yTn8H2GROIAffm1UQS7DXXjI5OnzBJNs72oNSeK8i72xLkoSdfVw3vCu\ni+mpt4LJgAZLvzc2O4nLzu4Bljb+Mrch34HSWyxOfWzt1v9vpJfEVQ2/VZaIng6U\nUQIDAQAB\n-----END PUBLIC KEY-----\n";
|
||||
|
||||
@ -239,7 +238,7 @@ mod tests {
|
||||
0x2c, 0x49,
|
||||
];
|
||||
|
||||
let mut seed = &[
|
||||
let seed = &[
|
||||
0xaa, 0xfd, 0x12, 0xf6, 0x59, 0xca, 0xe6, 0x34, 0x89, 0xb4, 0x79, 0xe5, 0x07, 0x6d,
|
||||
0xde, 0xc2, 0xf0, 0x6c, 0xb5, 0x8f,
|
||||
][..];
|
||||
|
||||
@ -43,6 +43,12 @@ where
|
||||
DB::Connection: crate::Connection<Database = DB>,
|
||||
{
|
||||
/// Creates a connection pool with the default configuration.
|
||||
///
|
||||
/// The connection URL syntax is documented on the connection type for the respective
|
||||
/// database you're connecting to:
|
||||
///
|
||||
/// * MySQL/MariaDB: [crate::MySqlConnection]
|
||||
/// * PostgreSQL: [crate::PgConnection]
|
||||
pub async fn new(url: &str) -> crate::Result<Self> {
|
||||
Self::builder().build(url).await
|
||||
}
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
use std::convert::TryInto;
|
||||
|
||||
use async_std::net::{Shutdown, TcpStream};
|
||||
use async_std::net::Shutdown;
|
||||
use byteorder::NetworkEndian;
|
||||
use futures_core::future::BoxFuture;
|
||||
use hmac::{Hmac, Mac};
|
||||
use rand::Rng;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::cache::StatementCache;
|
||||
use crate::connection::Connection;
|
||||
use crate::io::{Buf, BufStream};
|
||||
use crate::io::{Buf, BufStream, MaybeTlsStream};
|
||||
use crate::postgres::protocol::{
|
||||
self, hi, Authentication, Decode, Encode, Message, SaslInitialResponse, SaslResponse,
|
||||
StatementId,
|
||||
@ -14,17 +17,69 @@ use crate::postgres::protocol::{
|
||||
use crate::postgres::PgError;
|
||||
use crate::url::Url;
|
||||
use crate::Result;
|
||||
use hmac::{Hmac, Mac};
|
||||
use rand::Rng;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
/// An asynchronous connection to a [Postgres] database.
|
||||
///
|
||||
/// The connection string expected by [Connection::open] should be a PostgreSQL connection
|
||||
/// string, as documented at
|
||||
/// <https://www.postgresql.org/docs/12/libpq-connect.html#LIBPQ-CONNSTRING>
|
||||
///
|
||||
/// ### TLS Support (requires `tls` feature)
|
||||
/// This connection type supports the same `sslmode` query parameter that `libpq` does in
|
||||
/// connection strings: <https://www.postgresql.org/docs/12/libpq-ssl.html>
|
||||
///
|
||||
/// ```text
|
||||
/// postgresql://<user>[:<password>]@<host>[:<port>]/<database>[?sslmode=<ssl-mode>[&sslcrootcert=<path>]]
|
||||
/// ```
|
||||
/// where
|
||||
/// ```text
|
||||
/// ssl-mode = disable | allow | prefer | require | verify-ca | verify-full
|
||||
/// path = percent (URL) encoded path on the local machine
|
||||
/// ```
|
||||
///
|
||||
/// If the `tls` feature is not enabled, `disable`, `allow` and `prefer` are no-ops and `require`,
|
||||
/// `verify-ca` and `verify-full` are forbidden (attempting to connect with these will return
|
||||
/// an error).
|
||||
///
|
||||
/// If the `tls` feature is enabled, an upgrade to TLS is attempted on every connection by default
|
||||
/// (equivalent to `sslmode=prefer`). If the server does not support TLS (because it was not
|
||||
/// started with a valid certificate and key, see <https://www.postgresql.org/docs/12/ssl-tcp.html>)
|
||||
/// then it falls back to an unsecured connection and logs a warning.
|
||||
///
|
||||
/// Add `sslmode=require` to your connection string to emit an error if the TLS upgrade fails.
|
||||
///
|
||||
/// If you're running Postgres locally, your connection string might look like this:
|
||||
/// ```text
|
||||
/// postgresql://root:password@localhost/my_database?sslmode=require
|
||||
/// ```
|
||||
///
|
||||
/// However, like with `libpq` the server certificate is **not** checked for validity by default.
|
||||
///
|
||||
/// Specifying `sslmode=verify-ca` will cause the TLS upgrade to verify the server's SSL
|
||||
/// certificate against a local CA root certificate; this is not the system root certificate
|
||||
/// but is instead expected to be specified in one of a few ways:
|
||||
///
|
||||
/// * The path to the certificate can be specified by adding the `sslrootcert` query parameter
|
||||
/// to the connection string. (Remember to percent-encode it!)
|
||||
///
|
||||
/// * The path may also be specified via the `PGSSLROOTCERT` environment variable (which
|
||||
/// should *not* be percent-encoded.)
|
||||
///
|
||||
/// * Otherwise, the library will look for the Postgres global root CA certificate in the default
|
||||
/// location:
|
||||
///
|
||||
/// * `$HOME/.postgresql/root.crt` on POSIX systems
|
||||
/// * `%APPDATA%\postgresql\root.crt` on Windows
|
||||
///
|
||||
/// These locations are documented here: <https://www.postgresql.org/docs/12/libpq-ssl.html#LIBQ-SSL-CERTIFICATES>
|
||||
/// If the root certificate cannot be found by any of these means then the TLS upgrade will fail.
|
||||
///
|
||||
/// If `sslmode=verify-full` is specified, in addition to checking the certificate as with
|
||||
/// `sslmode=verify-ca`, the hostname in the connection string will be verified
|
||||
/// against the hostname in the server certificate, so they must be the same for the TLS
|
||||
/// upgrade to succeed.
|
||||
pub struct PgConnection {
|
||||
pub(super) stream: BufStream<TcpStream>,
|
||||
pub(super) stream: BufStream<MaybeTlsStream>,
|
||||
|
||||
// Map of query to statement id
|
||||
pub(super) statement_cache: StatementCache<StatementId>,
|
||||
@ -43,8 +98,49 @@ pub struct PgConnection {
|
||||
}
|
||||
|
||||
impl PgConnection {
|
||||
#[cfg(feature = "tls")]
|
||||
async fn try_ssl(
|
||||
&mut self,
|
||||
url: &Url,
|
||||
invalid_certs: bool,
|
||||
invalid_hostnames: bool,
|
||||
) -> crate::Result<bool> {
|
||||
use async_native_tls::TlsConnector;
|
||||
|
||||
protocol::SslRequest::encode(self.stream.buffer_mut());
|
||||
|
||||
self.stream.flush().await?;
|
||||
|
||||
match self.stream.peek(1).await? {
|
||||
Some(b"N") => return Ok(false),
|
||||
Some(b"S") => (),
|
||||
Some(other) => {
|
||||
return Err(tls_err!("unexpected single-byte response: 0x{:02X}", other[0]).into())
|
||||
}
|
||||
None => return Err(tls_err!("server unexpectedly closed connection").into()),
|
||||
}
|
||||
|
||||
let mut connector = TlsConnector::new()
|
||||
.danger_accept_invalid_certs(invalid_certs)
|
||||
.danger_accept_invalid_hostnames(invalid_hostnames);
|
||||
|
||||
if !invalid_certs {
|
||||
match read_root_certificate(&url).await {
|
||||
Ok(cert) => {
|
||||
connector = connector.add_root_certificate(cert);
|
||||
}
|
||||
Err(e) => log::warn!("failed to read Postgres root certificate: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
self.stream.clear_bufs();
|
||||
self.stream.stream.upgrade(url, connector).await?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
// https://www.postgresql.org/docs/12/protocol-flow.html#id-1.10.5.7.3
|
||||
async fn startup(&mut self, url: Url) -> 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");
|
||||
@ -240,7 +336,8 @@ impl PgConnection {
|
||||
impl PgConnection {
|
||||
pub(super) async fn open(url: Result<Url>) -> Result<Self> {
|
||||
let url = url?;
|
||||
let stream = TcpStream::connect((url.host(), url.port(5432))).await?;
|
||||
|
||||
let stream = MaybeTlsStream::connect(&url, 5432).await?;
|
||||
let mut self_ = Self {
|
||||
stream: BufStream::new(stream),
|
||||
process_id: 0,
|
||||
@ -251,7 +348,48 @@ impl PgConnection {
|
||||
ready: true,
|
||||
};
|
||||
|
||||
self_.startup(url).await?;
|
||||
let ssl_mode = url.get_param("sslmode").unwrap_or("prefer".into());
|
||||
|
||||
match &*ssl_mode {
|
||||
// TODO: on "allow" retry with TLS if startup fails
|
||||
"disable" | "allow" => (),
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
"prefer" => {
|
||||
if !self_.try_ssl(&url, true, true).await? {
|
||||
log::warn!("server does not support TLS, falling back to unsecured connection")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tls"))]
|
||||
"prefer" => log::info!("compiled without TLS, skipping upgrade"),
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
"require" | "verify-ca" | "verify-full" => {
|
||||
if !self_
|
||||
.try_ssl(
|
||||
&url,
|
||||
ssl_mode == "require", // false for both verify-ca and verify-full
|
||||
ssl_mode != "verify-full", // false for only verify-full
|
||||
)
|
||||
.await?
|
||||
{
|
||||
return Err(tls_err!("Postgres server does not support TLS").into());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tls"))]
|
||||
"require" | "verify-ca" | "verify-full" => {
|
||||
return Err(tls_err!(
|
||||
"sslmode {:?} unsupported; SQLx was compiled without `tls` feature",
|
||||
ssl_mode
|
||||
)
|
||||
.into())
|
||||
}
|
||||
_ => return Err(tls_err!("unknown `sslmode` value: {:?}", ssl_mode).into()),
|
||||
}
|
||||
|
||||
self_.startup(&url).await?;
|
||||
|
||||
Ok(self_)
|
||||
}
|
||||
@ -271,6 +409,26 @@ impl Connection for PgConnection {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
async fn read_root_certificate(url: &Url) -> crate::Result<async_native_tls::Certificate> {
|
||||
use std::env;
|
||||
|
||||
let root_cert_path = if let Some(path) = url.get_param("sslrootcert") {
|
||||
path.into()
|
||||
} else if let Ok(cert_path) = env::var("PGSSLROOTCERT") {
|
||||
cert_path
|
||||
} else if cfg!(windows) {
|
||||
let appdata = env::var("APPDATA").map_err(|_| tls_err!("APPDATA not set"))?;
|
||||
format!("{}\\postgresql\\root.crt", appdata)
|
||||
} else {
|
||||
let home = env::var("HOME").map_err(|_| tls_err!("HOME not set"))?;
|
||||
format!("{}/.postgresql/root.crt", home)
|
||||
};
|
||||
|
||||
let root_cert = async_std::fs::read(root_cert_path).await?;
|
||||
Ok(async_native_tls::Certificate::from_pem(&root_cert)?)
|
||||
}
|
||||
|
||||
static GS2_HEADER: &'static str = "n,,";
|
||||
static CHANNEL_ATTR: &'static str = "c";
|
||||
static USERNAME_ATTR: &'static str = "n";
|
||||
@ -354,7 +512,7 @@ async fn sasl_auth<T: AsRef<str>>(conn: &mut PgConnection, username: T, password
|
||||
);
|
||||
|
||||
// AuthMessage := client-first-message-bare + "," + server-first-message + "," + client-final-message-without-proof
|
||||
let auth_message = format!("{client_first_message_bare},{server_first_message},{client_final_message_wo_proof}",
|
||||
let auth_message = format!("{client_first_message_bare},{server_first_message},{client_final_message_wo_proof}",
|
||||
client_first_message_bare = client_first_message_bare,
|
||||
server_first_message = server_first_message,
|
||||
client_final_message_wo_proof = client_final_message_wo_proof);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
// the size of this module to exactly what is necessary.
|
||||
#![allow(unused)]
|
||||
|
||||
// REQUESTS
|
||||
mod bind;
|
||||
mod cancel_request;
|
||||
mod close;
|
||||
@ -16,6 +17,7 @@ mod parse;
|
||||
mod password_message;
|
||||
mod query;
|
||||
mod sasl;
|
||||
mod ssl_request;
|
||||
mod startup_message;
|
||||
mod statement;
|
||||
mod sync;
|
||||
@ -32,11 +34,13 @@ pub use parse::Parse;
|
||||
pub use password_message::PasswordMessage;
|
||||
pub use query::Query;
|
||||
pub use sasl::{hi, SaslInitialResponse, SaslResponse};
|
||||
pub use ssl_request::SslRequest;
|
||||
pub use startup_message::StartupMessage;
|
||||
pub use statement::StatementId;
|
||||
pub use sync::Sync;
|
||||
pub use terminate::Terminate;
|
||||
|
||||
// RESPONSES
|
||||
mod authentication;
|
||||
mod backend_key_data;
|
||||
mod command_complete;
|
||||
|
||||
23
sqlx-core/src/postgres/protocol/ssl_request.rs
Normal file
23
sqlx-core/src/postgres/protocol/ssl_request.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use crate::io::{Buf, BufMut};
|
||||
use byteorder::NetworkEndian;
|
||||
|
||||
pub struct SslRequest;
|
||||
|
||||
impl SslRequest {
|
||||
pub fn encode(buf: &mut Vec<u8>) {
|
||||
// packet length: 8 bytes including self
|
||||
buf.put_u32::<NetworkEndian>(8);
|
||||
// 1234 in high 16 bits, 5679 in low 16
|
||||
buf.put_u32::<NetworkEndian>((1234 << 16) | 5679);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ssl_request() {
|
||||
use crate::io::Buf;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
SslRequest::encode(&mut buf);
|
||||
|
||||
assert_eq!(&buf, b"\x00\x00\x00\x08\x04\xd2\x16/");
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
use std::borrow::Cow;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
pub struct Url(url::Url);
|
||||
@ -64,4 +65,10 @@ impl Url {
|
||||
Some(database)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_param(&self, key: &str) -> Option<Cow<str>> {
|
||||
self.0
|
||||
.query_pairs()
|
||||
.find_map(|(key_, val)| if key == key_ { Some(val) } else { None })
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,5 +66,7 @@ async fn it_remains_stable_issue_30() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
async fn connect() -> anyhow::Result<PgConnection> {
|
||||
let _ = dotenv::dotenv();
|
||||
let _ = env_logger::try_init();
|
||||
Ok(PgConnection::open(dotenv::var("DATABASE_URL")?).await?)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user