Skip to content

Commit c70a03f

Browse files
committed
Split out TLS implementations
This provides a lot more flexibility around version support, and unlike the ToSql/FromSql implementations, these don't actually need to be in postgres itself.
1 parent 374d0ca commit c70a03f

File tree

16 files changed

+262
-381
lines changed

16 files changed

+262
-381
lines changed

.circleci/config.yml

+2-4
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ jobs:
2929
- image: sfackler/rust-postgres-test:3
3030
steps:
3131
- checkout
32-
- run: apt-get update
33-
- run: DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends jq
3432
- *RESTORE_REGISTRY
3533
- run: cargo generate-lockfile
3634
- run: cargo update -p nalgebra --precise 0.14.3 # 0.14.4 requires 1.26 :(
@@ -39,6 +37,6 @@ jobs:
3937
- run: rustc --version > ~/rust-version
4038
- *RESTORE_DEPS
4139
- run: cargo test --all
42-
- run: cargo test --manifest-path=postgres/Cargo.toml --features "$(cargo read-manifest --manifest-path=postgres/Cargo.toml | jq -r '.features|keys|map(select(. != "with-security-framework" and . != "with-schannel"))|join(" ")')"
43-
- run: cargo test --manifest-path=tokio-postgres/Cargo.toml --all-features
40+
- run: cargo test -p postgres --all-features
41+
- run: cargo test -p tokio-postgres --all-features
4442
- *SAVE_DEPS

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@ members = [
44
"postgres",
55
"postgres-protocol",
66
"postgres-shared",
7-
"tokio-postgres"
7+
"postgres-openssl",
8+
"postgres-native-tls",
9+
"tokio-postgres",
810
]

postgres-native-tls/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "postgres-native-tls"
3+
version = "0.1.0"
4+
authors = ["Steven Fackler <[email protected]>"]
5+
6+
[dependencies]
7+
native-tls = "0.1"
8+
9+
postgres = { version = "0.15", path = "../postgres" }

postgres-native-tls/src/lib.rs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
pub extern crate native_tls;
2+
extern crate postgres;
3+
4+
use native_tls::TlsConnector;
5+
use postgres::tls::{Stream, TlsHandshake, TlsStream};
6+
use std::error::Error;
7+
use std::fmt::{self, Debug};
8+
use std::io::{self, Read, Write};
9+
10+
#[cfg(test)]
11+
mod test;
12+
13+
pub struct NativeTls {
14+
connector: TlsConnector,
15+
}
16+
17+
impl Debug for NativeTls {
18+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
19+
fmt.debug_struct("NativeTls").finish()
20+
}
21+
}
22+
23+
impl NativeTls {
24+
pub fn new() -> Result<NativeTls, native_tls::Error> {
25+
let connector = TlsConnector::builder()?.build()?;
26+
Ok(NativeTls::with_connector(connector))
27+
}
28+
29+
pub fn with_connector(connector: TlsConnector) -> NativeTls {
30+
NativeTls { connector }
31+
}
32+
}
33+
34+
impl TlsHandshake for NativeTls {
35+
fn tls_handshake(
36+
&self,
37+
domain: &str,
38+
stream: Stream,
39+
) -> Result<Box<TlsStream>, Box<Error + Sync + Send>> {
40+
let stream = self.connector.connect(domain, stream)?;
41+
Ok(Box::new(NativeTlsStream(stream)))
42+
}
43+
}
44+
45+
#[derive(Debug)]
46+
struct NativeTlsStream(native_tls::TlsStream<Stream>);
47+
48+
impl Read for NativeTlsStream {
49+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
50+
self.0.read(buf)
51+
}
52+
}
53+
54+
impl Write for NativeTlsStream {
55+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
56+
self.0.write(buf)
57+
}
58+
59+
fn flush(&mut self) -> io::Result<()> {
60+
self.0.flush()
61+
}
62+
}
63+
64+
impl TlsStream for NativeTlsStream {
65+
fn get_ref(&self) -> &Stream {
66+
self.0.get_ref()
67+
}
68+
69+
fn get_mut(&mut self) -> &mut Stream {
70+
self.0.get_mut()
71+
}
72+
}

postgres-native-tls/src/test.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use native_tls::{Certificate, TlsConnector};
2+
use postgres::{Connection, TlsMode};
3+
4+
use NativeTls;
5+
6+
#[test]
7+
fn connect() {
8+
let cert = include_bytes!("../../test/server.crt");
9+
let cert = Certificate::from_pem(cert).unwrap();
10+
11+
let mut builder = TlsConnector::builder().unwrap();
12+
builder.add_root_certificate(cert).unwrap();
13+
let connector = builder.build().unwrap();
14+
15+
let handshake = NativeTls::with_connector(connector);
16+
let conn = Connection::connect(
17+
"postgres://ssl_user@localhost:5433/postgres",
18+
TlsMode::Require(&handshake),
19+
).unwrap();
20+
conn.execute("SELECT 1::VARCHAR", &[]).unwrap();
21+
}

postgres-openssl/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "postgres-openssl"
3+
version = "0.1.0"
4+
authors = ["Steven Fackler <[email protected]>"]
5+
6+
[dependencies]
7+
openssl = "0.10"
8+
9+
postgres = { version = "0.15", path = "../postgres" }

