Skip to content

Client: Add SMB2DfsFileStore to follow DFS referrals - #352

Merged
TalAloni merged 2 commits into
TalAloni:masterfrom
jahales:3-smb2-dfs-filestore
Jul 10, 2026
Merged

Client: Add SMB2DfsFileStore to follow DFS referrals#352
TalAloni merged 2 commits into
TalAloni:masterfrom
jahales:3-smb2-dfs-filestore

Conversation

@jahales

@jahales jahales commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Adds SMB2DfsFileStore, which follows DFS referrals transparently, building on the DFS data structures/helpers from #346 and ResetSecurityContext from #348. This is the client-side counterpart that ties those pieces together into working DFS support.

Integration (as you suggested in #326)

SMB2Client.TreeConnect() returns an SMB2DfsFileStore if and only if the tree connect reply has the SMB2_SHAREFLAG_DFS_ROOT flag set; otherwise it returns the plain SMB2FileStore as before. Non-DFS shares are completely unaffected.

Behavior

When a CreateFile is not covered by the DFS root (STATUS_PATH_NOT_COVERED), the store requests a DFS referral (via DfsReferralHelper), rewrites the path to the referral target (via DfsPath.ReplacePrefix), and retries the open against that target — connecting to another server when the target lives elsewhere, reusing the authentication client via IAuthenticationClient.ResetSecurityContext. Handles are routed back to the connection they were opened against, so reads/writes/closes go to the right target.

On breaking changes

You asked in #326 whether ResetSecurityContext would be the end of it. It is — that remains the only public/breaking API change. SMB2DfsFileStore is declared internal, and the cross-server connect/login reuse is done through internal helpers on SMB2Client (ConnectAndLoginToDfsTarget), so there's no further public surface. (I also updated the KerberosNetAuthenticationClient example in ClientExamples.md to implement the new interface method.)

The first commit (retaining the IAuthenticationClient after login) is the small piece from #348 folded in here, since it's only actually used by this file store — happy to close #348 in favor of this.

Scope / deliberate limitations

Kept intentionally minimal:

  • Single referral hop across servers, with a hop cap to guard against interlink loops.
  • Multi-target failover within a referral is handled (targets tried in preference order).
  • V3/V4 referral entries (what modern servers send); V1/V2 fall back to STATUS_PATH_NOT_COVERED.
  • No referral cache yet. MS-DFSC prescribes a TTL-based ReferralCache; I left it out to keep this PR focused, so each open under a link currently re-requests a referral. Easy follow-up if you'd like it.

Tests

SMB2DfsFileStoreTests covers the referral-following loop, handle routing, cross-server target selection, and multi-target failover using the real captured V4 referral format, without needing a live server.

A note on size

This is a bit larger than the earlier pieces. For what it's worth, SMB2DfsFileStore.cs is ~400 lines but ~150 of those are the mechanical ISMBFileStore forwarding methods and ~130 are the actual DFS logic. If you'd prefer, I'm happy to split the cross-server support (auth reuse + failover) out into a separate follow-up PR and keep this one to the wrapper + same-server referral following — just let me know.

jahales added 2 commits July 4, 2026 06:55
…r to support DFS

The authentication client is kept so it can be reused via ResetSecurityContext when following a DFS referral to another server.
TreeConnect() now returns an SMB2DfsFileStore when the share reply has the SMB2_SHAREFLAG_DFS_ROOT flag set. When a CreateFile is not covered by the DFS root (STATUS_PATH_NOT_COVERED), a DFS referral is requested and the operation is retried against the referral target, connecting to another server when necessary by reusing the authentication client via IAuthenticationClient.ResetSecurityContext.
@TalAloni

TalAloni commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Thank you Jacob!,
looks good and clean, the size is manageable, I'll take a closer look in the coming days.

@TalAloni
TalAloni merged commit 71e67ae into TalAloni:master Jul 10, 2026
@TalAloni

Copy link
Copy Markdown
Owner

Thank you! Merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants