Skip to content

Commit ddf7f24

Browse files
authored
Add Certificate::from_pem_bundle() (#2032)
1 parent 5d8443d commit ddf7f24

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ http3 = ["rustls-tls-manual-roots", "h3", "h3-quinn", "quinn", "futures-channel"
7070
# Don't rely on these whatsoever. They may disappear at anytime.
7171

7272
# Enables common types used for TLS. Useless on its own.
73-
__tls = []
73+
__tls = ["dep:rustls-pemfile"]
7474

7575
# Enables common rustls code.
7676
# Equivalent to rustls-tls-manual-roots but shorter :)
77-
__rustls = ["hyper-rustls", "tokio-rustls", "rustls", "__tls", "rustls-pemfile"]
77+
__rustls = ["hyper-rustls", "tokio-rustls", "rustls", "__tls"]
7878

7979
# When enabled, disable using the cached SYS_PROXIES.
8080
__internal_proxy_sys_no_cache = []
@@ -112,6 +112,7 @@ pin-project-lite = "0.2.0"
112112
ipnet = "2.3"
113113

114114
# Optional deps...
115+
rustls-pemfile = { version = "1.0", optional = true }
115116

116117
## default-tls
117118
hyper-tls = { version = "0.5", optional = true }
@@ -124,7 +125,6 @@ rustls = { version = "0.21.6", features = ["dangerous_configuration"], optional
124125
tokio-rustls = { version = "0.24", optional = true }
125126
webpki-roots = { version = "0.25", optional = true }
126127
rustls-native-certs = { version = "0.6", optional = true }
127-
rustls-pemfile = { version = "1.0", optional = true }
128128

129129
## cookies
130130
cookie_crate = { version = "0.17.0", package = "cookie", optional = true }

src/tls.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ use rustls::{
4949
client::HandshakeSignatureValid, client::ServerCertVerified, client::ServerCertVerifier,
5050
DigitallySignedStruct, Error as TLSError, ServerName,
5151
};
52-
use std::fmt;
52+
use std::{
53+
fmt,
54+
io::{BufRead, BufReader},
55+
};
5356

5457
/// Represents a server X509 certificate.
5558
#[derive(Clone)]
@@ -138,6 +141,32 @@ impl Certificate {
138141
})
139142
}
140143

144+
/// Create a collection of `Certificate`s from a PEM encoded certificate bundle.
145+
/// Example byte sources may be `.crt`, `.cer` or `.pem` files.
146+
///
147+
/// # Examples
148+
///
149+
/// ```
150+
/// # use std::fs::File;
151+
/// # use std::io::Read;
152+
/// # fn cert() -> Result<(), Box<std::error::Error>> {
153+
/// let mut buf = Vec::new();
154+
/// File::open("ca-bundle.crt")?
155+
/// .read_to_end(&mut buf)?;
156+
/// let certs = reqwest::Certificate::from_pem_bundle(&buf)?;
157+
/// # drop(certs);
158+
/// # Ok(())
159+
/// # }
160+
/// ```
161+
pub fn from_pem_bundle(pem_bundle: &[u8]) -> crate::Result<Vec<Certificate>> {
162+
let mut reader = BufReader::new(pem_bundle);
163+
164+
Self::read_pem_certs(&mut reader)?
165+
.iter()
166+
.map(|cert_vec| Certificate::from_pem(&cert_vec))
167+
.collect::<crate::Result<Vec<Certificate>>>()
168+
}
169+
141170
#[cfg(feature = "native-tls-crate")]
142171
pub(crate) fn add_to_native_tls(self, tls: &mut native_tls_crate::TlsConnectorBuilder) {
143172
tls.add_root_certificate(self.native);
@@ -155,12 +184,8 @@ impl Certificate {
155184
.add(&rustls::Certificate(buf))
156185
.map_err(crate::error::builder)?,
157186
Cert::Pem(buf) => {
158-
let mut pem = Cursor::new(buf);
159-
let certs = rustls_pemfile::certs(&mut pem).map_err(|_| {
160-
crate::error::builder(TLSError::General(String::from(
161-
"No valid certificate was found",
162-
)))
163-
})?;
187+
let mut reader = Cursor::new(buf);
188+
let certs = Self::read_pem_certs(&mut reader)?;
164189
for c in certs {
165190
root_cert_store
166191
.add(&rustls::Certificate(c))
@@ -170,6 +195,11 @@ impl Certificate {
170195
}
171196
Ok(())
172197
}
198+
199+
fn read_pem_certs(reader: &mut impl BufRead) -> crate::Result<Vec<Vec<u8>>> {
200+
rustls_pemfile::certs(reader)
201+
.map_err(|_| crate::error::builder("invalid certificate encoding"))
202+
}
173203
}
174204

175205
impl Identity {

0 commit comments

Comments
 (0)