Skip to content

Commit 0f57ded

Browse files
authored
Merge pull request sfackler#2 from uce/6716-config
config: add sslmode `verify-ca` and `verify-full`
2 parents fea178c + 71e51f3 commit 0f57ded

File tree

3 files changed

+128
-8
lines changed

3 files changed

+128
-8
lines changed

postgres/src/config.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
use crate::connection::Connection;
66
use crate::Client;
77
use log::info;
8-
use std::fmt;
98
use std::path::Path;
109
use std::str::FromStr;
1110
use std::sync::Arc;
1211
use std::time::Duration;
12+
use std::{fmt, path::PathBuf};
1313
use tokio::runtime;
1414
#[doc(inline)]
1515
pub use tokio_postgres::config::{ChannelBinding, Host, SslMode, TargetSessionAttrs};
@@ -33,8 +33,12 @@ use tokio_postgres::{Error, Socket};
3333
/// * `dbname` - The name of the database to connect to. Defaults to the username.
3434
/// * `options` - Command line options used to configure the server.
3535
/// * `application_name` - Sets the `application_name` parameter on the server.
36+
/// * `sslcert` - Location of the client SSL certificate file.
37+
/// * `sslkey` - Location for the secret key file used for the client certificate.
3638
/// * `sslmode` - Controls usage of TLS. If set to `disable`, TLS will not be used. If set to `prefer`, TLS will be used
37-
/// if available, but not used otherwise. If set to `require`, TLS will be forced to be used. Defaults to `prefer`.
39+
/// if available, but not used otherwise. If set to `require`, `verify-ca`, or `verify-full`, TLS will be forced to
40+
/// be used. Defaults to `prefer`.
41+
/// * `sslrootcert` - Location of SSL certificate authority (CA) certificate.
3842
/// * `host` - The host to connect to. On Unix platforms, if the host starts with a `/` character it is treated as the
3943
/// path to the directory containing Unix domain sockets. Otherwise, it is treated as a hostname. Multiple hosts
4044
/// can be specified, separated by commas. Each host will be tried in turn when connecting. Required if connecting
@@ -183,6 +187,32 @@ impl Config {
183187
self.config.get_application_name()
184188
}
185189

190+
/// Sets the location of the client SSL certificate file.
191+
///
192+
/// Defaults to `None`.
193+
pub fn ssl_cert(&mut self, ssl_cert: &str) -> &mut Config {
194+
self.config.ssl_cert(ssl_cert);
195+
self
196+
}
197+
198+
/// Gets the location of the client SSL certificate file.
199+
pub fn get_ssl_cert(&self) -> Option<PathBuf> {
200+
self.config.get_ssl_cert()
201+
}
202+
203+
/// Sets the location of the secret key file used for the client certificate.
204+
///
205+
/// Defaults to `None`.
206+
pub fn ssl_key(&mut self, ssl_key: &str) -> &mut Config {
207+
self.config.ssl_key(ssl_key);
208+
self
209+
}
210+
211+
/// Gets the location of the secret key file used for the client certificate.
212+
pub fn get_ssl_key(&self) -> Option<PathBuf> {
213+
self.config.get_ssl_key()
214+
}
215+
186216
/// Sets the SSL configuration.
187217
///
188218
/// Defaults to `prefer`.
@@ -196,6 +226,19 @@ impl Config {
196226
self.config.get_ssl_mode()
197227
}
198228

229+
/// Sets the location of SSL certificate authority (CA) certificate.
230+
///
231+
/// Defaults to `None`.
232+
pub fn ssl_root_cert(&mut self, ssl_root_cert: &str) -> &mut Config {
233+
self.config.ssl_root_cert(ssl_root_cert);
234+
self
235+
}
236+
237+
/// Gets the location of SSL certificate authority (CA) certificate.
238+
pub fn get_ssl_root_cert(&self) -> Option<PathBuf> {
239+
self.config.get_ssl_root_cert()
240+
}
241+
199242
/// Adds a host to the configuration.
200243
///
201244
/// Multiple hosts can be specified by calling this method multiple times, and each will be tried in order. On Unix

