Skip to content

Commit c7b4bd9

Browse files
committed
impl SSL_CTX_set_default_verify_paths and friends
Adds: * SSL_CTX_set_default_verify_paths * SSL_CTX_set_default_verify_dir * SSL_CTX_set_default_verify_file Stubs: * SSL_CTX_set_default_verify_store We take a dep on `openssl-probe` in order to get convenient handling of the `SSL_CERT_DIR` and `SSL_CERT_FILE` env vars, and default locations for the verify paths. There is likely some fine-tuning to do (e.g. with respect to the `X509_LOOKUP` API surface), but is a step in the right direction for the simple cases.
1 parent a0c4a24 commit c7b4bd9

File tree

5 files changed

+114
-1
lines changed

5 files changed

+114
-1
lines changed

rustls-libssl/Cargo.lock

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

rustls-libssl/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ crate-type = ["cdylib"]
1212
[dependencies]
1313
env_logger = "0.10"
1414
log = "0.4"
15+
openssl-probe = "0.1"
1516
openssl-sys = "0.9.98"
1617
rustls = "0.22"
1718
rustls-pemfile = "2"

rustls-libssl/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ const ENTRYPOINTS: &[&str] = &[
6565
"SSL_CTX_get_cert_store",
6666
"SSL_CTX_get_ex_data",
6767
"SSL_CTX_get_options",
68+
"SSL_CTX_set_default_verify_paths",
69+
"SSL_CTX_set_default_verify_dir",
70+
"SSL_CTX_set_default_verify_file",
71+
"SSL_CTX_set_default_verify_store",
6872
"SSL_CTX_load_verify_dir",
6973
"SSL_CTX_load_verify_file",
7074
"SSL_CTX_new",

rustls-libssl/src/entry.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,48 @@ fn load_verify_files(ctx: &Mutex<SSL_CTX>, file_names: impl Iterator<Item = Path
234234
}
235235
}
236236

