Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Add hook for custom SSPI context for SqlConnection instances #2253

Copy link
Copy link

Description

@twsouthwick
Issue body actions

Background

There have been a couple of active issues around NTLM/kerberos authentication and customizing it for various reasons (see discussions in #305 and #31), with an attempt of enabling this in #1379. This issue is to track an API proposal and the steps needed to integrate it into SqlClient.

NOTE:
I'm not sure of naming in this area and very open to better names for things. I haven't spent much time within the SSPI/GSS/NTLM/Kerberos/etc space and this proposal is based on my limited understanding of these concepts. If I'm missing anything important, please let me know

Proposal

The proposal is to add a provider that has the ability to generate a context given an incoming blob. There are currently a few ways that this is handled internally:

  • A native implementation on all Windows platforms
  • An internal managed implementation on .NET Standard/.NET 6
  • System.Net.Security.NegotiateAuthentication on .NET 7+

As part of this change, those different implementations should be moved to follow the same pattern as an external implementer would have to ensure the abstraction is sufficient. After attempting to do so, it appears the best design would be to have a class that is used per connection (retrieved via a factory method) as there is some state that may need to be accessed between invocations:

+ /// <summary>
+ /// Defines a provider to supply and operate on an SSPI context as part of integrated authentication.
+ /// </summary>
+ public abstract class SspiClientContextProvider
+ {
+     /// <summary>
+     /// Generates a context given a (possibly empty) previously buffer.
+     /// </summary>
+     /// <param name="incomingBlob">The incoming blob (may be empty).</param>
+     /// <param name="outgoingBlobWriter">A writer that allows us to write data for the outgoing blob.</param>
+     protected abstract bool GenerateContext(ReadOnlySpan<byte> incomingBlob, IBufferWriter<byte> outgoingBlobWriter, SspiAuthenticationParameters authParams);
+ }

public class SqlConnection
{
+   /// <summary>
+   /// Gets or sets a factory to handle the SSPI context
+   /// </summary>
+   public Func<SspiClientContextProvider> SspiContextProviderFactory { get; set; }
}

Alternate designs

  • We could just return a byte[] - but this would most likely requrie creating new arrays for any authentication

    public abstract class SspiClientContextProvider
    {
    -     protected abstract void GenerateContext(ReadOnlySpan<byte> incomingBlob, IBufferWriter<byte> outgoingBlobWriter);
    +     protected abstract byte[] GenerateContext(ReadOnlySpan<byte> incomingBlob);
    }
  • Or we could use an IMemoryOwner to track the lifetime of potentially pooled memory:

    public abstract class SspiClientContextProvider
    {
    -     protected abstract void GenerateContext(ReadOnlySpan<byte> incomingBlob, IBufferWriter<byte> outgoingBlobWriter);
    +     protected abstract IMemoryOwner<byte> GenerateContext(ReadOnlySpan<byte> incomingBlob);
    }

Implementation/Testing

While prototyping this, I found that as-is, it would be a fairly large change. However, I think it should be broken into the following steps to make sure we don't regress anything.

Some follow up items:

The first four are mostly refactorings that I'm assuming can use current testing to ensure no regressions (please correct me if that is incorrect). For the final two, the main thing to test will be that a custom implementation is picked up and handled correctly, which can be done with unit tests. I also plan on testing the E2E of this API by enabling NTLM with this enabled hook.

Reactions are currently unavailable

Metadata

Metadata

Assignees

Labels

Public API 🆕Issues/PRs that introduce new APIs to the driver.Issues/PRs that introduce new APIs to the driver.Up-for-Grabs 🙌Issues that are ready to be picked up for anyone interested. Please self-assign and remove the labelIssues that are ready to be picked up for anyone interested. Please self-assign and remove the label

Projects

Status
Done
Show more project fields

Relationships

None yet

Development

No branches or pull requests

Issue actions

Morty Proxy This is a proxified and sanitized view of the page, visit original site.