Skip to content

Client: Allow SMB2 create contexts on CreateFile, and add SMB2_CREATE_TIMEWARP_TOKEN - #372

Open
smbecker wants to merge 2 commits into
TalAloni:masterfrom
smbecker:feature/smb2-create-contexts
Open

smbecker wants to merge 2 commits into
TalAloni:masterfrom
smbecker:feature/smb2-create-contexts

Conversation

@smbecker

Copy link
Copy Markdown

What this does

Lets a client send SMB2 create contexts with CreateFile and read the ones the server answers
with, and adds the pieces needed to open a previous version (shadow copy) of a file.

Closes #371.

Background

CreateRequest.CreateContexts and CreateResponse.CreateContexts were already implemented; the client API simply had no way to reach them. A shadow copy is addressed with the
SMB2_CREATE_TIMEWARP_TOKEN create context.

Compatibility

The existing CreateFile overload is unchanged and now delegates to the new one passing null contexts, so behavior for current callers is identical. Nothing is added to ISMBFileStore since create-contexts are SMB2-specific, and that interface is also implemented by SMB1 and server-side stores. A caller that needs contexts uses SMB2FileStore directly.

…_TIMEWARP_TOKEN

The SMB2 layer already carried create contexts in both directions --
CreateRequest.CreateContexts and CreateResponse.CreateContexts are parsed and
serialized -- but the client had no way to send or read them, so a caller could
not open a previous version of a file.

A shadow copy is addressed with the SMB2_CREATE_TIMEWARP_TOKEN create context.
The @GMT- path prefix is not a server-side convention: smbclient and the Windows
redirector translate such a path into a TimeWarp token, which is why a raw SMB2
client that sends the token in the path gets STATUS_OBJECT_PATH_NOT_FOUND from
Samba while smbclient reads the same file.

- SMB2FileStore.CreateFile gains an overload taking the create contexts to send
  and returning those the server answered with. The existing overload delegates
  to it, so behaviour is unchanged for current callers.
- CreateContextName holds the context names from [MS-SMB2] 2.2.13.2.
- CreateContextHelper builds and reads SMB2_CREATE_TIMEWARP_TOKEN and looks a
  context up by name.

Verified against Samba with shadow_copy2 and two snapshots: opening report.txt
with a TimeWarp token for the older snapshot reads that snapshot's content,
while opening it without one reads the live file. Those integration tests are
inconclusive unless ServerAddress is set, since the in-process SMBServer does
not serve shadow copies.
@TalAloni

Copy link
Copy Markdown
Owner

Thanks Shaun,
Given that this is a niche use case, I'm not sure how I want to proceed here,
The CreateFile API is hard-to-understand as it is, so even if I had gone with the CreateFile overload you suggested in the pull request, having it marked as "protected" rather than "public" would have made more sense (to avoid cluttering the public API)
In that alternative, the CreateContextName class and the CreateContextHelper class should be part of the solution that use the library and not part of the library itself.
To put it more bluntly: I have no interest in exposing an API that allows a client to open a previous version of a file, but I am open to enable developers to utilize such capabilities.

@smbecker

Copy link
Copy Markdown
Author

Thanks Shaun, Given that this is a niche use case, I'm not sure how I want to proceed here, The CreateFile API is hard-to-understand as it is, so even if I had gone with the CreateFile overload you suggested in the pull request, having it marked as "protected" rather than "public" would have made more sense (to avoid cluttering the public API) In that alternative, the CreateContextName class and the CreateContextHelper class should be part of the solution that use the library and not part of the library itself. To put it more bluntly: I have no interest in exposing an API that allows a client to open a previous version of a file, but I am open to enable developers to utilize such capabilities.

I can certainly remove the CreateContextName and CreateContextHelper classes as those are probably a bit too niche to include in the public API as part of this project. However, without the public overload for request/response create-context, how would a developer be able to utilize such capabilities? Given that ISMBClient.TreeConnect is what is responsible for discovering what implementation of ISMBFileStore to return and developers have no ability to override that today, making the overload protected would still render it pretty much inaccessible.

@smbecker

Copy link
Copy Markdown
Author

To put it more bluntly: I have no interest in exposing an API that allows a client to open a previous version of a file, but I am open to enable developers to utilize such capabilities.

The current approach of using a public method on SMB2FileStore was my attempt at not messing with the public API that most developers would generally be consuming (utilizing ISMBFileStore) while still making it available for developers to utilize such capabilities.

@TalAloni

TalAloni commented Sep 18, 2026

Copy link
Copy Markdown
Owner

without the public overload for request/response create-context, how would a developer be able to utilize such capabilities? Given that ISMBClient.TreeConnect is what is responsible for discovering what implementation of ISMBFileStore to return and developers have no ability to override that today, making the overload protected would still render it pretty much inaccessible.

Thanks, you make a good point, there would need to be a "protected virtual" CreateFileStore method in SMB2Client for that to work.
Not loving this but definitely better than exposing CreateContext as part of a public API.
(CreateContext is an SMB2 concept, not a file store concept, so it feels wrong even before we consider how complicated the CreateFile API is)

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.

Client cannot send SMB2 create contexts, so previous versions (shadow copies) cannot be opened

2 participants