Skip to content

Commit 6edab70

Browse files
committed
Channel binding support in tokio-postgres
1 parent 705ef7d commit 6edab70

File tree

3 files changed

+65
-7
lines changed

3 files changed

+65
-7
lines changed

tokio-postgres-openssl/src/lib.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ extern crate tokio;
1111
use bytes::{Buf, BufMut};
1212
use futures::{Future, IntoFuture, Poll};
1313
use openssl::error::ErrorStack;
14-
use openssl::ssl::{ConnectConfiguration, SslConnector, SslMethod};
14+
use openssl::ssl::{ConnectConfiguration, SslConnector, SslMethod, SslRef};
1515
use std::error::Error;
1616
use std::io::{self, Read, Write};
1717
use tokio_io::{AsyncRead, AsyncWrite};
@@ -124,4 +124,18 @@ impl AsyncWrite for SslStream {
124124
}
125125
}
126126

127-
impl TlsStream for SslStream {}
127+
impl TlsStream for SslStream {
128+
fn tls_unique(&self) -> Option<Vec<u8>> {
129+
let f = if self.0.get_ref().ssl().session_reused() {
130+
SslRef::peer_finished
131+
} else {
132+
SslRef::finished
133+
};
134+
135+
let len = f(self.0.get_ref().ssl(), &mut []);
136+
let mut buf = vec![0; len];
137+
f(self.0.get_ref().ssl(), &mut buf);
138+
139+
Some(buf)
140+
}
141+
}

tokio-postgres/src/proto/handshake.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -263,25 +263,49 @@ impl PollHandshake for Handshake {
263263
let pass = state.user.password().ok_or_else(missing_password)?;
264264

265265
let mut has_scram = false;
266+
let mut has_scram_plus = false;
266267
let mut mechanisms = body.mechanisms();
267268
while let Some(mechanism) = mechanisms.next()? {
268269
match mechanism {
269270
sasl::SCRAM_SHA_256 => has_scram = true,
271+
sasl::SCRAM_SHA_256_PLUS => has_scram_plus = true,
270272
_ => {}
271273
}
272274
}
275+
let channel_binding = state
276+
.stream
277+
.get_ref()
278+
.tls_unique()
279+
.map(ChannelBinding::tls_unique)
280+
.or_else(|| {
281+
state
282+
.stream
283+
.get_ref()
284+
.tls_server_end_point()
285+
.map(ChannelBinding::tls_server_end_point)
286+
});
273287

274-
if !has_scram {
288+
let (channel_binding, mechanism) = if has_scram_plus {
289+
match channel_binding {
290+
Some(channel_binding) => (channel_binding, sasl::SCRAM_SHA_256_PLUS),
291+
None => (ChannelBinding::unsupported(), sasl::SCRAM_SHA_256),
292+
}
293+
} else if has_scram {
294+
match channel_binding {
295+
Some(_) => (ChannelBinding::unrequested(), sasl::SCRAM_SHA_256),
296+
None => (ChannelBinding::unsupported(), sasl::SCRAM_SHA_256),
297+
}
298+
} else {
275299
return Err(io::Error::new(
276300
io::ErrorKind::Other,
277301
"unsupported SASL authentication",
278302
).into());
279-
}
303+
};
280304

281-
let mut scram = ScramSha256::new(pass.as_bytes(), ChannelBinding::unsupported())?;
305+
let mut scram = ScramSha256::new(pass.as_bytes(), channel_binding)?;
282306

283307
let mut buf = vec![];
284-
frontend::sasl_initial_response(sasl::SCRAM_SHA_256, scram.message(), &mut buf)?;
308+
frontend::sasl_initial_response(mechanism, scram.message(), &mut buf)?;
285309

286310
transition!(SendingSasl {
287311
future: state.stream.send(buf),

tokio-postgres/src/tls.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,26 @@ pub trait TlsConnect {
5858
) -> Box<Future<Item = Box<TlsStream>, Error = Box<Error + Sync + Send>> + Sync + Send>;
5959
}
6060

61-
pub trait TlsStream: 'static + Sync + Send + AsyncRead + AsyncWrite {}
61+
pub trait TlsStream: 'static + Sync + Send + AsyncRead + AsyncWrite {
62+
/// Returns the data associated with the `tls-unique` channel binding type as described in
63+
/// [RFC 5929], if supported.
64+
///
65+
/// An implementation only needs to support one of this or `tls_server_end_point`.
66+
///
67+
/// [RFC 5929]: https://tools.ietf.org/html/rfc5929
68+
fn tls_unique(&self) -> Option<Vec<u8>> {
69+
None
70+
}
71+
72+
/// Returns the data associated with the `tls-server-end-point` channel binding type as
73+
/// described in [RFC 5929], if supported.
74+
///
75+
/// An implementation only needs to support one of this or `tls_unique`.
76+
///
77+
/// [RFC 5929]: https://tools.ietf.org/html/rfc5929
78+
fn tls_server_end_point(&self) -> Option<Vec<u8>> {
79+
None
80+
}
81+
}
6282

6383
impl TlsStream for proto::Socket {}

0 commit comments

Comments
 (0)