237+
entry! {
238+
pub fn _SSL_CTX_set_default_verify_paths(ctx: *mut SSL_CTX) -> c_int {
239+
let ctx = try_clone_arc!(ctx);
240+
match ctx
241+
.lock()
242+
.map_err(|_| Error::cannot_lock())
243+
.map(|mut ctx| ctx.set_default_verify_paths())
244+
{
245+
Err(e) => e.raise().into(),
246+
Ok(()) => C_INT_SUCCESS,
247+
}
248+
}
249+
}
250+
251+
entry! {
252+
pub fn _SSL_CTX_set_default_verify_dir(ctx: *mut SSL_CTX) -> c_int {
253+
let ctx = try_clone_arc!(ctx);
254+
match ctx
255+
.lock()
256+
.map_err(|_| Error::cannot_lock())
257+
.map(|mut ctx| ctx.set_default_verify_dir())
258+
{
259+
Err(e) => e.raise().into(),
260+
Ok(()) => C_INT_SUCCESS,
261+
}
262+
}
263+
}
264+
265+
entry! {
266+
pub fn _SSL_CTX_set_default_verify_file(ctx: *mut SSL_CTX) -> c_int {
267+
let ctx = try_clone_arc!(ctx);
268+
match ctx
269+
.lock()
270+
.map_err(|_| Error::cannot_lock())
271+
.map(|mut ctx| ctx.set_default_verify_file())
272+
{
273+
Err(e) => e.raise().into(),
274+
Ok(()) => C_INT_SUCCESS,
275+
}
276+
}
277+
}
278+
237279
entry! {
238280
pub fn _SSL_CTX_load_verify_file(ctx: *mut SSL_CTX, ca_file: *const c_char) -> c_int {
239281
let ctx = try_clone_arc!(ctx);
@@ -1007,6 +1049,11 @@ entry_stub! {
10071049
) -> c_int;
10081050
}
10091051

1052+
// The SSL_CTX X509_STORE isn't being meaningfully used yet.
1053+
entry_stub! {
1054+
pub fn _SSL_CTX_set_default_verify_store(_ctx: *mut SSL_CTX) -> c_int;
1055+
}
1056+
10101057
pub struct SSL_SESSION;
10111058

10121059
entry_stub! {

rustls-libssl/src/lib.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use core::ffi::{c_int, CStr};
2+
use std::fs;
23
use std::io::{ErrorKind, Read, Write};
4+
use std::path::PathBuf;
35
use std::sync::{Arc, Mutex};
46

7+
use openssl_probe::ProbeResult;
58
use openssl_sys::{
69
SSL_ERROR_NONE, SSL_ERROR_SSL, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, X509_STORE,
710
X509_V_ERR_UNSPECIFIED,
@@ -205,6 +208,8 @@ pub struct SslContext {
205208
verify_roots: RootCertStore,
206209
verify_x509_store: x509::OwnedX509Store,
207210
alpn: Vec<Vec<u8>>,
211+
default_cert_file: Option<PathBuf>,
212+
default_cert_dir: Option<PathBuf>,
208213
}
209214

210215
impl SslContext {
@@ -216,6 +221,8 @@ impl SslContext {
216221
verify_roots: RootCertStore::empty(),
217222
verify_x509_store: x509::OwnedX509Store::new(),
218223
alpn: vec![],
224+
default_cert_file: None,
225+
default_cert_dir: None,
219226
}
220227
}
221228

@@ -237,6 +244,25 @@ impl SslContext {
237244
self.verify_mode = mode;
238245
}
239246

247+
fn set_default_verify_paths(&mut self) {
248+
let ProbeResult {
249+
cert_file,
250+
cert_dir,
251+
} = openssl_probe::probe();
252+
self.default_cert_file = cert_file;
253+
self.default_cert_dir = cert_dir;
254+
}
255+
256+
fn set_default_verify_dir(&mut self) {
257+
let ProbeResult { cert_dir, .. } = openssl_probe::probe();
258+
self.default_cert_dir = cert_dir;
259+
}
260+
261+
fn set_default_verify_file(&mut self) {
262+
let ProbeResult { cert_file, .. } = openssl_probe::probe();
263+
self.default_cert_file = cert_file;
264+
}
265+
240266
fn add_trusted_certs(
241267
&mut self,
242268
certs: Vec<CertificateDer<'static>>,
@@ -303,7 +329,7 @@ impl Ssl {
303329
raw_options: inner.raw_options,
304330
mode: inner.method.mode(),
305331
verify_mode: inner.verify_mode,
306-
verify_roots: inner.verify_roots.clone(),
332+
verify_roots: Self::load_verify_certs(inner)?,
307333
verify_server_name: None,
308334
alpn: inner.alpn.clone(),
309335
sni_server_name: None,
@@ -633,6 +659,34 @@ impl Ssl {
633659
None => SSL_ERROR_SSL,
634660
}
635661
}
662+
663+
fn load_verify_certs(ctx: &SslContext) -> Result<RootCertStore, error::Error> {
664+
let mut verify_roots = ctx.verify_roots.clone();
665+
666+
// If verify_roots isn't empty then it was configured with `SSL_CTX_load_verify_file`
667+
// or `SSL_CTX_load_verify_dir` and we should use it as-is.
668+
if !ctx.verify_roots.is_empty() {
669+
return Ok(verify_roots);
670+
}
671+
672+
// Otherwise, try to load the default cert file or cert dir.
673+
if let Some(default_cert_file) = &ctx.default_cert_file {
674+
verify_roots.add_parsable_certificates(x509::load_certs(
675+
vec![default_cert_file.to_path_buf()].into_iter(),
676+
)?);
677+
} else if let Some(default_cert_dir) = &ctx.default_cert_dir {
678+
let entries = match fs::read_dir(default_cert_dir) {
679+
Ok(iter) => iter,
680+
Err(err) => return Err(error::Error::from_io(err).raise()),
681+
}
682+
.filter_map(|entry| entry.ok())
683+
.map(|dir_entry| dir_entry.path());
684+
685+
verify_roots.add_parsable_certificates(x509::load_certs(entries)?);
686+
}
687+
688+
Ok(verify_roots)
689+
}
636690
}
637691

638692
#[derive(Default)]

0 commit comments

Comments
 (0)