postgres-openssl/src/lib.rs

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
pub extern crate openssl;
2+
extern crate postgres;
3+
4+
use openssl::error::ErrorStack;
5+
use openssl::ssl::{ConnectConfiguration, SslConnector, SslMethod, SslStream};
6+
use postgres::tls::{Stream, TlsHandshake, TlsStream};
7+
use std::error::Error;
8+
use std::fmt;
9+
use std::io::{self, Read, Write};
10+
11+
#[cfg(test)]
12+
mod test;
13+
14+
pub struct OpenSsl {
15+
connector: SslConnector,
16+
config: Box<Fn(&mut ConnectConfiguration) -> Result<(), ErrorStack> + Sync + Send>,
17+
}
18+
19+
impl fmt::Debug for OpenSsl {
20+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
21+
fmt.debug_struct("OpenSsl").finish()
22+
}
23+
}
24+
25+
impl OpenSsl {
26+
pub fn new() -> Result<OpenSsl, ErrorStack> {
27+
let connector = SslConnector::builder(SslMethod::tls())?.build();
28+
Ok(OpenSsl::with_connector(connector))
29+
}
30+
31+
pub fn with_connector(connector: SslConnector) -> OpenSsl {
32+
OpenSsl {
33+
connector,
34+
config: Box::new(|_| Ok(())),
35+
}
36+
}
37+
38+
pub fn callback<F>(&mut self, f: F)
39+
where
40+
F: Fn(&mut ConnectConfiguration) -> Result<(), ErrorStack> + 'static + Sync + Send,
41+
{
42+
self.config = Box::new(f);
43+
}
44+
}
45+
46+
impl TlsHandshake for OpenSsl {
47+
fn tls_handshake(
48+
&self,
49+
domain: &str,
50+
stream: Stream,
51+
) -> Result<Box<TlsStream>, Box<Error + Sync + Send>> {
52+
let mut ssl = self.connector.configure()?;
53+
(self.config)(&mut ssl)?;
54+
let stream = ssl.connect(domain, stream)?;
55+
56+
Ok(Box::new(OpenSslStream(stream)))
57+
}
58+
}
59+
60+
#[derive(Debug)]
61+
struct OpenSslStream(SslStream<Stream>);
62+
63+
impl Read for OpenSslStream {
64+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
65+
self.0.read(buf)
66+
}
67+
}
68+
69+
impl Write for OpenSslStream {
70+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
71+
self.0.write(buf)
72+
}
73+
74+
fn flush(&mut self) -> io::Result<()> {
75+
self.0.flush()
76+
}
77+
}
78+
79+
impl TlsStream for OpenSslStream {
80+
fn get_ref(&self) -> &Stream {
81+
self.0.get_ref()
82+
}
83+
84+
fn get_mut(&mut self) -> &mut Stream {
85+
self.0.get_mut()
86+
}
87+
}

postgres-openssl/src/test.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use openssl::ssl::{SslConnector, SslMethod};
2+
use postgres::{Connection, TlsMode};
3+
4+
use OpenSsl;
5+
6+
#[test]
7+
fn test_require_ssl_conn() {
8+
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
9+
builder.set_ca_file("../test/server.crt").unwrap();
10+
let negotiator = OpenSsl::with_connector(builder.build());
11+
let conn = Connection::connect(
12+
"postgres://ssl_user@localhost:5433/postgres",
13+
TlsMode::Require(&negotiator),
14+
).unwrap();
15+
conn.execute("SELECT 1::VARCHAR", &[]).unwrap();
16+
}
17+
18+
#[test]
19+
fn test_prefer_ssl_conn() {
20+
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
21+
builder.set_ca_file("../test/server.crt").unwrap();
22+
let negotiator = OpenSsl::with_connector(builder.build());
23+
let conn = Connection::connect(
24+
"postgres://ssl_user@localhost:5433/postgres",
25+
TlsMode::Require(&negotiator),
26+
).unwrap();
27+
conn.execute("SELECT 1::VARCHAR", &[]).unwrap();
28+
}

postgres/Cargo.toml

-10
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,6 @@ path = "tests/test.rs"
4343
"with-serde_json-1" = ["postgres-shared/with-serde_json-1"]
4444
"with-uuid-0.6" = ["postgres-shared/with-uuid-0.6"]
4545

46-
with-openssl = ["openssl"]
47-
with-native-tls = ["native-tls"]
48-
with-schannel = ["schannel"]
49-
with-security-framework = ["security-framework"]
50-
5146
no-logging = []
5247

5348
[dependencies]
@@ -56,11 +51,6 @@ fallible-iterator = "0.1.3"
5651
log = "0.4"
5752
socket2 = { version = "0.3.5", features = ["unix"] }
5853

59-
openssl = { version = "0.9.23", optional = true }
60-
native-tls = { version = "0.1", optional = true }
61-
schannel = { version = "0.1", optional = true }
62-
security-framework = { version = "0.1.2", optional = true }
63-
6454
postgres-protocol = { version = "0.3.0", path = "../postgres-protocol" }
6555
postgres-shared = { version = "0.4.1", path = "../postgres-shared" }
6656

0 commit comments

Comments
 (0)