Coder Social home page Coder Social logo

rust-tls-api's Introduction

GitHub Workflow Status License crates.io

One TLS API to rule them all

Supports:

  • tokio and async-std
  • rustls, native-tls, openssl, security-framework

Crates in this repository

  • tls-api — TLS API without any implementation and without dependencies
  • tls-api-native-tls — implementation of TLS API over native-tls crate
  • tls-api-openssl — implementation of TLS API over openssl crate
  • tls-api-rustls — implementation of TLS API over rustls crate
  • tls-api-security-framework — implementation of TLS API over security framework crate
  • tls-api-schannel — missing implementation of TLS API over schannel crate
  • tls-api-stub — stub API implementation which returns an error on any operation
  • tls-api-not-tls — stub API implementation which pretends to be TLS, but returns wrapped plain socket
  • test-cert-gen — utility to generate certificate for unit tests

Why one might want to use TLS API instead of concrete implementation

  • it is not decided yet which TLS implementation is better, start prototyping with one, and then switch to another
  • something doesn't work, no idea why, maybe try another implementation which would provide better diagnostics
  • provide a library over TLS (like database client) and allow user do specify preferred TLS implementation
  • do a performace comparison of TLS implementations on the same code base
  • if one implementation is buggy, it's easy to switch to another without heavy rewrite

Example

download-rust-lang-org.rs contains the implementation of simple TLS client downloading rust-lang.org, which is invoked with four backends.

Implementations comparison

openssl rustls security-framework native-tls
Can fetch google.com:443 Yes Yes Yes Yes
Server works Yes Yes Yes Yes
Client ALPN Yes Yes Yes Yes
Server ALPN Yes Yes No No
Server init from DER key Yes Yes No No
Server init from PKCS12 Yes No Yes Yes

Why not simply use XXX

Why not simply use native-tls

  • does not support server side ALPN
  • requires PKCS #12 keys on the server side
  • building OpenSSL on Linux is not always trivial

Why not simply use openssl

  • sometimes it's hard to compile it
  • some concerns about OpenSSL safety

Why not simply use rustls

  • diagnostics of rustls is not perfect
  • certain TLS features are not supported

Why not simply use security-framework

  • only works on Apple
  • does not support server side ALPN

rust-tls-api's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

rust-tls-api's Issues

rustls::stream invalid result

Hi. We are performing google speech api calls using grps-rust with tls-api and tls-api-rustls and we have issues with the latest version.
More specifically, the following commit 8aa2f6a#diff-bc54d678b15366c5071904c8b5d6c325 precisely seem to cause the issue (the switch to rustls::stream).

Since v0.1.14, calling google.cloud.speech.v1.Speech/StreamingRecognize with the same sample wav (the "brookly bridge" audio sample from google for example) gives more or less random result: for example instead of getting back "how old is the brooklyn bridge" we get "how old how old is the brooklyn bridge" or even worse. It gives the impression that some audio stream frames uploaded through grpc/rustls are partially duplicated.

And indeed if we force tls-api-rustls back to v0.1.13 (only that single dependency), we get correct results. So my guess is that there is some issues with rustls::stream...

Unable to build: failed to select a version for the requirement `security-framework = "^0.1"`

Checking out master or the 0.9.0 tag using Rust 1.70.0:

user@dev ~/g/s/rust-tls-api> cargo build
    Updating crates.io index
error: failed to select a version for the requirement `security-framework = "^0.1"`
candidate versions found which didn't match: 2.9.1, 2.9.0, 2.8.2, ...
location searched: crates.io index
required by package `tls-api-examples v0.0.0 (/home/user/github/stepancheg/rust-tls-api/examples)`
perhaps a crate was updated and forgotten to be re-vendored?

I commented out the dependency for now, but I expect it would cause CI, etc. to fail.

Option to disable server certificate authentication

I'm making a small CLI to control a Roomba and I need to send a specific network packet using TLS (see here the code I'm trying to clone from JS).

Unfortunately I always get the error:

