Swap openssl for native-tls (#43)

* Replace openssl with native-tls

* Add From<TlsError> to allow builder()?

* Update AppVeyor config

* No email since it's not configured
This commit is contained in:
Jon Gjengset 2017-10-01 19:53:03 -04:00 committed by Matt McCoy
parent ba2eb75ddd
commit 7c95ae76d6
7 changed files with 95 additions and 110 deletions

View file

@ -25,7 +25,7 @@ name = "imap"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
openssl = "0.9" native-tls = "0.1"
regex = "0.2" regex = "0.2"
bufstream = "0.1" bufstream = "0.1"

View file

@ -1,94 +1,67 @@
# inspired by https://github.com/starkat99/appveyor-rust/blob/master/appveyor.yml
environment: environment:
global:
RUST_VERSION: stable
CRATE_NAME: imap
SSL_CERT_FILE: "C:\\OpenSSL\\cacert.pem"
matrix: matrix:
# MinGW ### MSVC Toolchains ###
- TARGET: i686-pc-windows-gnu
BITS: 32
MSYS2: 1
OPENSSL_VERSION: 1_1_0f
- TARGET: x86_64-pc-windows-gnu
BITS: 64
MSYS2: 1
OPENSSL_VERSION: 1_0_2L
# MSVC # Stable 64-bit MSVC
- TARGET: i686-pc-windows-msvc - channel: stable
BITS: 32 target: x86_64-pc-windows-msvc
OPENSSL_VERSION: 1_0_2L # Stable 32-bit MSVC
OPENSSL_DIR: C:\OpenSSL - channel: stable
- TARGET: x86_64-pc-windows-msvc target: i686-pc-windows-msvc
BITS: 64 # Beta 64-bit MSVC
OPENSSL_VERSION: 1_1_0f - channel: beta
OPENSSL_DIR: C:\OpenSSL target: x86_64-pc-windows-msvc
# Beta 32-bit MSVC
- channel: beta
target: i686-pc-windows-msvc
# MinGW beta ### GNU Toolchains ###
- TARGET: i686-pc-windows-gnu
BITS: 32
MSYS2: 1
OPENSSL_VERSION: 1_1_0f
RUST_VERSION: beta
- TARGET: x86_64-pc-windows-gnu
BITS: 64
MSYS2: 1
OPENSSL_VERSION: 1_0_2L
RUST_VERSION: beta
# MSVC beta # Stable 64-bit GNU
- TARGET: i686-pc-windows-msvc - channel: stable
BITS: 32 target: x86_64-pc-windows-gnu
MSYS2: 1 # Stable 32-bit GNU
OPENSSL_VERSION: 1_0_2L - channel: stable
OPENSSL_DIR: C:\OpenSSL target: i686-pc-windows-gnu
RUST_VERSION: beta # Beta 64-bit GNU
- TARGET: x86_64-pc-windows-msvc - channel: beta
BITS: 64 target: x86_64-pc-windows-gnu
OPENSSL_VERSION: 1_1_0f # Beta 32-bit GNU
OPENSSL_DIR: C:\OpenSSL - channel: beta
RUST_VERSION: beta target: i686-pc-windows-gnu
### MinGW Toolchains ###
# Stable 64-bit MinGW
- channel: stable
target: x86_64-pc-windows-msvc
MSYS_BITS: 64
# Stable 32-bit MinGW
- channel: stable
target: i686-pc-windows-msvc
MSYS_BITS: 32
# Beta 64-bit MinGW
- channel: beta
target: x86_64-pc-windows-msvc
MSYS_BITS: 64
# Beta 32-bit MinGW
- channel: beta
target: i686-pc-windows-msvc
MSYS_BITS: 32
install: install:
# install OpenSSL
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-${env:OPENSSL_VERSION}.exe"
- Win%BITS%OpenSSL-%OPENSSL_VERSION%.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
- appveyor DownloadFile https://curl.haxx.se/ca/cacert.pem -FileName C:\OpenSSL\cacert.pem
# install Rust # install Rust
- curl -sSf -o rustup-init.exe https://win.rustup.rs/ - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
- rustup-init.exe -y --default-host %TARGET% --default-toolchain %RUST_VERSION% - rustup-init -yv --default-toolchain %channel% --default-host %target%
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - set PATH=%PATH%;%USERPROFILE%\.cargo\bin
- if defined MSYS2 set PATH=C:\msys64\mingw%BITS%\bin;%PATH% - rustc -vV
- rustc -Vv - cargo -vV
- cargo -V
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host %TARGET%
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
- if defined MSYS2 set PATH=C:\msys64\mingw%BITS%\bin;%PATH%
- rustc -V
- cargo -V
test_script:
# we don't run the "test phase" when doing deploys
- if [%APPVEYOR_REPO_TAG%]==[false] (
cargo build --target %TARGET% &&
cargo build --target %TARGET% --release &&
cargo test --target %TARGET% &&
cargo test --target %TARGET% --release
)
cache:
- C:\Users\appveyor\.cargo\registry
- target
notifications:
- provider: Email
on_build_success: false
# Building is done in the test phase, so we disable Appveyor's build phase. # Building is done in the test phase, so we disable Appveyor's build phase.
build: false build: false
test_script:
- cargo test

View file

@ -1,7 +1,7 @@
extern crate imap; extern crate imap;
extern crate openssl; extern crate native_tls;
use openssl::ssl::{SslConnectorBuilder, SslMethod}; use native_tls::TlsConnector;
use imap::client::Client; use imap::client::Client;
// To connect to the gmail IMAP server with this you will need to allow unsecure apps access. // To connect to the gmail IMAP server with this you will need to allow unsecure apps access.
@ -11,7 +11,7 @@ fn main() {
let domain = "imap.gmail.com"; let domain = "imap.gmail.com";
let port = 993; let port = 993;
let socket_addr = (domain, port); let socket_addr = (domain, port);
let ssl_connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build(); let ssl_connector = TlsConnector::builder().unwrap().build().unwrap();
let mut imap_socket = Client::secure_connect(socket_addr, domain, ssl_connector).unwrap(); let mut imap_socket = Client::secure_connect(socket_addr, domain, ssl_connector).unwrap();
imap_socket.login("username", "password").unwrap(); imap_socket.login("username", "password").unwrap();

View file

@ -1,8 +1,8 @@
extern crate base64; extern crate base64;
extern crate imap; extern crate imap;
extern crate openssl; extern crate native_tls;
use openssl::ssl::{SslConnectorBuilder, SslMethod}; use native_tls::TlsConnector;
use base64::encode; use base64::encode;
use imap::client::Client; use imap::client::Client;
use imap::authenticator::Authenticator; use imap::authenticator::Authenticator;
@ -33,7 +33,7 @@ fn main() {
let domain = "imap.gmail.com"; let domain = "imap.gmail.com";
let port = 993; let port = 993;
let socket_addr = (domain, port); let socket_addr = (domain, port);
let ssl_connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build(); let ssl_connector = TlsConnector::builder().unwrap().build().unwrap();
let mut imap_socket = Client::secure_connect(socket_addr, domain, ssl_connector).unwrap(); let mut imap_socket = Client::secure_connect(socket_addr, domain, ssl_connector).unwrap();
imap_socket.authenticate("XOAUTH2", gmail_auth).unwrap(); imap_socket.authenticate("XOAUTH2", gmail_auth).unwrap();

View file

@ -1,5 +1,5 @@
use std::net::{TcpStream, ToSocketAddrs}; use std::net::{TcpStream, ToSocketAddrs};
use openssl::ssl::{SslConnector, SslStream}; use native_tls::{TlsConnector, TlsStream};
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::time::Duration; use std::time::Duration;
use bufstream::BufStream; use bufstream::BufStream;
@ -168,7 +168,7 @@ impl<'a> SetReadTimeout for TcpStream {
} }
} }
impl<'a> SetReadTimeout for SslStream<TcpStream> { impl<'a> SetReadTimeout for TlsStream<TcpStream> {
fn set_read_timeout(&mut self, timeout: Option<Duration>) -> Result<()> { fn set_read_timeout(&mut self, timeout: Option<Duration>) -> Result<()> {
self.get_ref() self.get_ref()
.set_read_timeout(timeout) .set_read_timeout(timeout)
@ -196,28 +196,28 @@ impl Client<TcpStream> {
pub fn secure( pub fn secure(
mut self, mut self,
domain: &str, domain: &str,
ssl_connector: SslConnector, ssl_connector: TlsConnector,
) -> Result<Client<SslStream<TcpStream>>> { ) -> Result<Client<TlsStream<TcpStream>>> {
// TODO This needs to be tested // TODO This needs to be tested
self.run_command_and_check_ok("STARTTLS")?; self.run_command_and_check_ok("STARTTLS")?;
SslConnector::connect(&ssl_connector, domain, try!(self.stream.into_inner())) TlsConnector::connect(&ssl_connector, domain, try!(self.stream.into_inner()))
.map(Client::new) .map(Client::new)
.map_err(Error::Ssl) .map_err(Error::TlsHandshake)
} }
} }
impl Client<SslStream<TcpStream>> { impl Client<TlsStream<TcpStream>> {
/// Creates a client with an SSL wrapper. /// Creates a client with an SSL wrapper.
pub fn secure_connect<A: ToSocketAddrs>( pub fn secure_connect<A: ToSocketAddrs>(
addr: A, addr: A,
domain: &str, domain: &str,
ssl_connector: SslConnector, ssl_connector: TlsConnector,
) -> Result<Client<SslStream<TcpStream>>> { ) -> Result<Client<TlsStream<TcpStream>>> {
match TcpStream::connect(addr) { match TcpStream::connect(addr) {
Ok(stream) => { Ok(stream) => {
let ssl_stream = match SslConnector::connect(&ssl_connector, domain, stream) { let ssl_stream = match TlsConnector::connect(&ssl_connector, domain, stream) {
Ok(s) => s, Ok(s) => s,
Err(e) => return Err(Error::Ssl(e)), Err(e) => return Err(Error::TlsHandshake(e)),
}; };
let mut socket = Client::new(ssl_stream); let mut socket = Client::new(ssl_stream);

View file

@ -4,7 +4,8 @@ use std::fmt;
use std::error::Error as StdError; use std::error::Error as StdError;
use std::net::TcpStream; use std::net::TcpStream;
use openssl::ssl::HandshakeError as SslError; use native_tls::HandshakeError as TlsHandshakeError;
use native_tls::Error as TlsError;
use bufstream::IntoInnerError as BufError; use bufstream::IntoInnerError as BufError;
pub type Result<T> = result::Result<T, Error>; pub type Result<T> = result::Result<T, Error>;
@ -14,8 +15,10 @@ pub type Result<T> = result::Result<T, Error>;
pub enum Error { pub enum Error {
/// An `io::Error` that occurred while trying to read or write to a network stream. /// An `io::Error` that occurred while trying to read or write to a network stream.
Io(IoError), Io(IoError),
/// An error from the `openssl` library. /// An error from the `native_tls` library during the TLS handshake.
Ssl(SslError<TcpStream>), TlsHandshake(TlsHandshakeError<TcpStream>),
/// An error from the `native_tls` library while managing the socket.
Tls(TlsError),
/// A BAD response from the IMAP server. /// A BAD response from the IMAP server.
BadResponse(Vec<String>), BadResponse(Vec<String>),
/// A NO response from the IMAP server. /// A NO response from the IMAP server.
@ -40,9 +43,15 @@ impl<T> From<BufError<T>> for Error {
} }
} }
impl From<SslError<TcpStream>> for Error { impl From<TlsHandshakeError<TcpStream>> for Error {
fn from(err: SslError<TcpStream>) -> Error { fn from(err: TlsHandshakeError<TcpStream>) -> Error {
Error::Ssl(err) Error::TlsHandshake(err)
}
}
impl From<TlsError> for Error {
fn from(err: TlsError) -> Error {
Error::Tls(err)
} }
} }
@ -50,7 +59,8 @@ impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
Error::Io(ref e) => fmt::Display::fmt(e, f), Error::Io(ref e) => fmt::Display::fmt(e, f),
Error::Ssl(ref e) => fmt::Display::fmt(e, f), Error::Tls(ref e) => fmt::Display::fmt(e, f),
Error::TlsHandshake(ref e) => fmt::Display::fmt(e, f),
ref e => f.write_str(e.description()), ref e => f.write_str(e.description()),
} }
} }
@ -60,7 +70,8 @@ impl StdError for Error {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
Error::Io(ref e) => e.description(), Error::Io(ref e) => e.description(),
Error::Ssl(ref e) => e.description(), Error::Tls(ref e) => e.description(),
Error::TlsHandshake(ref e) => e.description(),
Error::Parse(ref e) => e.description(), Error::Parse(ref e) => e.description(),
Error::BadResponse(_) => "Bad Response", Error::BadResponse(_) => "Bad Response",
Error::NoResponse(_) => "No Response", Error::NoResponse(_) => "No Response",
@ -72,7 +83,8 @@ impl StdError for Error {
fn cause(&self) -> Option<&StdError> { fn cause(&self) -> Option<&StdError> {
match *self { match *self {
Error::Io(ref e) => Some(e), Error::Io(ref e) => Some(e),
Error::Ssl(ref e) => Some(e), Error::Tls(ref e) => Some(e),
Error::TlsHandshake(ref e) => Some(e),
_ => None, _ => None,
} }
} }

View file

@ -4,7 +4,7 @@
//! imap is a IMAP client for Rust. //! imap is a IMAP client for Rust.
extern crate bufstream; extern crate bufstream;
extern crate openssl; extern crate native_tls;
extern crate regex; extern crate regex;
pub mod authenticator; pub mod authenticator;