From d1db4ee97f9cba762a2f548e238d3c1e51caa22c Mon Sep 17 00:00:00 2001 From: Egert Aia Date: Wed, 4 Nov 2026 11:40:59 +0200 Subject: [PATCH 1/8] feat: add NTLM authentication on every platform Upgrade mssql-tiberius-bridge to 0.3.0 and mssql-tds to 0.4.0, whose SecurityContextProvider hook (microsoft/mssql-rs#742) replaces the built-in SSPI/GSSAPI context. extra.ntlm plugs in an NtlmProvider built on the pure-Rust sspi crate, using the username (DOMAIN\user or user@domain) and password, so Linux and macOS no longer need Kerberos. The connection modal gains a "Use NTLM" checkbox that excludes Windows Authentication. Also handle mssql-tds 0.4.0's new Error::EncodedValueTooLong variant. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 9 ++ Cargo.toml | 6 +- README.md | 17 ++- src/connection.rs | 60 ++++++++ src/driver/error.rs | 1 + src/driver/mod.rs | 1 + src/driver/ntlm.rs | 197 +++++++++++++++++++++++++++ src/driver/pool.rs | 13 +- src/driver/pool/tests.rs | 17 +++ src/models.rs | 3 + src/pool_manager.rs | 11 ++ ui/src/IntegratedAuthToggle.test.tsx | 30 +++- ui/src/IntegratedAuthToggle.tsx | 37 +++-- 13 files changed, 383 insertions(+), 19 deletions(-) create mode 100644 src/driver/ntlm.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index ba2627b..da6e56e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- NTLM authentication with `DOMAIN\user` and password on every platform, + including Linux and macOS (`extra.ntlm`, "Use NTLM" checkbox). + +### Changed + +- Upgrade Microsoft's `mssql-tiberius-bridge` to 0.3.0 and `mssql-tds` to 0.4.0. + ## [1.0.0-beta.4] - 2026-10-25 ### Changed diff --git a/Cargo.toml b/Cargo.toml index 0dbe59b..a157d03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,14 +14,16 @@ infer = "0.22" # SQL Server driver — Microsoft's mssql-tds protocol implementation behind a # tiberius-compatible API, pooled with deadpool. Keep the exact pin and update # alongside the directly used protocol crate when the bridge changes versions. -mssql-tiberius-bridge = "=0.2.0" +mssql-tiberius-bridge = "=0.3.0" # Direct dependency on the underlying protocol crate (lib name `mssql_tds`): # the result-set traits used through `Client::inner_mut()` are not re-exported # by the bridge. Pinned in lockstep with its compatible published protocol API. -mssql-tds = "=0.2.0" +mssql-tds = "=0.4.0" once_cell = "1" serde = { version = "1", features = ["derive"] } serde_json = "1" +# Pure-Rust NTLM client for `extra.ntlm`; mssql-tds only has Kerberos on Unix. +sspi = { version = "0.23", default-features = false } tokio = { version = "1", features = ["full"] } uuid = "1" diff --git a/README.md b/README.md index e21d5b2..8e17e9a 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ This plugin enables Tabularis to connect to SQL Server instances, providing sche | `host` | `localhost` | Yes unless using `connection_string` | SQL Server hostname or IP address | | `port` | `1433` | No | TDS port | | `database` | — | Yes unless using `connection_string` | Database the pool connects to | -| `username` | `sa` | Yes, unless integrated authentication is enabled or `connection_string` is used | SQL-authenticated login | +| `username` | `sa` | Yes, unless integrated authentication is enabled or `connection_string` is used | SQL-authenticated login, or `DOMAIN\user` / `user@domain` with NTLM | | `password` | — | If required by the server | Login password; redacted from connection errors | | `ssl_mode` | `prefer` | No | `disable`, `prefer`, `require`, or `verify-full` | | `ssl_ca` | — | No | Rejected; strict TLS uses the system trust store | @@ -137,6 +137,19 @@ fails at runtime if `libgssapi_krb5` (package `libgssapi-krb5-2` on Debian/Ubuntu, `krb5-libs` on RHEL/Alpine) is missing, or without a valid Kerberos ticket (`kinit`) and `/etc/krb5.conf`. +### NTLM authentication + +The second checkbox, "Use NTLM", writes `extra.ntlm = "true"` and keeps the +username/password inputs. Enter the username as `DOMAIN\user` or +`user@domain`. The plugin then authenticates with NTLM through the pure-Rust +[`sspi`](https://crates.io/crates/sspi) crate on every platform, so Linux and +macOS need no Kerberos setup or system library. It plugs into mssql-tds' +`SecurityContextProvider` hook ([microsoft/mssql-rs#707](https://github.com/microsoft/mssql-rs/issues/707)). + +NTLM cannot be combined with integrated authentication, and it requires a +username. Channel bindings (Extended Protection) are not sent, so servers +that require Extended Protection reject it. + A connection string may be combined with discrete fields. Values explicitly present in the string are authoritative, while discrete fields fill only fields the string omits. Repeating the same value is allowed; contradictory @@ -372,7 +385,7 @@ remaining pools. ## Known Limitations -- SQL authentication and Windows/Kerberos integrated authentication (`integrated_auth`) are supported; Azure AD authentication is follow-up work. +- SQL authentication, Windows/Kerberos integrated authentication (`integrated_auth`) and NTLM (`ntlm`) are supported; Azure AD authentication is follow-up work. - Primary-key membership changes are disabled: the single-column alteration API cannot safely preserve composite PKs and referencing foreign keys. - Custom CA files are rejected explicitly; strict verification uses the system trust store. - SQL Server has indexed views, not materialized views. Indexed views are maintained synchronously and have no refresh operation, so `get_materialized_views`, `get_materialized_view_columns`, `get_materialized_view_definition`, and `refresh_materialized_view` deliberately return `-32601` rather than pretending the features are equivalent. diff --git a/src/connection.rs b/src/connection.rs index 73d19a1..60e85d9 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -49,6 +49,12 @@ pub fn resolve_connection_params(params: &ConnectionParams) -> Result Result) -> String { | TdsError::ImplementationError(_) | TdsError::UnimplementedFeature { .. } | TdsError::TypeConversionError(_) + | TdsError::EncodedValueTooLong { .. } | TdsError::UnsupportedEncoding { .. } | TdsError::BulkCopyError(_) | TdsError::ColumnEncryptionError(_) => format!("SQL Server driver failure: {error}"), diff --git a/src/driver/mod.rs b/src/driver/mod.rs index 6cf10d3..1319c0f 100644 --- a/src/driver/mod.rs +++ b/src/driver/mod.rs @@ -11,6 +11,7 @@ pub mod explain; pub mod extract; pub mod helpers; pub mod introspection; +pub mod ntlm; pub mod ops; pub mod pool; pub mod query_templates; diff --git a/src/driver/ntlm.rs b/src/driver/ntlm.rs new file mode 100644 index 0000000..4202fe1 --- /dev/null +++ b/src/driver/ntlm.rs @@ -0,0 +1,197 @@ +//! NTLM with explicit `DOMAIN\user` credentials, on every platform. +//! +//! mssql-tds' built-in integrated auth is Kerberos-only on Linux/macOS +//! (GSSAPI). This plugs Devolutions' pure-Rust `sspi` NTLM client into its +//! `SecurityContextProvider` hook instead, so no system library is needed. +//! Channel bindings (Extended Protection) are not sent. + +use mssql_tds::security::{ + IntegratedAuthConfig, SecurityContext, SecurityContextProvider, SecurityError, SspiAuthToken, +}; +use sspi::{ + AuthIdentity, AuthIdentityBuffers, BufferType, ClientRequestFlags, CredentialUse, + DataRepresentation, Ntlm, SecurityBuffer, SecurityStatus, Sspi, SspiImpl, Username, +}; + +pub struct NtlmProvider { + identity: AuthIdentity, +} + +impl NtlmProvider { + /// `username` is `DOMAIN\user` or `user@domain`. + pub fn new(username: &str, password: &str) -> Result { + let username = Username::parse(username) + .map_err(|error| format!("invalid NTLM username {username:?}: {error}"))?; + Ok(Self { + identity: AuthIdentity { + username, + password: password.to_string().into(), + }, + }) + } +} + +impl SecurityContextProvider for NtlmProvider { + fn create_context( + &self, + _config: &IntegratedAuthConfig, + server: &str, + port: u16, + ) -> Result, SecurityError> { + let mut ntlm = Ntlm::new(); + let credentials = ntlm + .acquire_credentials_handle() + .with_credential_use(CredentialUse::Outbound) + .with_auth_data(&self.identity) + .execute(&mut ntlm) + .map_err(|error| SecurityError::AcquireCredentialsFailed { + code: error.error_type as u32, + message: error.to_string(), + })? + .credentials_handle; + Ok(Box::new(NtlmContext { + ntlm, + credentials, + spn: format!("MSSQLSvc/{server}:{port}"), + complete: false, + })) + } +} + +struct NtlmContext { + ntlm: Ntlm, + credentials: Option, + spn: String, + complete: bool, +} + +impl SecurityContext for NtlmContext { + fn package_name(&self) -> &str { + "NTLM" + } + + fn generate_token( + &mut self, + server_token: Option<&[u8]>, + ) -> Result { + let failed = |error: sspi::Error| SecurityError::InitContextFailed { + code: error.error_type as u32, + message: error.to_string(), + }; + let mut input = vec![SecurityBuffer::new( + server_token.unwrap_or_default().to_vec(), + BufferType::Token, + )]; + let mut output = vec![SecurityBuffer::new(Vec::new(), BufferType::Token)]; + let mut builder = self + .ntlm + .initialize_security_context() + .with_credentials_handle(&mut self.credentials) + .with_context_requirements(ClientRequestFlags::ALLOCATE_MEMORY) + .with_target_data_representation(DataRepresentation::Native) + .with_target_name(&self.spn) + .with_output(&mut output); + if server_token.is_some() { + builder = builder.with_input(&mut input); + } + let status = self + .ntlm + .initialize_security_context_impl(&mut builder) + .map_err(failed)? + .resolve_to_result() + .map_err(failed)? + .status; + if matches!( + status, + SecurityStatus::CompleteAndContinue | SecurityStatus::CompleteNeeded + ) { + self.ntlm.complete_auth_token(&mut output).map_err(failed)?; + } + self.complete = !matches!( + status, + SecurityStatus::ContinueNeeded | SecurityStatus::CompleteAndContinue + ); + let data = output.pop().map(|buffer| buffer.buffer).unwrap_or_default(); + Ok(SspiAuthToken::new(data, self.complete)) + } + + fn is_complete(&self) -> bool { + self.complete + } + + fn spn(&self) -> &str { + &self.spn + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sspi::ServerRequestFlags; + + /// Runs the client against sspi's NTLM server, as SQL Server would. + fn handshake(user: &str, client_password: &str, server_password: &str) -> sspi::Result<()> { + let client = NtlmProvider::new(user, client_password).expect("username parses"); + let mut client = client + .create_context(&IntegratedAuthConfig::new(), "db.example.com", 1433) + .expect("context"); + + let mut server = Ntlm::new(); + let server_identity = AuthIdentity { + username: Username::parse(user).expect("username parses"), + password: server_password.to_string().into(), + }; + let mut server_credentials = server + .acquire_credentials_handle() + .with_credential_use(CredentialUse::Inbound) + .with_auth_data(&server_identity) + .execute(&mut server)? + .credentials_handle; + + let mut token = client.generate_token(None).expect("negotiate"); + assert!(!token.is_complete); + loop { + let mut input = vec![SecurityBuffer::new(token.data, BufferType::Token)]; + let mut output = vec![SecurityBuffer::new(Vec::new(), BufferType::Token)]; + let builder = server + .accept_security_context() + .with_credentials_handle(&mut server_credentials) + .with_context_requirements(ServerRequestFlags::ALLOCATE_MEMORY) + .with_target_data_representation(DataRepresentation::Native) + .with_input(&mut input) + .with_output(&mut output); + let status = server + .accept_security_context_impl(builder)? + .resolve_to_result()? + .status; + if matches!( + status, + SecurityStatus::CompleteAndContinue | SecurityStatus::CompleteNeeded + ) { + server.complete_auth_token(&mut output)?; + } + if status != SecurityStatus::ContinueNeeded { + assert!(client.is_complete()); + return Ok(()); + } + token = client + .generate_token(Some(&output[0].buffer)) + .expect("authenticate"); + } + } + + #[test] + fn completes_a_handshake_with_matching_credentials() { + handshake(r"CONTOSO\alice", "Secret1!", "Secret1!").expect("server accepts"); + } + + #[test] + fn a_wrong_password_is_rejected() { + assert!(handshake(r"CONTOSO\alice", "wrong", "Secret1!").is_err()); + } + + #[test] + fn rejects_an_unparseable_username() { + assert!(NtlmProvider::new(r"CONTOSO\alice\bob", "x").is_err()); + } +} diff --git a/src/driver/pool.rs b/src/driver/pool.rs index 87e4931..cc7db88 100644 --- a/src/driver/pool.rs +++ b/src/driver/pool.rs @@ -11,10 +11,12 @@ //! requests encrypted local-development-compatible connections. use std::future::Future; +use std::sync::Arc; use std::time::Duration; use crate::connection::{custom_ca_error, resolve_connection_params}; use crate::driver::error::{bridge_error_requires_discard, format_bridge_error}; +use crate::driver::ntlm::NtlmProvider; use crate::models::ConnectionParams; use crate::settings::PluginSettings; use deadpool::managed::{Manager, Metrics, RecycleError, RecycleResult}; @@ -194,8 +196,8 @@ impl Manager for BridgeManager { /// Build a `mssql_tiberius_bridge::Config` from Tabularis `ConnectionParams`. /// /// Consumes the shared connection fields used by current Tabularis drivers. -/// Uses `AuthMethod::Integrated` when `integrated_auth` is set, else -/// username/password. TLS maps `ssl_mode` onto the bridge's encryption policy. +/// Uses `AuthMethod::Integrated` when `integrated_auth` is set, the same with +/// an [`NtlmProvider`] when `ntlm` is set, else username/password. TLS maps `ssl_mode` onto the bridge's encryption policy. pub fn build_config( params: &ConnectionParams, settings: &PluginSettings, @@ -207,6 +209,13 @@ pub fn build_config( cfg.database(params.database.primary()); if params.integrated_auth { cfg.authentication(AuthMethod::Integrated); + } else if params.ntlm { + let provider = NtlmProvider::new( + params.username.as_deref().unwrap_or(""), + params.password.as_deref().unwrap_or(""), + )?; + cfg.authentication(AuthMethod::Integrated) + .security_context_provider(Arc::new(provider)); } else { cfg.authentication(AuthMethod::sql_server( params.username.as_deref().unwrap_or("sa"), diff --git a/src/driver/pool/tests.rs b/src/driver/pool/tests.rs index 5055431..959c6cb 100644 --- a/src/driver/pool/tests.rs +++ b/src/driver/pool/tests.rs @@ -61,6 +61,23 @@ fn build_config_accepts_integrated_auth_without_credentials() { assert!(build_config(¶ms, &PluginSettings::default()).is_ok()); } +#[test] +fn build_config_accepts_ntlm_credentials() { + let mut params = base_params(Some("localhost"), Some(1433), "master"); + params.username = Some(r"CONTOSO\alice".into()); + params.ntlm = true; + assert!(build_config(¶ms, &PluginSettings::default()).is_ok()); +} + +#[test] +fn build_config_rejects_a_malformed_ntlm_username() { + let mut params = base_params(Some("localhost"), Some(1433), "master"); + params.username = Some(r"CONTOSO\alice\bob".into()); + params.ntlm = true; + let error = build_config(¶ms, &PluginSettings::default()).unwrap_err(); + assert!(error.contains("NTLM username"), "{error}"); +} + #[test] fn manager_is_clone_send_sync() { fn assert_send() {} diff --git a/src/models.rs b/src/models.rs index 466a876..ca924f5 100644 --- a/src/models.rs +++ b/src/models.rs @@ -56,6 +56,9 @@ pub struct ConnectionParams { /// Windows/Kerberos auth (SSPI/GSSAPI). Set via `extra["integrated_auth"]` /// or `Integrated Security=True` in `connection_string`; excludes username/password. pub integrated_auth: bool, + /// NTLM with `username` as `DOMAIN\user` (or `user@domain`) and `password`, + /// on every platform. Set via `extra["ntlm"]`; excludes `integrated_auth`. + pub ntlm: bool, /// Opaque plugin-specific fields forwarded verbatim by the host. pub extra: HashMap, /// URL or ADO.NET/ODBC keyword connection string. It is parsed and diff --git a/src/pool_manager.rs b/src/pool_manager.rs index 062c713..f7be8c5 100644 --- a/src/pool_manager.rs +++ b/src/pool_manager.rs @@ -29,6 +29,8 @@ fn build_connection_key(params: &ConnectionParams) -> String { let ssl_mode = params.ssl_mode.as_deref().unwrap_or("prefer"); let auth = if params.integrated_auth { "integrated".to_string() + } else if params.ntlm { + format!("ntlm:{}", params.username.as_deref().unwrap_or("")) } else { format!("sql:{}", params.username.as_deref().unwrap_or("")) }; @@ -174,6 +176,15 @@ mod tests { ); } + #[test] + fn ntlm_is_part_of_the_key_for_the_same_username() { + let sql_auth = params(Some("ss045-key")); + let mut ntlm = sql_auth.clone(); + ntlm.ntlm = true; + + assert_ne!(build_connection_key(&sql_auth), build_connection_key(&ntlm)); + } + #[test] fn database_is_part_of_the_key_and_identical_params_are_stable() { let master = params(Some("ss045-key")); diff --git a/ui/src/IntegratedAuthToggle.test.tsx b/ui/src/IntegratedAuthToggle.test.tsx index add12f4..9566946 100644 --- a/ui/src/IntegratedAuthToggle.test.tsx +++ b/ui/src/IntegratedAuthToggle.test.tsx @@ -8,9 +8,10 @@ import IntegratedAuthToggle from "./IntegratedAuthToggle"; function mount(extra: Record) { const setCredentialFieldsHidden = vi.fn(); + const setExtraField = vi.fn(); const container = document.createElement("div"); document.body.appendChild(container); - const context = { extra, setExtraField: vi.fn(), setCredentialFieldsHidden }; + const context = { extra, setExtraField, setCredentialFieldsHidden }; act(() => { createRoot(container).render( ) { />, ); }); - const checkbox = container.querySelector("input")!; - return { checkbox, setCredentialFieldsHidden }; + const inputs = container.querySelectorAll("input"); + const checkbox = inputs[0]; + const ntlmCheckbox = inputs[1]; + return { checkbox, ntlmCheckbox, setCredentialFieldsHidden, setExtraField }; } test("hides credential fields for a saved connection without a click", () => { @@ -34,3 +37,24 @@ test("leaves credential fields visible when the flag is unset", () => { expect(checkbox.checked).toBe(false); expect(setCredentialFieldsHidden).toHaveBeenCalledWith(false); }); + +test("NTLM keeps credential fields visible for DOMAIN\\user and password", () => { + const { checkbox, ntlmCheckbox, setCredentialFieldsHidden } = mount({ ntlm: "true" }); + expect(ntlmCheckbox.checked).toBe(true); + expect(checkbox.checked).toBe(false); + expect(setCredentialFieldsHidden).toHaveBeenCalledWith(false); +}); + +test("checking NTLM clears Windows Authentication", () => { + const { ntlmCheckbox, setExtraField } = mount({ integrated_auth: "true" }); + act(() => ntlmCheckbox.click()); + expect(setExtraField).toHaveBeenCalledWith("ntlm", "true"); + expect(setExtraField).toHaveBeenCalledWith("integrated_auth", ""); +}); + +test("checking Windows Authentication clears NTLM", () => { + const { checkbox, setExtraField } = mount({ ntlm: "true" }); + act(() => checkbox.click()); + expect(setExtraField).toHaveBeenCalledWith("integrated_auth", "true"); + expect(setExtraField).toHaveBeenCalledWith("ntlm", ""); +}); diff --git a/ui/src/IntegratedAuthToggle.tsx b/ui/src/IntegratedAuthToggle.tsx index 55f92cc..ac70cfc 100644 --- a/ui/src/IntegratedAuthToggle.tsx +++ b/ui/src/IntegratedAuthToggle.tsx @@ -12,6 +12,7 @@ interface ExtraFieldsContext { export default function IntegratedAuthToggle({ context }: SlotComponentProps) { const c = context as ExtraFieldsContext; const checked = c.extra?.integrated_auth === "true"; + const ntlm = c.extra?.ntlm === "true"; const setCredentialFieldsHidden = c.setCredentialFieldsHidden; // Also runs on mount: a saved connection arrives with extra.integrated_auth @@ -20,16 +21,32 @@ export default function IntegratedAuthToggle({ context }: SlotComponentProps) { setCredentialFieldsHidden?.(checked); }, [checked, setCredentialFieldsHidden]); + // The two modes exclude each other; the backend rejects both at once. + const select = (key: "integrated_auth" | "ntlm", other: string, on: boolean) => { + c.setExtraField?.(key, on ? "true" : ""); + if (on) c.setExtraField?.(other, ""); + }; + return ( - +
+ + +
); } + +const labelStyle = { display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }; From 54c59debe7de52d3636fe9641f6b79b561f2f6cd Mon Sep 17 00:00:00 2001 From: Egert Aia Date: Sat, 7 Nov 2026 16:59:06 +0200 Subject: [PATCH 2/8] build: pin mssql-tds 0.4.0 and mssql-tiberius-bridge 0.3.0 Both are now on crates.io. Map mssql-tds 0.4.0's new TvpCellSerialization error to a driver failure. Co-Authored-By: Claude Haiku 5.5 --- Cargo.lock | 1296 ++++++++++++++++++++++++++++++++++++++++++- src/driver/error.rs | 1 + 2 files changed, 1280 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1462f6b..84875ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,17 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aes" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fc36d7440d015b45468ba08a21e80e056ebbd014c611c6298bb7503e04bd1" +dependencies = [ + "cipher", + "cpubits", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.7.8" @@ -53,7 +64,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.119", - "synstructure", + "synstructure 0.13.2", ] [[package]] @@ -67,6 +78,36 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "async-dnssd" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d49ffe175ab45bbfd74b548313d9d7cdfff27161a94b007b52eeeb5f9aaa15e" +dependencies = [ + "bitflags 1.3.2", + "futures-channel", + "futures-core", + "futures-executor", + "futures-util", + "libc", + "log", + "pin-utils", + "pkg-config", + "tokio", + "winapi", +] + +[[package]] +name = "async-recursion" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f8abc12baad266b1c8cec146854c195b5864b4221d4b2ca7296a7ae82d9e451" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -106,12 +147,24 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "base16ct" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" + [[package]] name = "base64" version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "bigdecimal" version = "0.4.10" @@ -125,6 +178,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.13.1" @@ -143,6 +202,33 @@ dependencies = [ "wyz", ] +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "block-padding" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + [[package]] name = "borsh" version = "1.8.0" @@ -195,6 +281,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" + [[package]] name = "byteorder" version = "1.5.0" @@ -207,6 +299,15 @@ version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +[[package]] +name = "cbc" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.4.0" @@ -264,6 +365,28 @@ dependencies = [ "windows-link", ] +[[package]] +name = "cipher" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + [[package]] name = "core-foundation" version = "0.10.1" @@ -280,6 +403,12 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + [[package]] name = "cpufeatures" version = "0.3.0" @@ -295,6 +424,92 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-bigint" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c035cb64cba03dad2fb921f3e218785e8cf9a41790da5eb3a1400f62fa2be11" +dependencies = [ + "cpubits", + "ctutils", + "getrandom 0.4.3", + "hybrid-array", + "num-traits", + "rand_core 0.10.1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "getrandom 0.4.3", + "hybrid-array", + "rand_core 0.10.1", +] + +[[package]] +name = "crypto-mac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-primes" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3633a51a39c69ebbaa4feaa694bd83d241e4093901c84a0963b19d9bb3f0cf8f" +dependencies = [ + "crypto-bigint", + "rand_core 0.10.1", +] + +[[package]] +name = "ctutils" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261af4dc7a06ea8a527a8717d8cbba3417530d6ea14e1edb3de6b67806be474f" +dependencies = [ + "cmov", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rand_core 0.10.1", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "data-encoding" version = "2.11.0" @@ -338,6 +553,17 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2657f61fb1dd8bf37a8d51093cc7cee4e77125b22f7753f49b289f831bec2bae" +[[package]] +name = "der" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a996a108feb8b427a6e12fcf6af4aa83409b79d72c15337d7741368131ee004" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "der-parser" version = "10.0.0" @@ -358,6 +584,27 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +[[package]] +name = "des" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916a94e407b54f9034d71dd748234cd1e516ced6284009906ae246f177eafe5a" +dependencies = [ + "cipher", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "ctutils", +] + [[package]] name = "displaydoc" version = "0.2.7" @@ -381,6 +628,67 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "ecdsa" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0681a4fc24c767085329728d8dfba959af91228aa4610cca4f8ce317ba46ae0" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", + "zeroize", +] + +[[package]] +name = "ed25519" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fcf32e6c73d1079f83ab4d782de2d81620346a5f38c6237a86a22f8368980a" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ebaa1a2bf1290ab3bfe5a7b771d050ebffab2711c19a81691c683a5144a25de" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.10.1", + "sha2", + "signature", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900f37e7e18d74a2347389af6cd69e3a30d5cc9e697f40004865679aa75e9c7c" +dependencies = [ + "base16ct", + "crypto-bigint", + "crypto-common", + "digest", + "ff", + "group", + "hkdf", + "hybrid-array", + "pem-rfc7468", + "pkcs8", + "rand_core 0.10.1", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encoding_rs" version = "0.8.35" @@ -412,6 +720,22 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" +[[package]] +name = "ff" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f686ab92a9fb0eaf188f6c6c87b89490baa6fdb0db4544ba4dc47f7942489f" +dependencies = [ + "rand_core 0.10.1", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -439,6 +763,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + [[package]] name = "funty" version = "2.0.0" @@ -533,6 +866,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -544,6 +887,20 @@ dependencies = [ "wasi", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + [[package]] name = "getrandom" version = "0.4.3" @@ -552,10 +909,21 @@ checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "rand_core 0.10.1", ] +[[package]] +name = "group" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd1a1c7a5206c5b7a3f5a0d7ccd3ff85d0c8f5133d62a02680255b0004af5f4" +dependencies = [ + "ff", + "rand_core 0.10.1", + "subtle", +] + [[package]] name = "half" version = "2.7.1" @@ -594,6 +962,30 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest", +] + [[package]] name = "hostname" version = "0.4.2" @@ -605,6 +997,17 @@ dependencies = [ "windows-link", ] +[[package]] +name = "hybrid-array" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" +dependencies = [ + "subtle", + "typenum", + "zeroize", +] + [[package]] name = "iana-time-zone" version = "0.1.65" @@ -629,6 +1032,110 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe090a42a0d3140fed8c63263ed1fecc02422cb2f4bfe55cd8de2de1b8e105dd" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25d29b57c17c6528d0dc4c2141cfa2d08200465acb537a3909c8b9b8a4a984c0" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404a3b8c486f205c87fe7f23ab6894d84a4ad76d6e4671ae1981ba7def87c599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20f0088bfb7441f7a37fa0c9e20cb1e9cba1cac6b9ce8cd2a6dc44294f8e8cbc" + +[[package]] +name = "icu_properties" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ea83d991c56158f7cf898bf86436c1dfe7c07ee82fe88951f2695c9f37a379f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98f29af82d02b163fe50161388350e743bb3107cc8e8c2f7314cb505faddfcf" + +[[package]] +name = "icu_provider" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413099315636c588ee8f011190b329b971a09a8fae9d157e01dcae8379468514" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indexmap" version = "2.14.0" @@ -648,6 +1155,16 @@ dependencies = [ "cfb", ] +[[package]] +name = "inout" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a580c13f0ffc335ef42dd3f6b1a41b726051c5e1656d9a3aa6fddb3c5dfbbf9" +dependencies = [ + "block-padding", + "hybrid-array", +] + [[package]] name = "itoa" version = "1.0.18" @@ -665,6 +1182,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keccak" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f198d1db720e4940b5a493201d199d9f24f568f8f746bd13706243a2f71598" +dependencies = [ + "cfg-if", + "cpufeatures", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -689,6 +1216,12 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "litemap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + [[package]] name = "lock_api" version = "0.4.14" @@ -704,6 +1237,25 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "md-5" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "md4" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd76fb0fd6b2e4be62a73f8e0858ca97f81babcb1af322dcaca196f735f17f80" +dependencies = [ + "digest", +] + [[package]] name = "memchr" version = "2.8.3" @@ -729,13 +1281,14 @@ dependencies = [ [[package]] name = "mssql-tds" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03612dd2098a7b98613b423414afaf3031ff080a24652941abfc1d2e13f6222" +checksum = "812c3993a5f6d98e14da9d8ab0bf9f9f536e49c18240f34af9bae301e4d35ae8" dependencies = [ "async-trait", "bigdecimal", - "bitflags", + "bitflags 2.13.1", + "block2", "byteorder", "bytes", "core-foundation", @@ -758,7 +1311,7 @@ dependencies = [ "tracing", "uuid", "winapi", - "windows", + "windows 0.58.0", "windows-sys 0.59.0", "x509-parser", "zeroize", @@ -766,9 +1319,9 @@ dependencies = [ [[package]] name = "mssql-tiberius-bridge" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f77f4020816d04d7710bc8f74fe832100b1e13e6ee4a90614946845c64aa617" +checksum = "7baca2d0d0d280ba914f058718ad41a09bcfd1a330d67a5c18ae720064963de9" dependencies = [ "async-stream", "async-trait", @@ -826,6 +1379,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +[[package]] +name = "num-derive" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e98dc3b890f6c23a0f9d3d491a2823d0dea0fa656302a13dd225fa924112a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -854,6 +1418,30 @@ dependencies = [ "libc", ] +[[package]] +name = "objc2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08849bbd4767dfae9457696856ae1c84fe4e0281bbe4a7abff2d0e06fb7981f8" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "oid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c19903c598813dba001b53beeae59bb77ad4892c5c1b9b3500ce4293a0d06c2" +dependencies = [ + "serde", +] + [[package]] name = "oid-registry" version = "0.8.1" @@ -875,7 +1463,7 @@ version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags", + "bitflags 2.13.1", "cfg-if", "foreign-types", "libc", @@ -922,6 +1510,47 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "p256" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c9239b2dbc807adbbe147e8cf72ea7450c3a0aabe62cb8e75ff4ec22e1f72a" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d17b851e6b3e378ab4ecb07fa2ed23f4d15f075735f8fec9fa1e7bdce5f8301f" +dependencies = [ + "ecdsa", + "elliptic-curve", + "fiat-crypto", + "primefield", + "primeorder", + "sha2", +] + +[[package]] +name = "p521" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad64cc32c2dc466317c12ee5853e61f159f9eab1fe7efade0395dc2e7b43449" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primefield", + "primeorder", + "sha2", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -945,18 +1574,179 @@ dependencies = [ "windows-link", ] +[[package]] +name = "pbkdf2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "pem-rfc7468" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "picky" +version = "7.0.0-rc.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bcf32b73bfc151bc07c3fbf35e729ad3078d48c581f8656c0f62a529fbf681c" +dependencies = [ + "base64", + "crypto-bigint", + "crypto-common", + "digest", + "ed25519-dalek", + "hex", + "inout", + "md-5", + "p256", + "p384", + "p521", + "picky-asn1", + "picky-asn1-der", + "picky-asn1-x509", + "pkcs1", + "rand 0.10.2", + "rand_core 0.10.1", + "rsa", + "serde", + "sha1", + "sha2", + "sha3", + "thiserror", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "picky-asn1" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9e56b8955035e2593f7f7e7f8d30c9c7a0ce5a5e31cc529f8f087a9e0437526" +dependencies = [ + "oid", + "serde", + "serde_bytes", + "time", + "zeroize", +] + +[[package]] +name = "picky-asn1-der" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4467118a2c640f4040aea27d01293620984b0b3f3ef0c53577c3bbf6bab4256" +dependencies = [ + "picky-asn1", + "serde", + "serde_bytes", +] + +[[package]] +name = "picky-asn1-x509" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98dd311a5e525d1200365273a509b9d07bccf3481aaa901047fdca19830ca721" +dependencies = [ + "base64", + "crypto-bigint", + "oid", + "picky-asn1", + "picky-asn1-der", + "serde", + "widestring", + "zeroize", +] + +[[package]] +name = "picky-krb" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9306c2a07e8bfd1faa0985b76bc7b86ab98f2b9a1433fdfa4c9a116b6e4c8a3d" +dependencies = [ + "aes", + "block-padding", + "byteorder", + "cbc", + "cipher", + "crypto-bigint", + "des", + "hmac", + "inout", + "oid", + "pbkdf2", + "picky-asn1", + "picky-asn1-der", + "picky-asn1-x509", + "rand 0.10.2", + "rand_core 0.10.1", + "serde", + "sha1", + "thiserror", + "uuid", +] + [[package]] name = "pin-project-lite" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "pin-utils" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13bee6c73da26345c729282832b60b0363cf3dd9f4bfd81d8551b7a1c889a113" + +[[package]] +name = "pkcs1" +version = "0.8.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "986d2e952779af96ea048f160fd9194e1751b4faea78bcf3ceb456efe008088e" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -978,6 +1768,33 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a65843dfefbafd3c879c683306959a6de478443ffe9c9adf02f5976432402d7" +[[package]] +name = "primefield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c555a6e4eb7d4e158fcb028c835c3b8642206ddc279b5c6b202ef9a8bdb592f4" +dependencies = [ + "crypto-bigint", + "crypto-common", + "ff", + "rand_core 0.10.1", + "subtle", + "zeroize", +] + +[[package]] +name = "primeorder" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c9f42978c78a00e3d68f69fc03e57a234debae69da4020a4fb588fcdcd07b06" +dependencies = [ + "elliptic-curve", + "once_cell", + "primefield", + "serdect", + "wnaf", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -1025,6 +1842,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + [[package]] name = "r-efi" version = "6.0.0" @@ -1090,16 +1913,26 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.13.1", +] + +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", ] [[package]] -name = "rend" -version = "0.4.2" +name = "rfc6979" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +checksum = "b4a459cddafb3fe76b31fd8f1108007566c40301feb64dc7b54656eb7388172b" dependencies = [ - "bytecheck", + "crypto-bigint", + "hmac", ] [[package]] @@ -1131,6 +1964,24 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rsa" +version = "0.10.0-rc.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b2aa4ba0d89f73d1e332df05be0eeab8840351c36ca5654341dfdb57bb3caf" +dependencies = [ + "const-oid", + "crypto-bigint", + "crypto-primes", + "digest", + "pkcs1", + "pkcs8", + "rand_core 0.10.1", + "signature", + "spki", + "zeroize", +] + [[package]] name = "rust_decimal" version = "1.42.1" @@ -1148,6 +1999,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rusticata-macros" version = "4.1.0" @@ -1163,7 +2023,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.13.1", "errno", "libc", "linux-raw-sys", @@ -1197,13 +2057,27 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sec1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56d437c2f19203ce5f7122e507831de96f3d2d4d3be5af44a0b0a09d8a80e4d" +dependencies = [ + "base16ct", + "ctutils", + "der", + "hybrid-array", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.13.1", "core-foundation", "core-foundation-sys", "libc", @@ -1220,6 +2094,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" version = "1.0.229" @@ -1230,6 +2110,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" +dependencies = [ + "serde", + "serde_core", +] + [[package]] name = "serde_core" version = "1.0.229" @@ -1263,6 +2153,49 @@ dependencies = [ "zmij", ] +[[package]] +name = "serdect" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9bad02c26382724b2d2692c6f179285e4b54eeecd7968f52a50059c3c11759" +dependencies = [ + "digest", + "keccak", + "sponge-cursor", +] + [[package]] name = "shlex" version = "2.0.1" @@ -1279,6 +2212,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" +dependencies = [ + "digest", + "rand_core 0.10.1", +] + [[package]] name = "simdutf8" version = "0.1.5" @@ -1317,6 +2260,22 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "spki" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef958a98b9d5da290cfc78946e9f3e61e1e62a18db0d92cac0b83cc161491a9" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sponge-cursor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0219bd7d979d58245a4f41f695e1ac9f8befdffadd7f61f1bae9e39abc6620" + [[package]] name = "sqlserver-plugin" version = "1.0.0-beta.4" @@ -1331,10 +2290,68 @@ dependencies = [ "openssl", "serde", "serde_json", + "sspi", + "tokio", + "uuid", +] + +[[package]] +name = "sspi" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3fa5e1405884e88be309bd801760caa84c654be746fe4261ab407496263692" +dependencies = [ + "async-dnssd", + "async-recursion", + "bitflags 2.13.1", + "bytemuck", + "byteorder", + "cfg-if", + "crypto-bigint", + "crypto-mac", + "futures", + "getrandom 0.3.4", + "hmac", + "md-5", + "md4", + "num-derive", + "num-traits", + "oid", + "picky", + "picky-asn1", + "picky-asn1-der", + "picky-asn1-x509", + "picky-krb", + "pkcs1", + "rand 0.10.2", + "rand_core 0.10.1", + "rsa", + "serde", + "sha1", + "sha2", + "time", "tokio", + "tracing", + "url", "uuid", + "widestring", + "windows 0.62.2", + "windows-registry", + "zeroize", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -1379,6 +2396,17 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "synstructure" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + [[package]] name = "tap" version = "1.0.1" @@ -1392,7 +2420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.3.4", "once_cell", "rustix", "windows-sys 0.61.2", @@ -1425,6 +2453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244" dependencies = [ "deranged", + "js-sys", "num-conv", "powerfmt", "serde_core", @@ -1448,6 +2477,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abc840c238154d58f9e86b2792261edfde565a17696e1cda1a449de27979801a" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.12.0" @@ -1581,12 +2620,45 @@ dependencies = [ "once_cell", ] +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af3bd9d3e571c26fcce9d033b87ea5ab061b8d2ffe9b7a5675d810d68f03edf0" +dependencies = [ + "utf_types", +] + +[[package]] +name = "utf_types" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3b425286980a367278453f3b6d28cdcb134b574e5a35824a6ff5eebad50bb6" + [[package]] name = "uuid" version = "1.28.0" @@ -1596,6 +2668,7 @@ dependencies = [ "getrandom 0.4.3", "js-sys", "rand 0.10.2", + "serde_core", "wasm-bindgen", ] @@ -1617,6 +2690,15 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.126" @@ -1673,6 +2755,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + [[package]] name = "winapi" version = "0.3.9" @@ -1705,6 +2793,27 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core 0.62.2", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", +] + [[package]] name = "windows-core" version = "0.58.0" @@ -1731,6 +2840,17 @@ dependencies = [ "windows-strings 0.5.1", ] +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link", + "windows-threading", +] + [[package]] name = "windows-implement" version = "0.58.0" @@ -1781,6 +2901,27 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core 0.62.2", + "windows-link", +] + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -1887,6 +3028,15 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -1992,6 +3142,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wnaf" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795ca18b3fdb5e62bf982199278341ddcf7ebf7d32e25e212ad05d496e95f6fa" +dependencies = [ + "ff", + "group", + "hybrid-array", + "primefield", +] + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + [[package]] name = "wyz" version = "0.5.1" @@ -2001,6 +3175,17 @@ dependencies = [ "tap", ] +[[package]] +name = "x25519-dalek" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e8131a03190127fb2263afc72b322ecadae46b6ff8c6f399ff5d02f5559af6" +dependencies = [ + "curve25519-dalek", + "rand_core 0.10.1", + "zeroize", +] + [[package]] name = "x509-parser" version = "0.18.1" @@ -2018,6 +3203,29 @@ dependencies = [ "time", ] +[[package]] +name = "yoke" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417ef3fcf6c300b7dbd25c85531a746931c02ad536f3cf4786ed1e88223340b3" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", + "synstructure 0.14.0", +] + [[package]] name = "zerocopy" version = "0.8.55" @@ -2038,6 +3246,27 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", + "synstructure 0.14.0", +] + [[package]] name = "zeroize" version = "1.9.1" @@ -2058,6 +3287,39 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58a2799cfe9a1670c7ea8edbd52ef8edb93cb37a7f83bf31ba9e35d9dae6a40" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3743ddbf47738d929cd1ae2e199d40d0162979dfe31aef8ae646d2bf00bf97a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + [[package]] name = "zmij" version = "1.0.23" diff --git a/src/driver/error.rs b/src/driver/error.rs index 23f7ff5..2f62d1b 100644 --- a/src/driver/error.rs +++ b/src/driver/error.rs @@ -59,6 +59,7 @@ pub fn format_tds_error(error: &TdsError, ssl_mode: Option<&str>) -> String { | TdsError::UnimplementedFeature { .. } | TdsError::TypeConversionError(_) | TdsError::EncodedValueTooLong { .. } + | TdsError::TvpCellSerialization { .. } | TdsError::UnsupportedEncoding { .. } | TdsError::BulkCopyError(_) | TdsError::ColumnEncryptionError(_) => format!("SQL Server driver failure: {error}"), From 87d9ddee1404ecfd6c68db06e0bf06bad37f9a87 Mon Sep 17 00:00:00 2001 From: Egert Aia Date: Sun, 8 Nov 2026 00:04:27 +0200 Subject: [PATCH 3/8] test: generate random NTLM test secrets Co-Authored-By: Claude Haiku 5.5 --- Cargo.lock | 1 + Cargo.toml | 4 ++++ src/driver/ntlm.rs | 18 ++++++++++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84875ca..2e12bda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2288,6 +2288,7 @@ dependencies = [ "mssql-tiberius-bridge", "once_cell", "openssl", + "rand 0.8.7", "serde", "serde_json", "sspi", diff --git a/Cargo.toml b/Cargo.toml index a157d03..3468d91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,10 @@ uuid = "1" # targets keep the platform TLS stack selected by native-tls. openssl = { version = "0.10", features = ["vendored"] } +[dev-dependencies] +# Random test secrets; the tests must not hardcode passwords. +rand = "0.8" + [profile.release] lto = true codegen-units = 1 diff --git a/src/driver/ntlm.rs b/src/driver/ntlm.rs index 4202fe1..fa7a032 100644 --- a/src/driver/ntlm.rs +++ b/src/driver/ntlm.rs @@ -127,8 +127,19 @@ impl SecurityContext for NtlmContext { #[cfg(test)] mod tests { use super::*; + use rand::distributions::Alphanumeric; + use rand::{thread_rng, Rng}; use sspi::ServerRequestFlags; + /// A fresh random password, so no test depends on a fixed secret. + fn random_secret() -> String { + thread_rng() + .sample_iter(&Alphanumeric) + .take(24) + .map(char::from) + .collect() + } + /// Runs the client against sspi's NTLM server, as SQL Server would. fn handshake(user: &str, client_password: &str, server_password: &str) -> sspi::Result<()> { let client = NtlmProvider::new(user, client_password).expect("username parses"); @@ -182,12 +193,15 @@ mod tests { #[test] fn completes_a_handshake_with_matching_credentials() { - handshake(r"CONTOSO\alice", "Secret1!", "Secret1!").expect("server accepts"); + let secret = random_secret(); + handshake(r"CONTOSO\alice", &secret, &secret).expect("server accepts"); } #[test] fn a_wrong_password_is_rejected() { - assert!(handshake(r"CONTOSO\alice", "wrong", "Secret1!").is_err()); + let (client_secret, server_secret) = (random_secret(), random_secret()); + assert_ne!(client_secret, server_secret); + assert!(handshake(r"CONTOSO\alice", &client_secret, &server_secret).is_err()); } #[test] From 554601170581e0952f0d380afd52921e9840b931 Mon Sep 17 00:00:00 2001 From: Egert Aia Date: Sun, 8 Nov 2026 00:07:01 +0200 Subject: [PATCH 4/8] test: use random secrets in unit tests Replace hardcoded passwords in unit tests with a shared random_secret() helper in common.rs. Live-database tests and injection payloads are unchanged. Co-Authored-By: Claude Haiku 5.5 --- src/common.rs | 12 ++++++++++++ src/connection.rs | 33 ++++++++++++++++++++------------- src/driver/error.rs | 13 +++++++------ src/driver/ntlm.rs | 12 +----------- src/driver/pool/tests.rs | 3 ++- src/rpc.rs | 2 +- 6 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/common.rs b/src/common.rs index ced5c70..0c7ac9b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -70,3 +70,15 @@ pub fn returns_result_set(query: &str) -> bool { | "CALL" ) } + +/// A fresh random password for tests. Tests must not hardcode secrets. +#[cfg(test)] +pub(crate) fn random_secret() -> String { + use rand::distributions::Alphanumeric; + use rand::{thread_rng, Rng}; + thread_rng() + .sample_iter(&Alphanumeric) + .take(24) + .map(char::from) + .collect() +} diff --git a/src/connection.rs b/src/connection.rs index 60e85d9..822d05c 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -779,11 +779,14 @@ mod tests { #[test] fn equal_discrete_values_are_accepted_and_missing_values_fill_in() { - let mut input = params("Server=db.example,1433;Database=app;User Id=sa;Password=secret"); + let secret = crate::common::random_secret(); + let mut input = params(&format!( + "Server=db.example,1433;Database=app;User Id=sa;Password={secret}" + )); input.host = Some("DB.EXAMPLE".into()); input.port = Some(1433); input.username = Some("sa".into()); - input.password = Some("secret".into()); + input.password = Some(secret); input.ssl_mode = Some("require".into()); let resolved = resolve_connection_params(&input).unwrap(); @@ -812,11 +815,12 @@ mod tests { #[test] fn integrated_auth_rejects_username_and_password() { + let secret = crate::common::random_secret(); for connection_string in [ - "Server=localhost;Integrated Security=True;User Id=sa", - "Server=localhost;Integrated Security=True;Password=secret", + "Server=localhost;Integrated Security=True;User Id=sa".to_string(), + format!("Server=localhost;Integrated Security=True;Password={secret}"), ] { - let error = resolve_connection_params(¶ms(connection_string)).unwrap_err(); + let error = resolve_connection_params(¶ms(&connection_string)).unwrap_err(); assert!(error.contains("integrated authentication"), "{error}"); } } @@ -838,7 +842,7 @@ mod tests { let mut input = ConnectionParams { host: Some("localhost".into()), username: Some(r"CONTOSO\alice".into()), - password: Some("secret".into()), + password: Some(crate::common::random_secret()), ..Default::default() }; input.extra.insert("ntlm".into(), "true".into()); @@ -923,19 +927,22 @@ mod tests { #[test] fn password_parse_errors_never_echo_credentials() { + let first = crate::common::random_secret(); + let second = crate::common::random_secret(); + let malformed = crate::common::random_secret(); for (connection_string, secret) in [ ( - "Server=localhost;Password=FirstSecret!;Password=SecondSecret!", - "FirstSecret!", + format!("Server=localhost;Password={first};Password={second}"), + first.clone(), ), ( - "sqlserver://sa:Malformed%ZZSecret@localhost/master", - "Malformed", + format!("sqlserver://sa:{malformed}%ZZ@localhost/master"), + malformed.clone(), ), ] { - let error = resolve_connection_params(¶ms(connection_string)).unwrap_err(); - assert!(!error.contains(secret), "{error}"); - assert!(!error.contains(connection_string), "{error}"); + let error = resolve_connection_params(¶ms(&connection_string)).unwrap_err(); + assert!(!error.contains(&secret), "{error}"); + assert!(!error.contains(&connection_string), "{error}"); } } diff --git a/src/driver/error.rs b/src/driver/error.rs index 2f62d1b..11140ea 100644 --- a/src/driver/error.rs +++ b/src/driver/error.rs @@ -274,19 +274,20 @@ mod tests { #[test] fn redaction_removes_password_and_connection_string() { - let connection_string = "Server=db;User Id=sa;Password=NeverExposeThis!;Encrypt=true"; + let secret = crate::common::random_secret(); + let connection_string = format!("Server=db;User Id=sa;Password={secret};Encrypt=true"); let params = ConnectionParams { - password: Some("NeverExposeThis!".into()), - connection_string: Some(connection_string.into()), + password: Some(secret.clone()), + connection_string: Some(connection_string.clone()), database: DatabaseSelection::Single("master".into()), ..Default::default() }; let message = redact_connection_secrets( - format!("failed with NeverExposeThis! from {connection_string}"), + format!("failed with {secret} from {connection_string}"), ¶ms, ); - assert!(!message.contains("NeverExposeThis!")); - assert!(!message.contains(connection_string)); + assert!(!message.contains(&secret)); + assert!(!message.contains(&connection_string)); assert!(message.contains("")); } } diff --git a/src/driver/ntlm.rs b/src/driver/ntlm.rs index fa7a032..ffb0be5 100644 --- a/src/driver/ntlm.rs +++ b/src/driver/ntlm.rs @@ -127,19 +127,9 @@ impl SecurityContext for NtlmContext { #[cfg(test)] mod tests { use super::*; - use rand::distributions::Alphanumeric; - use rand::{thread_rng, Rng}; + use crate::common::random_secret; use sspi::ServerRequestFlags; - /// A fresh random password, so no test depends on a fixed secret. - fn random_secret() -> String { - thread_rng() - .sample_iter(&Alphanumeric) - .take(24) - .map(char::from) - .collect() - } - /// Runs the client against sspi's NTLM server, as SQL Server would. fn handshake(user: &str, client_password: &str, server_password: &str) -> sspi::Result<()> { let client = NtlmProvider::new(user, client_password).expect("username parses"); diff --git a/src/driver/pool/tests.rs b/src/driver/pool/tests.rs index 959c6cb..f75581e 100644 --- a/src/driver/pool/tests.rs +++ b/src/driver/pool/tests.rs @@ -1,4 +1,5 @@ use super::*; +use crate::common::random_secret; use crate::models::{ConnectionParams, DatabaseSelection}; use crate::settings::PluginSettings; @@ -8,7 +9,7 @@ fn base_params(host: Option<&str>, port: Option, db: &str) -> ConnectionPar host: host.map(String::from), port, username: Some("sa".into()), - password: Some("Strong!Pass123".into()), + password: Some(random_secret()), database: DatabaseSelection::Single(db.into()), ..Default::default() } diff --git a/src/rpc.rs b/src/rpc.rs index 926a423..8bec0eb 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -412,7 +412,7 @@ mod tests { host: Some("localhost".into()), port: Some(1433), username: Some("sa".into()), - password: Some("test-password".into()), + password: Some(crate::common::random_secret()), database: crate::models::DatabaseSelection::Single("master".into()), connection_id: Some("shutdown-rpc-test".into()), ..Default::default() From 6f06d6909c70ffebb59b7ab37f4010d41e7f29d4 Mon Sep 17 00:00:00 2001 From: Egert Aia Date: Sun, 8 Nov 2026 00:22:35 +0200 Subject: [PATCH 5/8] refactor(ui): name connection-modal styles and extract ModeCheckbox Co-Authored-By: Claude Haiku 5.5 --- ui/src/IntegratedAuthToggle.tsx | 67 +++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/ui/src/IntegratedAuthToggle.tsx b/ui/src/IntegratedAuthToggle.tsx index ac70cfc..57fe908 100644 --- a/ui/src/IntegratedAuthToggle.tsx +++ b/ui/src/IntegratedAuthToggle.tsx @@ -1,4 +1,4 @@ -import { useEffect } from "react"; +import { useEffect, type CSSProperties } from "react"; import type { SlotComponentProps } from "@tabularis/plugin-api"; // Optional: falls back gracefully on hosts predating TabularisDB/tabularis#780. @@ -9,44 +9,61 @@ interface ExtraFieldsContext { setCredentialFieldsHidden?: (hidden: boolean) => void; } +type AuthMode = "integrated_auth" | "ntlm"; + +const modesStyle: CSSProperties = { display: "flex", flexDirection: "column", gap: 4 }; +const checkboxLabelStyle: CSSProperties = { + display: "flex", + alignItems: "center", + gap: 8, + cursor: "pointer", +}; + +interface ModeCheckboxProps { + label: string; + checked: boolean; + onToggle: (on: boolean) => void; +} + +function ModeCheckbox({ label, checked, onToggle }: ModeCheckboxProps) { + return ( + + ); +} + export default function IntegratedAuthToggle({ context }: SlotComponentProps) { const c = context as ExtraFieldsContext; - const checked = c.extra?.integrated_auth === "true"; + const integratedAuth = c.extra?.integrated_auth === "true"; const ntlm = c.extra?.ntlm === "true"; const setCredentialFieldsHidden = c.setCredentialFieldsHidden; // Also runs on mount: a saved connection arrives with extra.integrated_auth // already set and never fires onChange. useEffect(() => { - setCredentialFieldsHidden?.(checked); - }, [checked, setCredentialFieldsHidden]); + setCredentialFieldsHidden?.(integratedAuth); + }, [integratedAuth, setCredentialFieldsHidden]); // The two modes exclude each other; the backend rejects both at once. - const select = (key: "integrated_auth" | "ntlm", other: string, on: boolean) => { - c.setExtraField?.(key, on ? "true" : ""); + const selectMode = (mode: AuthMode, other: AuthMode, on: boolean) => { + c.setExtraField?.(mode, on ? "true" : ""); if (on) c.setExtraField?.(other, ""); }; return ( -
- - +
+ selectMode("integrated_auth", "ntlm", on)} + /> + selectMode("ntlm", "integrated_auth", on)} + />
); } - -const labelStyle = { display: "flex", alignItems: "center", gap: 8, cursor: "pointer" }; From e8a3b10a9b33c1048d9f969080e46328b95c2904 Mon Sep 17 00:00:00 2001 From: Egert Aia Date: Sun, 8 Nov 2026 00:23:19 +0200 Subject: [PATCH 6/8] refactor(ui): keep connection-modal styles inline Co-Authored-By: Claude Haiku 5.5 --- ui/src/IntegratedAuthToggle.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/ui/src/IntegratedAuthToggle.tsx b/ui/src/IntegratedAuthToggle.tsx index 57fe908..54370af 100644 --- a/ui/src/IntegratedAuthToggle.tsx +++ b/ui/src/IntegratedAuthToggle.tsx @@ -1,4 +1,4 @@ -import { useEffect, type CSSProperties } from "react"; +import { useEffect } from "react"; import type { SlotComponentProps } from "@tabularis/plugin-api"; // Optional: falls back gracefully on hosts predating TabularisDB/tabularis#780. @@ -11,14 +11,6 @@ interface ExtraFieldsContext { type AuthMode = "integrated_auth" | "ntlm"; -const modesStyle: CSSProperties = { display: "flex", flexDirection: "column", gap: 4 }; -const checkboxLabelStyle: CSSProperties = { - display: "flex", - alignItems: "center", - gap: 8, - cursor: "pointer", -}; - interface ModeCheckboxProps { label: string; checked: boolean; @@ -27,7 +19,7 @@ interface ModeCheckboxProps { function ModeCheckbox({ label, checked, onToggle }: ModeCheckboxProps) { return ( -