Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions lib/vector-core/src/tls/incoming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,23 @@ impl TlsSettings {
if self.identity.is_none() {
Err(TlsError::MissingRequiredIdentity)
} else {
let mut acceptor =
SslAcceptor::mozilla_intermediate(SslMethod::tls()).context(CreateAcceptorSnafu)?;
// Use custom acceptor if TLS version, ciphersuites, or curves are configured
let mut acceptor = if self.min_tls_version.is_some() || self.ciphersuites.is_some() || self.curves.is_some() {
SslAcceptor::custom(
SslMethod::tls(),
&self.min_tls_version,
&self.ciphersuites,
&self.curves,
)
.map_err(|e| match e {
openssl::ssl::ErrorEx::OpenSslError { error_stack } => TlsError::CreateAcceptor { source: error_stack },
openssl::ssl::ErrorEx::InvalidTlsVersion => TlsError::SslBuildError { source: openssl::error::ErrorStack::get() },
openssl::ssl::ErrorEx::InvalidCiphersuite => TlsError::SslBuildError { source: openssl::error::ErrorStack::get() },
openssl::ssl::ErrorEx::InvalidCurve { error_stack } => TlsError::SetCurves { source: error_stack },
})?
} else {
SslAcceptor::mozilla_intermediate(SslMethod::tls()).context(CreateAcceptorSnafu)?
};
self.apply_context_base(&mut acceptor, true)?;
Ok(acceptor.build())
}
Expand Down
2 changes: 2 additions & 0 deletions lib/vector-core/src/tls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ pub enum TlsError {
source
))]
EncodeAlpnProtocols { source: TryFromIntError },
#[snafu(display("Error setting TLS curves: {}", source))]
SetCurves { source: ErrorStack },
#[snafu(display("PKCS#12 parse failed: {}", source))]
ParsePkcs12 { source: ErrorStack },
#[snafu(display("TCP bind failed: {}", source))]
Expand Down
53 changes: 50 additions & 3 deletions lib/vector-core/src/tls/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::{
AddCertToStoreSnafu, AddExtraChainCertSnafu, CaStackPushSnafu, EncodeAlpnProtocolsSnafu,
FileOpenFailedSnafu, FileReadFailedSnafu, MaybeTls, NewCaStackSnafu, NewStoreBuilderSnafu,
ParsePkcs12Snafu, PrivateKeyParseSnafu, Result, SetAlpnProtocolsSnafu, SetCertificateSnafu,
SetPrivateKeySnafu, SetVerifyCertSnafu, TlsError, X509ParseSnafu,
SetCurvesSnafu, SetPrivateKeySnafu, SetVerifyCertSnafu, TlsError, X509ParseSnafu,
};
use cfg_if::cfg_if;
use lookup::lookup_v2::OptionalValuePath;
Expand Down Expand Up @@ -162,6 +162,15 @@ pub struct TlsConfig {

/// TLS ciphersuites to enable.
pub ciphersuites: Option<String>,

/// TLS elliptic curve groups (curves) to enable.
///
/// Specifies the list of elliptic curve groups (curves) to use for TLS connections.
/// The curves are specified as a colon-separated list of curve names.
///
/// Common curve names include: prime256v1, secp384r1, secp521r1, X25519, X448.
#[configurable(metadata(docs::examples = "prime256v1:secp384r1"))]
pub curves: Option<String>,
}

impl TlsConfig {
Expand All @@ -186,6 +195,7 @@ pub struct TlsSettings {
server_name: Option<String>,
pub min_tls_version: Option<String>,
pub ciphersuites: Option<String>,
pub curves: Option<String>,
}

/// Identity store in PEM format
Expand Down Expand Up @@ -230,6 +240,7 @@ impl TlsSettings {
server_name: options.server_name.clone(),
min_tls_version: options.min_tls_version.clone(),
ciphersuites: options.ciphersuites.clone(),
curves: options.curves.clone(),
})
}

Expand Down Expand Up @@ -347,6 +358,13 @@ impl TlsSettings {
}
}

// Configure curves if specified
if let Some(ref curves) = self.curves {
context
.set_groups_list(curves)
.context(SetCurvesSnafu)?;
}

Ok(())
}

