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.
This commit is contained in:
parent
374d0ca32e
commit
c70a03f9e6
@ -29,8 +29,6 @@ jobs:
|
||||
- image: sfackler/rust-postgres-test:3
|
||||
steps:
|
||||
- checkout
|
||||
- run: apt-get update
|
||||
- run: DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends jq
|
||||
- *RESTORE_REGISTRY
|
||||
- run: cargo generate-lockfile
|
||||
- run: cargo update -p nalgebra --precise 0.14.3 # 0.14.4 requires 1.26 :(
|
||||
@ -39,6 +37,6 @@ jobs:
|
||||
- run: rustc --version > ~/rust-version
|
||||
- *RESTORE_DEPS
|
||||
- run: cargo test --all
|
||||
- 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(" ")')"
|
||||
- run: cargo test --manifest-path=tokio-postgres/Cargo.toml --all-features
|
||||
- run: cargo test -p postgres --all-features
|
||||
- run: cargo test -p tokio-postgres --all-features
|
||||
- *SAVE_DEPS
|
||||
|
@ -4,5 +4,7 @@ members = [
|
||||
"postgres",
|
||||
"postgres-protocol",
|
||||
"postgres-shared",
|
||||
"tokio-postgres"
|
||||
"postgres-openssl",
|
||||
"postgres-native-tls",
|
||||
"tokio-postgres",
|
||||
]
|
||||
|
9
postgres-native-tls/Cargo.toml
Normal file
9
postgres-native-tls/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "postgres-native-tls"
|
||||
version = "0.1.0"
|
||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
native-tls = "0.1"
|
||||
|
||||
postgres = { version = "0.15", path = "../postgres" }
|
72
postgres-native-tls/src/lib.rs
Normal file
72
postgres-native-tls/src/lib.rs
Normal file
@ -0,0 +1,72 @@
|
||||
pub extern crate native_tls;
|
||||
extern crate postgres;
|
||||
|
||||
use native_tls::TlsConnector;
|
||||
use postgres::tls::{Stream, TlsHandshake, TlsStream};
|
||||
use std::error::Error;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
pub struct NativeTls {
|
||||
connector: TlsConnector,
|
||||
}
|
||||
|
||||
impl Debug for NativeTls {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("NativeTls").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeTls {
|
||||
pub fn new() -> Result<NativeTls, native_tls::Error> {
|
||||
let connector = TlsConnector::builder()?.build()?;
|
||||
Ok(NativeTls::with_connector(connector))
|
||||
}
|
||||
|
||||
pub fn with_connector(connector: TlsConnector) -> NativeTls {
|
||||
NativeTls { connector }
|
||||
}
|
||||
}
|
||||
|
||||
impl TlsHandshake for NativeTls {
|
||||
fn tls_handshake(
|
||||
&self,
|
||||
domain: &str,
|
||||
stream: Stream,
|
||||
) -> Result<Box<TlsStream>, Box<Error + Sync + Send>> {
|
||||
let stream = self.connector.connect(domain, stream)?;
|
||||
Ok(Box::new(NativeTlsStream(stream)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NativeTlsStream(native_tls::TlsStream<Stream>);
|
||||
|
||||
impl Read for NativeTlsStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for NativeTlsStream {
|
||||
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 NativeTlsStream {
|
||||
fn get_ref(&self) -> &Stream {
|
||||
self.0.get_ref()
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut Stream {
|
||||
self.0.get_mut()
|
||||
}
|
||||
}
|
21
postgres-native-tls/src/test.rs
Normal file
21
postgres-native-tls/src/test.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use native_tls::{Certificate, TlsConnector};
|
||||
use postgres::{Connection, TlsMode};
|
||||
|
||||
use NativeTls;
|
||||
|
||||
#[test]
|
||||
fn connect() {
|
||||
let cert = include_bytes!("../../test/server.crt");
|
||||
let cert = Certificate::from_pem(cert).unwrap();
|
||||
|
||||
let mut builder = TlsConnector::builder().unwrap();
|
||||
builder.add_root_certificate(cert).unwrap();
|
||||
let connector = builder.build().unwrap();
|
||||
|
||||
let handshake = NativeTls::with_connector(connector);
|
||||
let conn = Connection::connect(
|
||||
"postgres://ssl_user@localhost:5433/postgres",
|
||||
TlsMode::Require(&handshake),
|
||||
).unwrap();
|
||||
conn.execute("SELECT 1::VARCHAR", &[]).unwrap();
|
||||
}
|
9
postgres-openssl/Cargo.toml
Normal file
9
postgres-openssl/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "postgres-openssl"
|
||||
version = "0.1.0"
|
||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
openssl = "0.10"
|
||||
|
||||
postgres = { version = "0.15", path = "../postgres" }
|
87
postgres-openssl/src/lib.rs
Normal file
87
postgres-openssl/src/lib.rs
Normal file
@ -0,0 +1,87 @@
|
||||
pub extern crate openssl;
|
||||
extern crate postgres;
|
||||
|
||||
use openssl::error::ErrorStack;
|
||||
use openssl::ssl::{ConnectConfiguration, SslConnector, SslMethod, 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()
|
||||
}
|
||||
}
|
28
postgres-openssl/src/test.rs
Normal file
28
postgres-openssl/src/test.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use openssl::ssl::{SslConnector, SslMethod};
|
||||
use postgres::{Connection, TlsMode};
|
||||
|
||||
use OpenSsl;
|
||||
|
||||
#[test]
|
||||
fn test_require_ssl_conn() {
|
||||
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
|
||||
builder.set_ca_file("../test/server.crt").unwrap();
|
||||
let negotiator = OpenSsl::with_connector(builder.build());
|
||||
let conn = Connection::connect(
|
||||
"postgres://ssl_user@localhost:5433/postgres",
|
||||
TlsMode::Require(&negotiator),
|
||||
).unwrap();
|
||||
conn.execute("SELECT 1::VARCHAR", &[]).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prefer_ssl_conn() {
|
||||
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
|
||||
builder.set_ca_file("../test/server.crt").unwrap();
|
||||
let negotiator = OpenSsl::with_connector(builder.build());
|
||||
let conn = Connection::connect(
|
||||
"postgres://ssl_user@localhost:5433/postgres",
|
||||
TlsMode::Require(&negotiator),
|
||||
).unwrap();
|
||||
conn.execute("SELECT 1::VARCHAR", &[]).unwrap();
|
||||
}
|
@ -43,11 +43,6 @@ path = "tests/test.rs"
|
||||
"with-serde_json-1" = ["postgres-shared/with-serde_json-1"]
|
||||
"with-uuid-0.6" = ["postgres-shared/with-uuid-0.6"]
|
||||
|
||||
with-openssl = ["openssl"]
|
||||
with-native-tls = ["native-tls"]
|
||||
with-schannel = ["schannel"]
|
||||
with-security-framework = ["security-framework"]
|
||||
|
||||
no-logging = []
|
||||
|
||||
[dependencies]
|
||||
@ -56,11 +51,6 @@ fallible-iterator = "0.1.3"
|
||||
log = "0.4"
|
||||
socket2 = { version = "0.3.5", features = ["unix"] }
|
||||
|
||||
openssl = { version = "0.9.23", optional = true }
|
||||
native-tls = { version = "0.1", optional = true }
|
||||
schannel = { version = "0.1", optional = true }
|
||||
security-framework = { version = "0.1.2", optional = true }
|
||||
|
||||
postgres-protocol = { version = "0.3.0", path = "../postgres-protocol" }
|
||||
postgres-shared = { version = "0.4.1", path = "../postgres-shared" }
|
||||
|
||||
|
@ -100,10 +100,10 @@ use params::{IntoConnectParams, User};
|
||||
use priv_io::MessageStream;
|
||||
use rows::Rows;
|
||||
use stmt::{Column, Statement};
|
||||
use text_rows::TextRows;
|
||||
use tls::TlsHandshake;
|
||||
use transaction::{IsolationLevel, Transaction};
|
||||
use types::{Field, FromSql, IsNull, Kind, Oid, ToSql, Type};
|
||||
use text_rows::TextRows;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use error::Error;
|
||||
@ -119,8 +119,8 @@ pub mod notification;
|
||||
pub mod params;
|
||||
mod priv_io;
|
||||
pub mod rows;
|
||||
pub mod text_rows;
|
||||
pub mod stmt;
|
||||
pub mod text_rows;
|
||||
pub mod tls;
|
||||
pub mod transaction;
|
||||
|
||||
@ -423,7 +423,8 @@ impl InnerConnection {
|
||||
}
|
||||
backend::Message::AuthenticationSasl(body) => {
|
||||
// count to validate the entire message body.
|
||||
if body.mechanisms()
|
||||
if body
|
||||
.mechanisms()
|
||||
.filter(|m| *m == sasl::SCRAM_SHA_256)
|
||||
.count()? == 0
|
||||
{
|
||||
@ -726,10 +727,10 @@ impl InnerConnection {
|
||||
Ok(ty)
|
||||
}
|
||||
|
||||
|
||||
fn parse_cols(&mut self, raw: Option<backend::RowDescriptionBody>) -> Result<Vec<Column>> {
|
||||
match raw {
|
||||
Some(body) => body.fields()
|
||||
Some(body) => body
|
||||
.fields()
|
||||
.and_then(|field| {
|
||||
Ok(Column::new(
|
||||
field.name().to_owned(),
|
||||
@ -865,8 +866,9 @@ impl InnerConnection {
|
||||
|
||||
let mut variants = vec![];
|
||||
for row in rows {
|
||||
variants
|
||||
.push(String::from_sql_nullable(&Type::NAME, row.get(0)).map_err(error::conversion)?);
|
||||
variants.push(
|
||||
String::from_sql_nullable(&Type::NAME, row.get(0)).map_err(error::conversion)?
|
||||
);
|
||||
}
|
||||
|
||||
Ok(variants)
|
||||
@ -929,7 +931,8 @@ impl InnerConnection {
|
||||
fn simple_query_(&mut self, query: &str) -> Result<Vec<TextRows>> {
|
||||
check_desync!(self);
|
||||
debug!("executing query: {}", query);
|
||||
self.stream.write_message(|buf| frontend::query(query, buf))?;
|
||||
self.stream
|
||||
.write_message(|buf| frontend::query(query, buf))?;
|
||||
self.stream.flush()?;
|
||||
|
||||
let mut result = vec![];
|
||||
@ -946,9 +949,8 @@ impl InnerConnection {
|
||||
self.stream.write_message(|buf| {
|
||||
frontend::copy_fail("COPY queries cannot be directly executed", buf)
|
||||
})?;
|
||||
self.stream.write_message(
|
||||
|buf| Ok::<(), io::Error>(frontend::sync(buf)),
|
||||
)?;
|
||||
self.stream
|
||||
.write_message(|buf| Ok::<(), io::Error>(frontend::sync(buf)))?;
|
||||
self.stream.flush()?;
|
||||
}
|
||||
backend::Message::ErrorResponse(body) => {
|
||||
@ -981,7 +983,8 @@ impl InnerConnection {
|
||||
match self.read_message()? {
|
||||
backend::Message::ReadyForQuery(_) => break,
|
||||
backend::Message::DataRow(body) => {
|
||||
let row = body.ranges()
|
||||
let row = body
|
||||
.ranges()
|
||||
.map(|r| r.map(|r| String::from_utf8_lossy(&body.buffer()[r]).into_owned()))
|
||||
.collect()?;
|
||||
result.push(row);
|
||||
@ -1304,8 +1307,7 @@ impl Connection {
|
||||
pub fn set_transaction_config(&self, config: &transaction::Config) -> Result<()> {
|
||||
let mut command = "SET SESSION CHARACTERISTICS AS TRANSACTION".to_owned();
|
||||
config.build_command(&mut command);
|
||||
self.simple_query(&command)
|
||||
.map(|_| ())
|
||||
self.simple_query(&command).map(|_| ())
|
||||
}
|
||||
|
||||
/// Execute a sequence of SQL statements.
|
||||
@ -1342,12 +1344,11 @@ impl Connection {
|
||||
/// CREATE INDEX ON purchase (time);
|
||||
/// ").unwrap();
|
||||
/// ```
|
||||
#[deprecated(since="0.15.3", note="please use `simple_query` instead")]
|
||||
#[deprecated(since = "0.15.3", note = "please use `simple_query` instead")]
|
||||
pub fn batch_execute(&self, query: &str) -> Result<()> {
|
||||
self.0.borrow_mut().quick_query(query).map(|_| ())
|
||||
}
|
||||
|
||||
|
||||
/// Send a simple, non-prepared query
|
||||
///
|
||||
/// Executes a query without making a prepared statement. All result columns
|
||||
@ -1451,7 +1452,7 @@ pub trait GenericConnection {
|
||||
fn transaction<'a>(&'a self) -> Result<Transaction<'a>>;
|
||||
|
||||
/// Like `Connection::batch_execute`.
|
||||
#[deprecated(since="0.15.3", note="please use `simple_query` instead")]
|
||||
#[deprecated(since = "0.15.3", note = "please use `simple_query` instead")]
|
||||
fn batch_execute(&self, query: &str) -> Result<()>;
|
||||
|
||||
/// Like `Connection::is_active`.
|
||||
@ -1483,8 +1484,7 @@ impl GenericConnection for Connection {
|
||||
}
|
||||
|
||||
fn batch_execute(&self, query: &str) -> Result<()> {
|
||||
self.simple_query(query)
|
||||
.map(|_| ())
|
||||
self.simple_query(query).map(|_| ())
|
||||
}
|
||||
|
||||
fn is_active(&self) -> bool {
|
||||
@ -1518,8 +1518,7 @@ impl<'a> GenericConnection for Transaction<'a> {
|
||||
}
|
||||
|
||||
fn batch_execute(&self, query: &str) -> Result<()> {
|
||||
self.simple_query(query)
|
||||
.map(|_| ())
|
||||
self.simple_query(query).map(|_| ())
|
||||
}
|
||||
|
||||
fn simple_query(&self, query: &str) -> Result<Vec<TextRows>> {
|
||||
|
@ -2,17 +2,8 @@
|
||||
pub use priv_io::Stream;
|
||||
|
||||
use std::error::Error;
|
||||
use std::io::prelude::*;
|
||||
use std::fmt;
|
||||
|
||||
#[cfg(feature = "with-native-tls")]
|
||||
pub mod native_tls;
|
||||
#[cfg(feature = "with-openssl")]
|
||||
pub mod openssl;
|
||||
#[cfg(feature = "with-schannel")]
|
||||
pub mod schannel;
|
||||
#[cfg(feature = "with-security-framework")]
|
||||
pub mod security_framework;
|
||||
use std::io::prelude::*;
|
||||
|
||||
/// A trait implemented by TLS streams.
|
||||
pub trait TlsStream: fmt::Debug + Read + Write + Send {
|
@ -1,65 +0,0 @@
|
||||
//! Native TLS support.
|
||||
pub extern crate native_tls;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use self::native_tls::TlsConnector;
|
||||
use tls::{TlsStream, Stream, TlsHandshake};
|
||||
|
||||
impl TlsStream for native_tls::TlsStream<Stream> {
|
||||
fn get_ref(&self) -> &Stream {
|
||||
self.get_ref()
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut Stream {
|
||||
self.get_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `TlsHandshake` implementation that uses the native-tls crate.
|
||||
///
|
||||
/// Requires the `with-native-tls` feature.
|
||||
pub struct NativeTls(TlsConnector);
|
||||
|
||||
impl fmt::Debug for NativeTls {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("NativeTls").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeTls {
|
||||
/// Creates a new `NativeTls` with its default configuration.
|
||||
pub fn new() -> Result<NativeTls, native_tls::Error> {
|
||||
let connector = TlsConnector::builder()?;
|
||||
let connector = connector.build()?;
|
||||
Ok(NativeTls(connector))
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner `TlsConnector`.
|
||||
pub fn connector(&self) -> &TlsConnector {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner `TlsConnector`.
|
||||
pub fn connector_mut(&mut self) -> &mut TlsConnector {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TlsConnector> for NativeTls {
|
||||
fn from(connector: TlsConnector) -> NativeTls {
|
||||
NativeTls(connector)
|
||||
}
|
||||
}
|
||||
|
||||
impl TlsHandshake for NativeTls {
|
||||
fn tls_handshake(
|
||||
&self,
|
||||
domain: &str,
|
||||
stream: Stream,
|
||||
) -> Result<Box<TlsStream>, Box<Error + Send + Sync>> {
|
||||
let stream = self.0.connect(domain, stream)?;
|
||||
Ok(Box::new(stream))
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
//! OpenSSL support.
|
||||
pub extern crate openssl;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use self::openssl::error::ErrorStack;
|
||||
use self::openssl::ssl::{SslMethod, SslConnector, SslConnectorBuilder, SslStream};
|
||||
use tls::{TlsStream, Stream, TlsHandshake};
|
||||
|
||||
impl TlsStream for SslStream<Stream> {
|
||||
fn get_ref(&self) -> &Stream {
|
||||
self.get_ref()
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut Stream {
|
||||
self.get_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `TlsHandshake` implementation that uses OpenSSL.
|
||||
///
|
||||
/// Requires the `with-openssl` feature.
|
||||
pub struct OpenSsl {
|
||||
connector: SslConnector,
|
||||
disable_verification: bool,
|
||||
}
|
||||
|
||||
impl fmt::Debug for OpenSsl {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("OpenSsl").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenSsl {
|
||||
/// Creates a `OpenSsl` with `SslConnector`'s default configuration.
|
||||
pub fn new() -> Result<OpenSsl, ErrorStack> {
|
||||
let connector = SslConnectorBuilder::new(SslMethod::tls())?.build();
|
||||
Ok(OpenSsl::from(connector))
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner `SslConnector`.
|
||||
pub fn connector(&self) -> &SslConnector {
|
||||
&self.connector
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner `SslConnector`.
|
||||
pub fn connector_mut(&mut self) -> &mut SslConnector {
|
||||
&mut self.connector
|
||||
}
|
||||
|
||||
/// If set, the
|
||||
/// `SslConnector::danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication`
|
||||
/// method will be used to connect.
|
||||
///
|
||||
/// If certificate verification has been disabled in the `SslConnector`, verification must be
|
||||
/// additionally disabled here for that setting to take effect.
|
||||
pub fn danger_disable_hostname_verification(&mut self, disable_verification: bool) {
|
||||
self.disable_verification = disable_verification;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SslConnector> for OpenSsl {
|
||||
fn from(connector: SslConnector) -> OpenSsl {
|
||||
OpenSsl {
|
||||
connector: connector,
|
||||
disable_verification: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TlsHandshake for OpenSsl {
|
||||
fn tls_handshake(
|
||||
&self,
|
||||
domain: &str,
|
||||
stream: Stream,
|
||||
) -> Result<Box<TlsStream>, Box<Error + Send + Sync>> {
|
||||
let stream = if self.disable_verification {
|
||||
self.connector.danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(stream)?
|
||||
} else {
|
||||
self.connector.connect(domain, stream)?
|
||||
};
|
||||
Ok(Box::new(stream))
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
//! SChannel support.
|
||||
|
||||
pub extern crate schannel;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use self::schannel::schannel_cred::{SchannelCred, Direction};
|
||||
use self::schannel::tls_stream;
|
||||
use tls::{TlsStream, Stream, TlsHandshake};
|
||||
|
||||
impl TlsStream for tls_stream::TlsStream<Stream> {
|
||||
fn get_ref(&self) -> &Stream {
|
||||
self.get_ref()
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut Stream {
|
||||
self.get_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `TlsHandshake` implementation that uses the `schannel` crate.
|
||||
///
|
||||
/// Requires the `with-schannel` feature.
|
||||
pub struct Schannel(());
|
||||
|
||||
impl fmt::Debug for Schannel {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_struct("Schannel").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Schannel {
|
||||
/// Constructs a new `SChannel` with a default configuration.
|
||||
pub fn new() -> Schannel {
|
||||
Schannel(())
|
||||
}
|
||||
}
|
||||
|
||||
impl TlsHandshake for Schannel {
|
||||
fn tls_handshake(
|
||||
&self,
|
||||
host: &str,
|
||||
stream: Stream,
|
||||
) -> Result<Box<TlsStream>, Box<Error + Sync + Send>> {
|
||||
let creds = SchannelCred::builder().acquire(Direction::Outbound)?;
|
||||
let stream = tls_stream::Builder::new().domain(host).connect(
|
||||
creds,
|
||||
stream,
|
||||
)?;
|
||||
Ok(Box::new(stream))
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
//! Security Framework support.
|
||||
pub extern crate security_framework;
|
||||
|
||||
use self::security_framework::secure_transport::{SslStream, ClientBuilder};
|
||||
use tls::{Stream, TlsStream, TlsHandshake};
|
||||
use std::error::Error;
|
||||
|
||||
impl TlsStream for SslStream<Stream> {
|
||||
fn get_ref(&self) -> &Stream {
|
||||
self.get_ref()
|
||||
}
|
||||
|
||||
fn get_mut(&mut self) -> &mut Stream {
|
||||
self.get_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// A `TlsHandshake` implementation that uses the Security Framework.
|
||||
///
|
||||
/// Requires the `with-security-framework` feature.
|
||||
#[derive(Debug)]
|
||||
pub struct SecurityFramework(ClientBuilder);
|
||||
|
||||
impl SecurityFramework {
|
||||
/// Returns a new `SecurityFramework` with default settings.
|
||||
pub fn new() -> SecurityFramework {
|
||||
ClientBuilder::new().into()
|
||||
}
|
||||
|
||||
/// Returns a reference to the associated `ClientBuilder`.
|
||||
pub fn builder(&self) -> &ClientBuilder {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the associated `ClientBuilder`.
|
||||
pub fn builder_mut(&mut self) -> &mut ClientBuilder {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ClientBuilder> for SecurityFramework {
|
||||
fn from(b: ClientBuilder) -> SecurityFramework {
|
||||
SecurityFramework(b)
|
||||
}
|
||||
}
|
||||
|
||||
impl TlsHandshake for SecurityFramework {
|
||||
fn tls_handshake(
|
||||
&self,
|
||||
domain: &str,
|
||||
stream: Stream,
|
||||
) -> Result<Box<TlsStream>, Box<Error + Send + Sync>> {
|
||||
let stream = self.0.handshake(domain, stream)?;
|
||||
Ok(Box::new(stream))
|
||||
}
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
extern crate fallible_iterator;
|
||||
#[cfg(feature = "native-tls")]
|
||||
extern crate native_tls;
|
||||
#[cfg(feature = "with-openssl")]
|
||||
extern crate openssl;
|
||||
extern crate postgres;
|
||||
extern crate url;
|
||||
|
||||
#[macro_use]
|
||||
extern crate postgres_shared;
|
||||
#[cfg(feature = "with-security-framework")]
|
||||
extern crate security_framework;
|
||||
extern crate url;
|
||||
|
||||
use fallible_iterator::FallibleIterator;
|
||||
use postgres::error::ErrorPosition::Normal;
|
||||
@ -908,70 +903,6 @@ fn test_cancel_query() {
|
||||
t.join().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-openssl")]
|
||||
fn test_require_ssl_conn() {
|
||||
use openssl::ssl::{SslConnectorBuilder, SslMethod};
|
||||
use postgres::tls::openssl::OpenSsl;
|
||||
|
||||
let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
|
||||
builder.set_ca_file("../test/server.crt").unwrap();
|
||||
let negotiator = OpenSsl::from(builder.build());
|
||||
let conn = or_panic!(Connection::connect(
|
||||
"postgres://postgres@localhost:5433",
|
||||
TlsMode::Require(&negotiator),
|
||||
));
|
||||
or_panic!(conn.execute("SELECT 1::VARCHAR", &[]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-openssl")]
|
||||
fn test_prefer_ssl_conn() {
|
||||
use openssl::ssl::{SslConnectorBuilder, SslMethod};
|
||||
use postgres::tls::openssl::OpenSsl;
|
||||
|
||||
let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
|
||||
builder.set_ca_file("../test/server.crt").unwrap();
|
||||
let negotiator = OpenSsl::from(builder.build());
|
||||
let conn = or_panic!(Connection::connect(
|
||||
"postgres://postgres@localhost:5433",
|
||||
TlsMode::Require(&negotiator),
|
||||
));
|
||||
or_panic!(conn.execute("SELECT 1::VARCHAR", &[]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "with-security-framework")]
|
||||
fn security_framework_ssl() {
|
||||
use postgres::tls::security_framework::SecurityFramework;
|
||||
use security_framework::certificate::SecCertificate;
|
||||
|
||||
let certificate = include_bytes!("../../test/server.der");
|
||||
let certificate = or_panic!(SecCertificate::from_der(certificate));
|
||||
let mut negotiator = SecurityFramework::new();
|
||||
negotiator.builder_mut().anchor_certificates(&[certificate]);
|
||||
let conn = or_panic!(Connection::connect(
|
||||
"postgres://postgres@localhost:5433",
|
||||
TlsMode::Require(&negotiator),
|
||||
));
|
||||
or_panic!(conn.execute("SELECT 1::VARCHAR", &[]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
// need to ignore until native-tls supports extra root certs :(
|
||||
#[cfg(feature = "with-native-tls")]
|
||||
fn native_tls_ssl() {
|
||||
use postgres::tls::native_tls::NativeTls;
|
||||
|
||||
let negotiator = NativeTls::new().unwrap();
|
||||
let conn = or_panic!(Connection::connect(
|
||||
"postgres://postgres@localhost:5433",
|
||||
TlsMode::Require(&negotiator),
|
||||
));
|
||||
or_panic!(conn.execute("SELECT 1::VARCHAR", &[]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plaintext_pass() {
|
||||
or_panic!(Connection::connect(
|
||||
@ -1399,14 +1330,15 @@ fn test_rows_index() {
|
||||
#[test]
|
||||
fn test_type_names() {
|
||||
let conn = Connection::connect("postgres://postgres@localhost:5433", TlsMode::None).unwrap();
|
||||
let stmt = conn.prepare(
|
||||
"SELECT t.oid, t.typname
|
||||
let stmt =
|
||||
conn.prepare(
|
||||
"SELECT t.oid, t.typname
|
||||
FROM pg_catalog.pg_type t, pg_namespace n
|
||||
WHERE n.oid = t.typnamespace
|
||||
AND n.nspname = 'pg_catalog'
|
||||
AND t.oid < 10000
|
||||
AND t.typtype != 'c'",
|
||||
).unwrap();
|
||||
).unwrap();
|
||||
for row in &stmt.query(&[]).unwrap() {
|
||||
let id: Oid = row.get(0);
|
||||
let name: String = row.get(1);
|
||||
@ -1423,7 +1355,8 @@ fn test_conn_query() {
|
||||
INSERT INTO foo (id) VALUES (1), (2), (3);
|
||||
",
|
||||
).unwrap();
|
||||
let ids = conn.query("SELECT id FROM foo ORDER BY id", &[])
|
||||
let ids = conn
|
||||
.query("SELECT id FROM foo ORDER BY id", &[])
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|r| r.get(0))
|
||||
@ -1488,7 +1421,8 @@ fn keepalive() {
|
||||
#[test]
|
||||
fn explicit_types() {
|
||||
let conn = Connection::connect("postgres://postgres@localhost:5433", TlsMode::None).unwrap();
|
||||
let stmt = conn.prepare_typed("SELECT $1::INT4", &[Some(Type::INT8)])
|
||||
let stmt = conn
|
||||
.prepare_typed("SELECT $1::INT4", &[Some(Type::INT8)])
|
||||
.unwrap();
|
||||
assert_eq!(stmt.param_types()[0], Type::INT8);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user