Error: Custom { kind: Other, error: Failure(MidHandshakeSslStream { stream: SslStream { stream: AsyncIoAsSyncIo { inner: TcpStream { addr: V4(10.10.0.238:49792), peer: V4(10.10.0.90:8883), fd: 6 }, context: 0x7ffdc6b7e6e0 }, ssl: Ssl { state: "error", verify_result: X509VerifyResult { code: 20, error: "unable to get local issuer certificate" } } }, error: Error { code: ErrorCode(1), cause: Some(Ssl(ErrorStack([Error { code: 337047686, library: "SSL routines", function: "tls_process_server_certificate", reason: "certificate verify failed", file: "ssl/statem/statem_clnt.c", line: 1913 }]))) } }) }

Because I think it is still verifying the certificate even if I don't verify the hostname? Here is the code:

#[tokio::main]
async fn sign_up<A: ToSocketAddrs + std::fmt::Display>(addr: A) -> std::io::Result<()> {
    let packet: &[u8] = &[0xf0, 0x05, 0xef, 0xcc, 0x3b, 29, 00];

    let tcp_stream = TcpStream::connect(addr).await?;

    let mut builder = tls_api_openssl::TlsConnector::builder().expect("builder");
    builder.set_verify_hostname(false)?;
    let connector = builder.build().expect("build");
    let mut tls_stream: TlsStream<_> = connector.connect("ignore", tcp_stream).await?;

    println!("handshake complete");

    tls_stream.write_all(packet).await?;
    let mut result = vec![];
    tls_stream.read_to_end(&mut result).await?;

    println!("{}", String::from_utf8_lossy(&result));

    Ok(())
}

I also used paho for this project and there is a difference between checking the hostname and disabling the server certificate authentication. It works when I do .enable_server_cert_auth(false) but it won't work if I just disable the verification mechanism: .verify(false) (not in the doc because the option is available for next release).

I couldn't find an equivalent in tls-api. Is it a missing feature or do I miss something?

Thanks

Lift Sync restriction on accepted streams

The type signature of accept() requires me to provide a stream that is Sync. This seems overly restrictive to me. On a theoretical level, how do I even construct a stream that is sync?

   fn accept<'a, S>(
        &'a self,
        stream: S,
    ) -> Pin<Box<dyn Future<Output = Result<TlsStream<S>>> + Send + 'a>>
    where
        S: AsyncRead + AsyncWrite + fmt::Debug + Unpin + Send + Sync + 'static;

rustls 0.10 breaks tls-api-rustls

I get this error when building after a cargo update that pulled rustls 0.10.0

error[E0050]: method `verify_server_cert` has 4 parameters but the declaration in trait `rustls::ServerCertVerifier::verify_server_cert` has 5
   --> /home/fredszaq/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-rustls-0.1.8/src/lib.rs:289:28
    |
289 |                 _dns_name: &str)
    |                            ^^^^ expected 5 parameters, found 4
    |
    = note: `verify_server_cert` from trait: `fn(&Self, &rustls::RootCertStore, &[rustls::Certificate], &str, &[u8]) -> std::result::Result<rustls::ServerCertVerified, rustls::TLSError>`

error: aborting due to previous error(s)

error: Could not compile `tls-api-rustls`.
Build failed, waiting for other jobs to finish...

Mutually exclusive features are suboptimal

The runtime module of tls-api is constructed so that if both tokio and async_std are enabled, the whole crate fails to compile. (As the docs say, "Currently the features are mutually exclusive.)

This is not great, because cargo features are supposed to be strictly additive: https://doc.rust-lang.org/cargo/reference/features.html#feature-unification

In praftical terms, if a large program contained two separate places where TLS was used, and those two places both used tls-api, and for some reason those two places end up using different runtimes, the system would fail to compile. Normally this kind of situation woudl be undesirable, but doing it ought to be possible, and the "action at a distance" nature of this issue makes it troubling. Having two async runtimes in the same program image is going to happen sometimes.

A possible workaround would be to use cargo's patch feature, or some other mechanism (eg incompatible version requirements) to force cargo to include two separate copies of tls-api, which could each then only have one of the sets of features. (I haven't tried this, but it seems like something along those lines ought to work.)