Expand Down Expand Up @@ -880,7 +898,7 @@ mod test {
},
];
for t in tests {
match builder.set_min_tls_version_and_ciphersuites(&t.text, &None) {
match builder.set_min_tls_version_and_ciphersuites(&t.text, &None, &None) {
Ok(()) => {
assert!(t.want.is_ok());
assert_eq!(builder.min_proto_version(), t.num);
Expand Down Expand Up @@ -921,7 +939,7 @@ mod test {
},
];
for t in tests {
match builder.set_min_tls_version_and_ciphersuites(&t.min_tls_version, &t.ciphersuite) {
match builder.set_min_tls_version_and_ciphersuites(&t.min_tls_version, &t.ciphersuite, &None) {
Ok(()) => assert!(t.want.is_ok()),
Err(e) => assert_eq!(t.want.err().unwrap(), e),
}
Expand Down Expand Up @@ -949,4 +967,33 @@ mod test {
},
}
}

#[test]
fn from_options_curves() {
let options = TlsConfig {
curves: Some("prime256v1:secp384r1".to_string()),
..Default::default()
};
let settings = TlsSettings::from_options(Some(&options))
.expect("Failed to parse curves");
assert_eq!(settings.curves, Some("prime256v1:secp384r1".to_string()));
}

#[test]
fn from_options_with_curves_applied() {
use openssl::ssl::SslConnector;

let options = TlsConfig {
curves: Some("prime256v1:secp384r1:secp521r1".to_string()),
..Default::default()
};
let settings = TlsSettings::from_options(Some(&options))
.expect("Failed to parse curves");

// Test that the context can be created with curves
let mut builder = SslConnector::builder(SslMethod::tls())
.expect("Failed to create SSL builder");
settings.apply_context(&mut builder)
.expect("Failed to apply context with curves");
}
}
6 changes: 3 additions & 3 deletions patch/openssl/src/ssl/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,14 @@ impl SslAcceptor {
Ok(SslAcceptorBuilder(ctx))
}

/// Creates a new builder configured with a minimum supported TLS version and a set of ciphersuites
/// Creates a new builder configured with a minimum supported TLS version, a set of ciphersuites, and elliptic curves
///
pub fn custom(method: SslMethod, min_tls_version: &Option<String>, ciphersuites: &Option<String>) -> Result<SslAcceptorBuilder, ErrorEx> {
pub fn custom(method: SslMethod, min_tls_version: &Option<String>, ciphersuites: &Option<String>, curves: &Option<String>) -> Result<SslAcceptorBuilder, ErrorEx> {
let mut ctx = ctx(method).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?;
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes()).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?;
ctx.set_tmp_dh(&dh).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?;
setup_curves(&mut ctx).map_err(|e| ErrorEx::OpenSslError { error_stack: e })?;
ctx.set_min_tls_version_and_ciphersuites(min_tls_version, ciphersuites)?;
ctx.set_min_tls_version_and_ciphersuites(min_tls_version, ciphersuites, curves)?;
Ok(SslAcceptorBuilder(ctx))
}

Expand Down
6 changes: 5 additions & 1 deletion patch/openssl/src/ssl/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,18 @@ pub enum ErrorEx {
},
InvalidTlsVersion,
InvalidCiphersuite,
InvalidCurve {
error_stack: ErrorStack
},
}

impl PartialEq for ErrorEx {
fn eq(&self, other: &ErrorEx) -> bool {
match (self, other) {
(ErrorEx::OpenSslError{..}, ErrorEx::OpenSslError{..})
| (ErrorEx::InvalidTlsVersion, ErrorEx::InvalidTlsVersion)
| (ErrorEx::InvalidCiphersuite, ErrorEx::InvalidCiphersuite) => true,
| (ErrorEx::InvalidCiphersuite, ErrorEx::InvalidCiphersuite)
| (ErrorEx::InvalidCurve{..}, ErrorEx::InvalidCurve{..}) => true,
_ => false,
}
}
Expand Down
12 changes: 10 additions & 2 deletions patch/openssl/src/ssl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1774,9 +1774,9 @@ impl SslContextBuilder {
self.0
}

/// Sets the context's minimal TLS version, specified as "VersionTLS1[0..3]", and a comma-separated list of ciphersuites.
/// Sets the context's minimal TLS version, specified as "VersionTLS1[0..3]", a comma-separated list of ciphersuites, and a colon-separated list of curves.
///
pub fn set_min_tls_version_and_ciphersuites(&mut self, min_tls_version: &Option<String>, ciphersuites: &Option<String>) -> Result<(), ErrorEx>{
pub fn set_min_tls_version_and_ciphersuites(&mut self, min_tls_version: &Option<String>, ciphersuites: &Option<String>, curves: &Option<String>) -> Result<(), ErrorEx>{
let mut min_proto_version = SslVersion::TLS1;
if let Some(min_tls_version) = min_tls_version {
min_proto_version = match min_tls_version.as_str() {
Expand All @@ -1800,6 +1800,14 @@ impl SslContextBuilder {
return Err(ErrorEx::InvalidCiphersuite);
}
}
if let Some(ref curves) = curves {
if !curves.is_empty() {
self.set_groups_list(curves)
.map_err(|e| ErrorEx::InvalidCurve { error_stack: e })?;
} else {
return Err(ErrorEx::InvalidCurve { error_stack: crate::error::ErrorStack::get() });
}
}
Ok(())
}
}
Expand Down