tokio-postgres/src/config.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ pub enum SslMode {
4242
Prefer,
4343
/// Require the use of TLS.
4444
Require,
45+
/// Require the use of TLS.
46+
VerifyCa,
47+
/// Require the use of TLS.
48+
VerifyFull,
4549
}
4650

4751
/// Channel binding configuration.
@@ -94,8 +98,12 @@ pub enum Host {
9498
/// * `dbname` - The name of the database to connect to. Defaults to the username.
9599
/// * `options` - Command line options used to configure the server.
96100
/// * `application_name` - Sets the `application_name` parameter on the server.
101+
/// * `sslcert` - Location of the client SSL certificate file.
102+
/// * `sslkey` - Location for the secret key file used for the client certificate.
97103
/// * `sslmode` - Controls usage of TLS. If set to `disable`, TLS will not be used. If set to `prefer`, TLS will be used
98-
/// if available, but not used otherwise. If set to `require`, TLS will be forced to be used. Defaults to `prefer`.
104+
/// if available, but not used otherwise. If set to `require`, `verify-ca`, or `verify-full`, TLS will be forced to
105+
/// be used. Defaults to `prefer`.
106+
/// * `sslrootcert` - Location of SSL certificate authority (CA) certificate.
99107
/// * `host` - The host to connect to. On Unix platforms, if the host starts with a `/` character it is treated as the
100108
/// path to the directory containing Unix domain sockets. Otherwise, it is treated as a hostname. Multiple hosts
101109
/// can be specified, separated by commas. Each host will be tried in turn when connecting. Required if connecting
@@ -161,7 +169,10 @@ pub struct Config {
161169
pub(crate) dbname: Option<String>,
162170
pub(crate) options: Option<String>,
163171
pub(crate) application_name: Option<String>,
172+
pub(crate) ssl_cert: Option<PathBuf>,
173+
pub(crate) ssl_key: Option<PathBuf>,
164174
pub(crate) ssl_mode: SslMode,
175+
pub(crate) ssl_root_cert: Option<PathBuf>,
165176
pub(crate) host: Vec<Host>,
166177
pub(crate) port: Vec<u16>,
167178
pub(crate) connect_timeout: Option<Duration>,
@@ -187,7 +198,10 @@ impl Config {
187198
dbname: None,
188199
options: None,
189200
application_name: None,
201+
ssl_cert: None,
202+
ssl_key: None,
190203
ssl_mode: SslMode::Prefer,
204+
ssl_root_cert: None,
191205
host: vec![],
192206
port: vec![],
193207
connect_timeout: None,
@@ -266,6 +280,32 @@ impl Config {
266280
self.application_name.as_deref()
267281
}
268282

283+
/// Sets the location of the client SSL certificate file.
284+
///
285+
/// Defaults to `None`.
286+
pub fn ssl_cert(&mut self, ssl_cert: &str) -> &mut Config {
287+
self.ssl_cert = Some(PathBuf::from(ssl_cert));
288+
self
289+
}
290+
291+
/// Gets the location of the client SSL certificate file.
292+
pub fn get_ssl_cert(&self) -> Option<PathBuf> {
293+
self.ssl_cert.clone()
294+
}
295+
296+
/// Sets the location of the secret key file used for the client certificate.
297+
///
298+
/// Defaults to `None`.
299+
pub fn ssl_key(&mut self, ssl_key: &str) -> &mut Config {
300+
self.ssl_key = Some(PathBuf::from(ssl_key));
301+
self
302+
}
303+
304+
/// Gets the location of the secret key file used for the client certificate.
305+
pub fn get_ssl_key(&self) -> Option<PathBuf> {
306+
self.ssl_key.clone()
307+
}
308+
269309
/// Sets the SSL configuration.
270310
///
271311
/// Defaults to `prefer`.
@@ -279,6 +319,19 @@ impl Config {
279319
self.ssl_mode
280320
}
281321

322+
/// Sets the location of SSL certificate authority (CA) certificate.
323+
///
324+
/// Defaults to `None`.
325+
pub fn ssl_root_cert(&mut self, ssl_root_cert: &str) -> &mut Config {
326+
self.ssl_root_cert = Some(PathBuf::from(ssl_root_cert));
327+
self
328+
}
329+
330+
/// Gets the location of SSL certificate authority (CA) certificate.
331+
pub fn get_ssl_root_cert(&self) -> Option<PathBuf> {
332+
self.ssl_root_cert.clone()
333+
}
334+
282335
/// Adds a host to the configuration.
283336
///
284337
/// Multiple hosts can be specified by calling this method multiple times, and each will be tried in order. On Unix
@@ -427,15 +480,35 @@ impl Config {
427480
"application_name" => {
428481
self.application_name(&value);
429482
}
483+
"sslcert" => {
484+
if std::fs::metadata(&value).is_err() {
485+
return Err(Error::config_parse(Box::new(InvalidValue("sslcert"))));
486+
}
487+
self.ssl_cert(&value);
488+
}
489+
"sslkey" => {
490+
if std::fs::metadata(&value).is_err() {
491+
return Err(Error::config_parse(Box::new(InvalidValue("sslkey"))));
492+
}
493+
self.ssl_key(&value);
494+
}
430495
"sslmode" => {
431496
let mode = match value {
432497
"disable" => SslMode::Disable,
433498
"prefer" => SslMode::Prefer,
434499
"require" => SslMode::Require,
500+
"verify-ca" => SslMode::VerifyCa,
501+
"verify-full" => SslMode::VerifyFull,
435502
_ => return Err(Error::config_parse(Box::new(InvalidValue("sslmode")))),
436503
};
437504
self.ssl_mode(mode);
438505
}
506+
"sslrootcert" => {
507+
if std::fs::metadata(&value).is_err() {
508+
return Err(Error::config_parse(Box::new(InvalidValue("sslrootcert"))));
509+
}
510+
self.ssl_root_cert(&value);
511+
}
439512
"host" => {
440513
for host in value.split(',') {
441514
self.host(host);
@@ -574,7 +647,10 @@ impl fmt::Debug for Config {
574647
.field("dbname", &self.dbname)
575648
.field("options", &self.options)
576649
.field("application_name", &self.application_name)
650+
.field("ssl_cert", &self.ssl_cert)
651+
.field("ssl_key", &self.ssl_key)
577652
.field("ssl_mode", &self.ssl_mode)
653+
.field("ssl_root_cert", &self.ssl_root_cert)
578654
.field("host", &self.host)
579655
.field("port", &self.port)
580656
.field("connect_timeout", &self.connect_timeout)

tokio-postgres/src/connect_tls.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ where
2121
SslMode::Prefer if !tls.can_connect(ForcePrivateApi) => {
2222
return Ok(MaybeTlsStream::Raw(stream))
2323
}
24-
SslMode::Prefer | SslMode::Require => {}
24+
SslMode::Prefer | SslMode::Require | SslMode::VerifyCa | SslMode::VerifyFull => {}
2525
}
2626

2727
let mut buf = BytesMut::new();
@@ -32,10 +32,11 @@ where
3232
stream.read_exact(&mut buf).await.map_err(Error::io)?;
3333

3434
if buf[0] != b'S' {
35-
if SslMode::Require == mode {
36-
return Err(Error::tls("server does not support TLS".into()));
37-
} else {
38-
return Ok(MaybeTlsStream::Raw(stream));
35+
match mode {
36+
SslMode::Require | SslMode::VerifyCa | SslMode::VerifyFull => {
37+
return Err(Error::tls("server does not support TLS".into()))
38+
}
39+
SslMode::Disable | SslMode::Prefer => return Ok(MaybeTlsStream::Raw(stream)),
3940
}
4041
}
4142

0 commit comments

Comments
 (0)