Repository navigation
mssql-tds: public SSPI context provider extension point (enables NTLM on Linux/macOS) #707
Description
Problem statement
On Linux/macOS, integrated authentication is Kerberos-only via GSSAPI (mssql-tds/src/security/unix/mod.rs: "NTLM is not supported on Unix platforms"). There is no way to authenticate with a Windows/AD login when Kerberos is not usable, for example when:
- the SQL Server service has no
MSSQLSvc/...SPN registered (common when the service account lacks permission to self-register SPNs, and fixing it requires a domain admin), - the client machine has no ticket or cannot reach a KDC.
In that situation the GSSAPI handshake fails with:
Failed to initialize security context (code=0x000D0000): Major: Miscellaneous failure (see text);
Minor: Server (MSSQLSvc/<host>@<REALM>) unknown while looking up 'MSSQLSvc/<host>@<REALM>'
The same server is reachable from:
- Windows clients, because SSPI Negotiate falls back to NTLM,
- the Microsoft JDBC driver on macOS, via
integratedSecurity=true;authenticationScheme=NTLMwith a domain user and password.
Downstream crates also can't supply their own implementation:
SecurityContextis public, but the handler always builds its context through the platformcreate_security_context.SspiAuthHandler::with_contextexists, but it is#[cfg(test)]andpub(crate). This is still the case in 0.2.0.
Proposed solution
A public extension point, equivalent to SqlConnection.SspiContextProvider in Microsoft.Data.SqlClient:
- Accept a user-supplied provider in
ClientContext(for exampleArc<dyn SecurityContextProvider>, or a factory closure) that creates aBox<dyn SecurityContext>per connection attempt, given the server, port and SPN. - When a provider is set,
SspiAuthHandleruses it instead of the built-in SSPI/GSSAPI context. When it isn't set, nothing changes. - Pass channel bindings to the provider, so custom contexts work against servers with Extended Protection enabled.
This keeps NTLM out of mssql-tds itself. Downstream crates can implement it, for example with the pure-Rust sspi crate (Devolutions sspi-rs), which tiberius 0.13 uses for the same purpose. The same hook would serve other custom schemes and test doubles.
Affected crate
mssql-tds
Alternatives considered
- Register the SPN. This is the right fix for Kerberos, but it needs a domain admin and isn't always possible for the person connecting.
- SQL authentication. Not available when the server only grants access to AD logins.
- Built-in opt-in NTLMv2 on Unix.
IntegratedAuthConfigwould carry explicit credentials, andSecurityPackage::Ntlmwould be honored on Unix. It would never be an automatic fallback from Kerberos. This is more convenient for users, but more surface for mssql-tds to own. - Fork mssql-tds downstream. Works, but every consumer then maintains a patched fork.
Additional context
Downstream consumer: the Tabularis SQL Server plugin, which uses mssql-tds 0.2.0 through mssql-tiberius-bridge 0.2.0. The bridge would need to pass the provider through as well. Suggested by Saurabh Singh (@saurabh500). Happy to test a branch against a real AD-joined SQL Server from macOS.
Activity
saurabh500 commentedon Oct 16, 2026
Egert (@egertaia) can you take a stab at the implementation?
egertaia commentedon Oct 16, 2026
Saurabh Singh (@saurabh500) not a problem :)
#742