Skip to content

Commit 78ce118

Browse files
authored
fix: rustls-tls features to support certificate stores (#1542)
Add separate features for native system roots and Mozilla webpki roots. Update documentation and build configs to reflect new options.
1 parent 0a4969f commit 78ce118

File tree

15 files changed

+125
-78
lines changed

15 files changed

+125
-78
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ jobs:
8080
- name: Check workspace with native-tls
8181
run: >
8282
cargo hack check -p librespot --each-feature --exclude-all-features
83-
--include-features native-tls --exclude-features rustls-tls
83+
--include-features native-tls
84+
--exclude-features rustls-tls-native-roots,rustls-tls-webpki-roots
8485
85-
- name: Check workspace with rustls-tls
86+
- name: Check workspace with rustls-tls-native-roots
8687
run: >
8788
cargo hack check -p librespot --each-feature --exclude-all-features
88-
--include-features rustls-tls --exclude-features native-tls
89+
--include-features rustls-tls-native-roots
90+
--exclude-features native-tls,rustls-tls-webpki-roots
8991
9092
- name: Build binary with default features
9193
run: cargo build --frozen

.github/workflows/cross-compile.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ jobs:
6161
toolchain: ${{ matrix.toolchain }}
6262
args: --locked --verbose
6363

64-
- name: Build binary with rustls-tls and no default features
64+
- name: Build binary without system dependencies
6565
if: matrix.platform.target == 'riscv64gc-unknown-linux-gnu'
6666
uses: houseabsolute/actions-rust-cross@v1
6767
with:
6868
command: build
6969
target: ${{ matrix.platform.target }}
7070
toolchain: ${{ matrix.toolchain }}
71-
args: --locked --verbose --no-default-features --features rustls-tls
71+
args: --locked --verbose --no-default-features --features rustls-tls-webpki-roots
7272

7373
- name: Upload debug artifacts
7474
uses: actions/upload-artifact@v4

.github/workflows/quality.yml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,17 @@ jobs:
7171
- name: Run clippy with native-tls
7272
run: >
7373
cargo hack clippy -p librespot --each-feature --exclude-all-features
74-
--include-features native-tls --exclude-features rustls-tls
74+
--include-features native-tls
75+
--exclude-features rustls-tls-native-roots,rustls-tls-webpki-roots
7576
76-
- name: Run clippy with rustls-tls
77+
- name: Run clippy with rustls-tls-native-roots
7778
run: >
7879
cargo hack clippy -p librespot --each-feature --exclude-all-features
79-
--include-features rustls-tls --exclude-features native-tls
80+
--include-features rustls-tls-native-roots
81+
--exclude-features native-tls,rustls-tls-webpki-roots
82+
83+
- name: Run clippy with rustls-tls-webpki-roots
84+
run: >
85+
cargo hack clippy -p librespot --each-feature --exclude-all-features
86+
--include-features rustls-tls-webpki-roots
87+
--exclude-features native-tls,rustls-tls-native-roots

COMPILING.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,18 @@ sudo dnf install openssl-devel pkg-config
9696
```
9797

9898
#### rustls-tls
99-
Uses a Rust-based TLS implementation with `rustls-platform-verifier` for certificate authority (CA) verification:
99+
Uses a Rust-based TLS implementation with certificate authority (CA) verification. Two certificate store options are available:
100+
101+
**rustls-tls-native-roots**:
100102
- **Linux**: Uses system ca-certificates package
101103
- **macOS**: Uses Security.framework for CA verification
102104
- **Windows**: Uses Windows certificate store
105+
- Integrates with system certificate management and security updates
106+
107+
**rustls-tls-webpki-roots**:
108+
- Uses Mozilla's compiled-in certificate store (webpki-roots)
109+
- Certificate trust is independent of host system
110+
- Best for reproducible builds, containers, or embedded systems
103111

104112
**When to choose rustls-tls:**
105113
- You want to avoid external OpenSSL dependencies
@@ -118,8 +126,11 @@ cargo build
118126
# Explicitly use native-tls
119127
cargo build --no-default-features --features "native-tls rodio-backend with-libmdns"
120128

121-
# Use rustls-tls instead
122-
cargo build --no-default-features --features "rustls-tls rodio-backend with-libmdns"
129+
# Use rustls-tls with native certificate stores
130+
cargo build --no-default-features --features "rustls-tls-native-roots rodio-backend with-libmdns"
131+
132+
# Use rustls-tls with Mozilla's webpki certificate store
133+
cargo build --no-default-features --features "rustls-tls-webpki-roots rodio-backend with-libmdns"
123134
```
124135

125136
**Important:** The TLS backends are mutually exclusive. Attempting to enable both will result in a compile-time error.

Cargo.lock

Lines changed: 12 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,27 @@ default = ["native-tls", "rodio-backend", "with-libmdns"]
4848
# system-managed certificates.
4949
native-tls = ["librespot-core/native-tls", "librespot-oauth/native-tls"]
5050

51-
# rustls-tls: Uses the Rust-based rustls TLS implementation with platform certificate verification.
52-
# This provides a Rust TLS stack (with assembly optimizations) that uses rustls-platform-verifier to
53-
# automatically select the appropriate certificate authority (CA) certificates from your system's
54-
# trust store. Choose this for avoiding external OpenSSL dependencies, reproducible builds, or when
55-
# targeting platforms where native TLS dependencies are unavailable or problematic (musl, embedded,
56-
# static linking). On Linux it uses ca-certificates, on macOS it uses Security.framework, and on
57-
# Windows it uses the Windows certificate store.
58-
rustls-tls = ["librespot-core/rustls-tls", "librespot-oauth/rustls-tls"]
51+
# rustls-tls: Uses the Rust-based rustls TLS implementation with certificate authority (CA)
52+
# verification. This provides a Rust TLS stack (with assembly optimizations). Choose this for
53+
# avoiding external OpenSSL dependencies, reproducible builds, or when targeting platforms where
54+
# native TLS dependencies are unavailable or problematic (musl, embedded, static linking).
55+
#
56+
# Two certificate store options are available:
57+
#
58+
# - rustls-tls-native-roots: Uses rustls with native system certificate stores (ca-certificates on
59+
# Linux, Security.framework on macOS, Windows certificate store on Windows). Best for most users as
60+
# it integrates with system-managed certificates and gets security updates through the OS.
61+
rustls-tls-native-roots = [
62+
"librespot-core/rustls-tls-native-roots",
63+
"librespot-oauth/rustls-tls-native-roots",
64+
]
65+
# rustls-tls-webpki-roots: Uses rustls with Mozilla's compiled-in certificate store (webpki-roots).
66+
# Best for reproducible builds, containerized environments, or when you want certificate handling
67+
# to be independent of the host system.
68+
rustls-tls-webpki-roots = [
69+
"librespot-core/rustls-tls-webpki-roots",
70+
"librespot-oauth/rustls-tls-webpki-roots",
71+
]
5972

6073
# Audio backends - see README.md for audio backend selection guide
6174
# Cross-platform backends:

audio/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ default = ["native-tls"]
1414

1515
# TLS backend propagation
1616
native-tls = ["librespot-core/native-tls"]
17-
rustls-tls = ["librespot-core/rustls-tls"]
17+
rustls-tls-native-roots = ["librespot-core/rustls-tls-native-roots"]
18+
rustls-tls-webpki-roots = ["librespot-core/rustls-tls-webpki-roots"]
1819

1920
[dependencies]
2021
librespot-core.workspace = true

connect/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ edition.workspace = true
1313
default = ["native-tls"]
1414

1515
# TLS backend propagation
16-
native-tls = ["librespot-core/native-tls", "librespot-playback/native-tls"]
17-
rustls-tls = ["librespot-core/rustls-tls", "librespot-playback/rustls-tls"]
16+
native-tls = ["librespot-core/native-tls"]
17+
rustls-tls-native-roots = ["librespot-core/rustls-tls-native-roots"]
18+
rustls-tls-webpki-roots = ["librespot-core/rustls-tls-webpki-roots"]
1819

1920
[dependencies]
2021
librespot-core.workspace = true

core/Cargo.toml

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,23 @@ native-tls = [
2121
"librespot-oauth/native-tls",
2222
"tokio-tungstenite/native-tls",
2323
]
24-
rustls-tls = [
25-
"dep:hyper-rustls",
24+
rustls-tls-native-roots = [
25+
"__rustls",
2626
"hyper-proxy2/rustls",
27-
"librespot-oauth/rustls-tls",
28-
"tokio-tungstenite/__rustls-tls",
27+
"hyper-rustls/native-tokio",
28+
"librespot-oauth/rustls-tls-native-roots",
29+
"tokio-tungstenite/rustls-tls-native-roots",
2930
]
31+
rustls-tls-webpki-roots = [
32+
"__rustls",
33+
"hyper-proxy2/rustls-webpki",
34+
"hyper-rustls/webpki-tokio",
35+
"librespot-oauth/rustls-tls-webpki-roots",
36+
"tokio-tungstenite/rustls-tls-webpki-roots",
37+
]
38+
39+
# Internal features - these are not meant to be used by end users
40+
__rustls = []
3041

3142
[dependencies]
3243
librespot-oauth.workspace = true
@@ -60,8 +71,6 @@ hyper-rustls = { version = "0.27", default-features = false, features = [
6071
"http1",
6172
"http2",
6273
"ring",
63-
"rustls-platform-verifier",
64-
"tls12",
6574
], optional = true }
6675
hyper-tls = { version = "0.6", optional = true }
6776
hyper-util = { version = "0.1", default-features = false, features = [

core/src/http_client.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ use parking_lot::Mutex;
2222
use thiserror::Error;
2323
use url::Url;
2424

25-
#[cfg(all(feature = "rustls-tls", not(feature = "native-tls")))]
25+
#[cfg(all(feature = "__rustls", not(feature = "native-tls")))]
2626
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
27-
#[cfg(all(feature = "native-tls", not(feature = "rustls-tls")))]
27+
#[cfg(all(feature = "native-tls", not(feature = "__rustls")))]
2828
use hyper_tls::HttpsConnector;
2929

3030
use crate::{
@@ -150,13 +150,16 @@ impl HttpClient {
150150
fn try_create_hyper_client(proxy_url: Option<&Url>) -> Result<HyperClient, Error> {
151151
// configuring TLS is expensive and should be done once per process
152152

153-
#[cfg(all(feature = "rustls-tls", not(feature = "native-tls")))]
153+
#[cfg(all(feature = "__rustls", not(feature = "native-tls")))]
154154
let https_connector = {
155-
let tls = HttpsConnectorBuilder::new().with_platform_verifier();
155+
#[cfg(feature = "rustls-tls-native-roots")]
156+
let tls = HttpsConnectorBuilder::new().with_native_roots()?;
157+
#[cfg(feature = "rustls-tls-webpki-roots")]
158+
let tls = HttpsConnectorBuilder::new().with_webpki_roots();
156159
tls.https_or_http().enable_http1().enable_http2().build()
157160
};
158161

159-
#[cfg(all(feature = "native-tls", not(feature = "rustls-tls")))]
162+
#[cfg(all(feature = "native-tls", not(feature = "__rustls")))]
160163
let https_connector = HttpsConnector::new();
161164

162165
// When not using a proxy a dummy proxy is configured that will not intercept any traffic.

0 commit comments

Comments
 (0)