I appreciate that changing this with the current structure of tls_api is far from straightforward. So perhaps the current situation is the best compromise. I felt it seemed worth filing the issue.

Update rustls and webpki

tls-api-rustls currently is on outdated version of rustls and webpki. This is an issue for me because I'm using other dependencies that use ring v0.16.

Deprecate tokio-core

After reorganization tokio-core crate was moved to tokio, tokio-reactor, and so on.

Are any plans to remove its usage?

Why do I need a runtime?

I am trying to use this to be able to easly switch the tls implementation between rustls and native-tls.

Is there a way to use this crate without an async runtime, with std::net::tcp::TcpStream?

I tried to disable the default features to get rid of the async related stuff from this library but then I get these kind of errors:

[ERROR rust_analyzer::main_loop] FetchBuildDataError:
error[E0432]: unresolved import `crate::runtime::AsyncRead`
  --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/async_as_sync.rs:14:5
   |
14 | use crate::runtime::AsyncRead;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ no `AsyncRead` in `runtime`


error[E0432]: unresolved import `crate::runtime::AsyncWrite`
  --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/async_as_sync.rs:15:5
   |
15 | use crate::runtime::AsyncWrite;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `AsyncWrite` in `runtime`


error[E0432]: unresolved import `crate::runtime::AsyncRead`
 --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/socket.rs:1:5
  |
1 | use crate::runtime::AsyncRead;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^ no `AsyncRead` in `runtime`


error[E0432]: unresolved import `crate::runtime::AsyncWrite`
 --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/socket.rs:2:5
  |
2 | use crate::runtime::AsyncWrite;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `AsyncWrite` in `runtime`


error[E0432]: unresolved import `crate::spi_async_socket_impl_delegate`
 --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/socket_box.rs:8:5
  |
8 | use crate::spi_async_socket_impl_delegate;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `spi_async_socket_impl_delegate` in the root


error[E0432]: unresolved import `crate::spi_async_socket_impl_delegate`
 --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/stream.rs:4:5
  |
4 | use crate::spi_async_socket_impl_delegate;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `spi_async_socket_impl_delegate` in the root


error[E0432]: unresolved import `crate::runtime::AsyncRead`
 --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/stream_with_socket.rs:8:5
  |
8 | use crate::runtime::AsyncRead;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^ no `AsyncRead` in `runtime`


error[E0432]: unresolved import `crate::runtime::AsyncWrite`
 --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/stream_with_socket.rs:9:5
  |
9 | use crate::runtime::AsyncWrite;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ no `AsyncWrite` in `runtime`


error[E0432]: unresolved import `crate::spi_async_socket_impl_delegate`
  --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/stream_with_socket.rs:12:5
   |
12 | use crate::spi_async_socket_impl_delegate;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `spi_async_socket_impl_delegate` in the root


error: cannot determine resolution for the macro `spi_async_socket_impl_delegate`
  --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/socket_box.rs:49:1
   |
49 | spi_async_socket_impl_delegate!(AsyncSocketBox);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: import resolution is stuck, try simplifying macro imports


error: cannot determine resolution for the macro `spi_async_socket_impl_delegate`
  --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/stream.rs:52:1
   |
52 | spi_async_socket_impl_delegate!(TlsStream);
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: import resolution is stuck, try simplifying macro imports


error: cannot determine resolution for the macro `spi_async_socket_impl_delegate`
   --> /home/adam/.cargo/registry/src/github.com-1ecc6299db9ec823/tls-api-0.9.0/src/stream_with_socket.rs:114:1
    |
114 | spi_async_socket_impl_delegate!(TlsStreamWithSocket<S>);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: import resolution is stuck, try simplifying macro imports


error: aborting due to 12 previous errors


For more information about this error, try `rustc --explain E0432`.

error: could not compile `tls-api` due to 13 previous errors


