65 releases (8 breaking)

Uses new Rust 2021

0.9.0 May 3, 2022
0.7.3 Apr 6, 2022
0.7.1 Jan 7, 2022
0.6.5 Oct 29, 2021
0.1.0 May 6, 2016

#6 in Hardware support

Download history 10006/week @ 2022-01-30 9548/week @ 2022-02-06 9715/week @ 2022-02-13 8750/week @ 2022-02-20 8090/week @ 2022-02-27 7931/week @ 2022-03-06 7929/week @ 2022-03-13 20818/week @ 2022-03-20 23210/week @ 2022-03-27 17981/week @ 2022-04-03 18003/week @ 2022-04-10 18671/week @ 2022-04-17 21985/week @ 2022-04-24 19076/week @ 2022-05-01 18541/week @ 2022-05-08 7885/week @ 2022-05-15

68,210 downloads per month
Used in 9 crates (7 directly)

MIT/Apache

350KB
7.5K SLoC

Tiberius

crates.io docs.rs Cargo tests Chat

A native Microsoft SQL Server (TDS) client for Rust.

Goals

  • A perfect implementation of the TDS protocol.
  • Asynchronous network IO.
  • Independent of the network protocol.
  • Support for latest versions of Linux, Windows and macOS.

Non-goals

  • Connection pooling (use bb8, mobc, deadpool or any of the other asynchronous connection pools)
  • Query building
  • Object-relational mapping

Supported SQL Server versions

Version Support level Notes
2019 Tested on CI
2017 Tested on CI
2016 Should work
2014 Should work
2012 Should work
2008 Should work
2005 Should work With feature flag tds73 disabled.

Feature flags

Flag Description Default
tds73 Support for new date and time types in TDS version 7.3. Disable if using version 7.2. enabled
native-tls Use operating system's TLS libraries for traffic encryption. enabled
chrono Read and write date and time values using chrono's types. (for greenfield, using time instead of chrono is recommended) disabled
time Read and write date and time values using time crate types. disabled
rust_decimal Read and write numeric/decimal values using rust_decimal's Decimal. disabled
bigdecimal Read and write numeric/decimal values using bigdecimal's BigDecimal. disabled
sql-browser-async-std SQL Browser implementation for the TcpStream of async-std. disabled
sql-browser-tokio SQL Browser implementation for the TcpStream of Tokio. disabled
sql-browser-smol SQL Browser implementation for the TcpStream of smol. disabled
integrated-auth-gssapi Support for using Integrated Auth via GSSAPI disabled
rustls Use the builtin TLS implementation from rustls instead of linking to the operating system implementation for traffic encryption. disabled

Supported protocols

Tiberius does not rely on any protocol when connecting to an SQL Server instance. Instead the Client takes a socket that implements the AsyncRead and AsyncWrite traits from the futures-rs crate.

Currently there are good async implementations for TCP in the async-std, Tokio and Smol projects. To be able to use them together with Tiberius on Windows platforms with SQL Server, TCP protocol should be enabled in the server settings (disabled by default). In the offficial Docker image TCP is is enabled by default.

Named pipes should work by using the NamedPipeClient from the latest Tokio versions.

The shared memory protocol is not documented and seems there are no Rust crates implementing it.

Encryption (TLS/SSL)

TLS support is a compilation-time setting in Tiberius. By default it uses native-tls for encryption, where we link to the TLS implementation of the operating system. This is a good practice and in case of security vulnerabilities, upgrading the system libraries fixes the vulnerability in Tiberius without a recompilation. On Linux we link against OpenSSL, on Windows against schannel and on macOS against Security Framework.

Alternatively one can use the rustls feature flag to use the Rust native TLS implementation. This way there are no dynamic dependencies to the system. This might be useful in certain installations, but requires a rebuild to update to a new TLS version. For some reasons the Security Framework on macOS does not work with SQL Server TLS settings, and on Apple platforms if needing TLS it is recommended to use rustls instead of native-tls.

The crate can also be compiled without TLS support, but not with both features enabled at the same time.

Tiberius has three encryption settings:

Encryption level Description
Required All traffic is encrypted.
Off Only the login procedure is encrypted. (default)
NotSupported None of the traffic is encrypted.

Integrated Authentication (TrustedConnection) on *nix

With the integrated-auth-gssapi feature enabled, the crate requires the GSSAPI/Kerberos libraries/headers installed:

  • CentOS
  • Arch
  • Debian (you need the -dev packages to build)
  • Ubuntu
  • NixOS: Run nix-shell shell.nix on the repository root.
  • Mac: as of version 0.4.2 the libgssapi crate used for this feature now uses Apple's GSS Framework which ships with MacOS 10.14+.

Additionally, your runtime system will need to be trusted by and configured for the Active Directory domain your SQL Server is part of. In particular, you'll need to be able to get a valid TGT for your identity, via kinit or a keytab. This setup varies by environment and OS, but your friendly network/system administrator should be able to help figure out the specifics.

Redirects

With certain Azure firewall settings, a login might return Error::Routing { host, port }. This means the user must create a new TcpStream to the given address, and connect again.

A simple connection procedure would then be:

use tiberius::{Client, Config, AuthMethod, error::Error};
use tokio_util::compat::TokioAsyncWriteCompatExt;
use tokio::net::TcpStream;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut config = Config::new();

    config.host("0.0.0.0");
    config.port(1433);
    config.authentication(AuthMethod::sql_server("SA", "<Mys3cureP4ssW0rD>"));

    let tcp = TcpStream::connect(config.get_addr()).await?;
    tcp.set_nodelay(true)?;

    let client = match Client::connect(config, tcp.compat_write()).await {
        // Connection successful.
        Ok(client) => client,
        // The server wants us to redirect to a different address
        Err(Error::Routing { host, port }) => {
            let mut config = Config::new();

            config.host(&host);
            config.port(port);
            config.authentication(AuthMethod::sql_server("SA", "<Mys3cureP4ssW0rD>"));

            let tcp = TcpStream::connect(config.get_addr()).await?;
            tcp.set_nodelay(true)?;

            // we should not have more than one redirect, so we'll short-circuit here.
            Client::connect(config, tcp.compat_write()).await?
        }
        Err(e) => Err(e)?,
    };

    Ok(())
}

Security

If you have a security issue to report, please contact us at security@prisma.io

Dependencies

~4–14MB
~258K SLoC