use bytes::Bytes;
use cdbc::error::Error;
use crate::connection::stream::PgStream;
use crate::message::SslRequest;
use crate::{PgConnectOptions, PgSslMode};
pub(super) fn maybe_upgrade(
stream: &mut PgStream,
options: &PgConnectOptions,
) -> Result<(), Error> {
match options.ssl_mode {
PgSslMode::Allow | PgSslMode::Disable => {}
PgSslMode::Prefer => {
upgrade(stream, options)?;
}
PgSslMode::Require | PgSslMode::VerifyFull | PgSslMode::VerifyCa => {
if !upgrade(stream, options)? {
return Err(Error::Tls("server does not support TLS".into()));
}
}
}
Ok(())
}
fn upgrade(stream: &mut PgStream, options: &PgConnectOptions) -> Result<bool, Error> {
stream.send(SslRequest)?;
match stream.read::<Bytes>(1)?[0] {
b'S' => {
}
b'N' => {
return Ok(false);
}
other => {
return Err(err_protocol!(
"unexpected response from SSLRequest: 0x{:02x}",
other
));
}
}
let accept_invalid_certs = !matches!(
options.ssl_mode,
PgSslMode::VerifyCa | PgSslMode::VerifyFull
);
let accept_invalid_hostnames = !matches!(options.ssl_mode, PgSslMode::VerifyFull);
if !cfg!(feature = "native-tls") {
return cdbc::Result::Err(Error::from("must enable native-tls!"));
}
#[cfg(feature = "native-tls")]
stream.upgrade(
&options.host,
accept_invalid_certs,
accept_invalid_hostnames,
options.ssl_root_cert.as_ref(),
)
?;
Ok(true)
}