Using openssl 1.1.1 or vendored in the openssl crate causes "Unable to detect openssl version"

Hello

We are migrating to **openssl 0.10**, **vendored** (to be on the latest level of openssl) that works in different distros our dev guys use.

I see from the https://github.com/stepancheg/rust-tls-api/blob/master/impl-openssl/build.rs
there is an explicit lock on the versions.

So tls-api-openssl supports upto **1.1.0** as see in the **build.rs** file.

The vendored version is **1.1.1**

Is is safe to change build.rs by adding a **switch for 111** as well.

as below:

fn main() {
    // HAS
    match env::var("DEP_OPENSSL_VERSION") {
        Ok(ref v) if v == "101" => {
        }
        Ok(ref v) if v == "102" => {
            println!("cargo:rustc-cfg=has_alpn");
        }
        Ok(ref v) if v == "110" => {
            println!("cargo:rustc-cfg=has_alpn");
        }
        Ok(ref v) if v == "111" => {
            println!("cargo:rustc-cfg=has_alpn");
        }
        _ => panic!("Unable to detect OpenSSL version"),
    }
}
) 

Are there reasons that 111 isn't supported yet ?

I am on Arch, so it uses 1.1.1, but want to use the vendored feature in openssl crate.

Breaking! tokio-tls-api can not build after futures updated to 0.2

Suggestion

Change dependency futures = "0.*" to futures="0.1"

Error message

   Compiling tokio-tls-api v0.1.14
error[E0053]: method `shutdown` has an incompatible type for trait
   --> /home/xxx/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-tls-api-0.1.14/src/lib.rs:105:5
    |
105 | /     fn shutdown(&mut self) -> Poll<(), io::Error> {
106 | |         try_nb!(self.inner.shutdown());
107 | |         self.inner.get_mut().shutdown()
108 | |     }
    | |_____^ expected enum `futures::poll::Async`, found enum `futures::Async`
    |
    = note: expected type `fn(&mut TlsStream<S>) -> std::result::Result<futures::poll::Async<()>, std::io::Error>`
               found type `fn(&mut TlsStream<S>) -> std::result::Result<futures::Async<()>, std::io::Error>`

error[E0050]: method `poll` has 1 parameter but the declaration in trait `futures::Future::poll` has 2
   --> /home/xxx/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-tls-api-0.1.14/src/lib.rs:176:13
    |
176 |     fn poll(&mut self) -> Poll<TlsStream<S>, Error> {
    |             ^^^^^^^^^ expected 2 parameters, found 1
    |
    = note: `poll` from trait: `fn(&mut Self, &mut futures::task::Context<'_>) -> std::result::Result<futures::Async<<Self as futures::Future>::Item>, <Self as futures::Future>::Error>`

why only TlsStream::get_mut

because there is no immutable way to get the inner stream, this prevents it being used in traits that demand immutable access. Right now you can't implement mio::Evented trait on an struct with TlsStream.

Upgrade to native-tls 0.2.x to switch to openssl 0.10.x on Linux

We are currently using tls-api with tls-api-native-tls, which in turns uses openssl for Linux. We'd like to upgrade all of our crates to use openssl 0.10.x instead of 0.9.x, but since tls-api-native-tls still uses native-tls 0.1, we're stuck with openssl 0.9.x :/

Upgrading to native-tls 0.2 requires some fixes for the API breaking changes, but it is becoming increasingly necessary as more crates migrate to openssl 0.10.x.

Consider a tls-api-passthrough

I recently started using tls-api. In my use case I to be able to chose between TLS implementations, but also no TLS when appropriate.

My API is:

pub async fn connect<Tls: TlsConnector>(uri: &http::Uri) -> Result<Connection, Error> {}

For connecting plain http (not that one should), instead of having a duplicate connect() function with code duplication, the TlsConnector could be a pass through implementation.

I written one in my own repo, but would you consider a PR with it (fixed up) to sit alongside your other implementations?

https://github.com/algesten/ureq/blob/future/src/tls_pass.rs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.