forked from sfackler/rust-postgres
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlib.rs
100 lines (83 loc) · 2.35 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
pub extern crate openssl;
extern crate postgres;
use openssl::error::ErrorStack;
use openssl::ssl::{ConnectConfiguration, SslConnector, SslMethod, SslRef, SslStream};
use postgres::tls::{Stream, TlsHandshake, TlsStream};
use std::error::Error;
use std::fmt;
use std::io::{self, Read, Write};
#[cfg(test)]
mod test;
pub struct OpenSsl {
connector: SslConnector,
config: Box<Fn(&mut ConnectConfiguration) -> Result<(), ErrorStack> + Sync + Send>,
}
impl fmt::Debug for OpenSsl {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("OpenSsl").finish()
}
}
impl OpenSsl {
pub fn new() -> Result<OpenSsl, ErrorStack> {
let connector = SslConnector::builder(SslMethod::tls())?.build();
Ok(OpenSsl::with_connector(connector))
}
pub fn with_connector(connector: SslConnector) -> OpenSsl {
OpenSsl {
connector,
config: Box::new(|_| Ok(())),
}
}
pub fn callback<F>(&mut self, f: F)
where
F: Fn(&mut ConnectConfiguration) -> Result<(), ErrorStack> + 'static + Sync + Send,
{
self.config = Box::new(f);
}
}
impl TlsHandshake for OpenSsl {
fn tls_handshake(
&self,
domain: &str,
stream: Stream,
) -> Result<Box<TlsStream>, Box<Error + Sync + Send>> {
let mut ssl = self.connector.configure()?;
(self.config)(&mut ssl)?;
let stream = ssl.connect(domain, stream)?;
Ok(Box::new(OpenSslStream(stream)))
}
}
#[derive(Debug)]
struct OpenSslStream(SslStream<Stream>);
impl Read for OpenSslStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
}
impl Write for OpenSslStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.0.flush()
}
}
impl TlsStream for OpenSslStream {
fn get_ref(&self) -> &Stream {
self.0.get_ref()
}
fn get_mut(&mut self) -> &mut Stream {
self.0.get_mut()
}
fn tls_unique(&self) -> Option<Vec<u8>> {
let f = if self.0.ssl().session_reused() {
SslRef::peer_finished
} else {
SslRef::finished
};
let len = f(self.0.ssl(), &mut []);
let mut buf = vec![0; len];
f(self.0.ssl(), &mut buf);
Some(buf)
}
}