-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add symbolic link functionality for SMB2 #309
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the rather long delay, a bit of unexpected downtime...
Some comments inline.
src/main/java/jcifs/internal/smb2/Smb2ErrorContextResponse.java
Outdated
Show resolved
Hide resolved
src/main/java/jcifs/internal/smb2/Smb2ErrorContextResponse.java
Outdated
Show resolved
Hide resolved
src/main/java/jcifs/internal/smb2/Smb2ErrorContextResponse.java
Outdated
Show resolved
Hide resolved
src/main/java/jcifs/internal/smb2/Smb2ErrorContextResponse.java
Outdated
Show resolved
Hide resolved
src/main/java/jcifs/internal/smb2/Smb2ErrorContextResponse.java
Outdated
Show resolved
Hide resolved
@mbechler thanks for your review! Ok I’m off on vacation for two weeks and when I get back I’ll look into this, thanks. |
@mbechler Sorry for the lengthy delay... I'm going to start reviewing your feedback notes this week and next and address your comments. Thanks! |
@mbechler I've addressed a lot of your feedback points, however I need your help and expertise on a few items that I might not have covered off completely. Thanks! |
@mbechler My apologies for the chatty commits over the last couple of weeks, however I am ready for another review. Thanks! |
70f6dd9
to
4a74ebc
Compare
Polish code, remove spaces Polish code, remove unused method Revert last change Improve design, rename, refactor some classes Implement recursion limiter Improve JUnit test, follow test framework default utilities Polish code, fix typos, consistent variable names Refactor JUnit test to support Jcif testing framework Add support for resolving relative symlinks Increase coverage of unit tests for relative symlinks
4a74ebc
to
1bf0060
Compare
@mbechler I rebased my branch to master to make sure they were in sync with the latest changes in master. Please review at your convenience and let me know if we can move forward with this PR. Thanks! |
Thanks, unfortunately It's going to be another two to three weeks till I can get back on this. |
Hi Greg, thanks for contribution to the jcifs SMB library, it stumbled our team a bit that no one else came across symbolic link issues much sooner ;-). Anyway , we recently had issues with paths (Windows) containing symbolic links and it seemed your solution was the one to go to. I tested the code from your branch for our specific needs and after 1 modification, it does the job very well. |
Interesting... according to the spec at https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/9ff8837c-c4f7-452b-9272-8818a119dae9 ErrorId for a symlink error should be zero I really don't think the Windows server version has anything to do with what you are seeing. I have to follow the spec that Microsoft has written so not sure what is going on... Can you attach a code snippit of your fix so that I can test it? The Windows File server that I have been testing against is the Datacenter 2016 version, I'll see if I have a server version that you are using, however again I really don't think it has anything to do with that because the SMB2 specs have been around for quite some time now and it doesn't look like Microsoft has revised them for each server version, however @mbechler would know better as he has more experience with the specs. |
It seems to follow this spec;
.... |
It seems readErrorResponse in ServerMessageBlock2.java already strips of the first 8 bytes of the error and returns the actual ErrorData which should match the structure in https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/f15ae37d-a787-4bf2-9940-025a8c9c0022 |
I still believe we should make sure that we get the behavior in #309 (comment) right/according to spec. I was planning to check against the Microsoft implementation, but haven't gotten around to. |
So with the setup on the server (2K19) as follows:
after enabling bidirectional local/remote symlink following on a Win10 machine (
Relevant packet captures, link error data: capture.zip So I think the correct behavior would be:
|
Can you explain why you would do this on the client? Or am I misinterpreting this test case which I never would have anticipated for? Furthermore my client is locked down by my organization, so I don't have local admin access to run a command like this to enable bi-directional symlinks on my laptop which I am sure would not be allowed by my organization anyways due to security concerns. Is this really a valid test case scenario that needs to be supported? From my point of view all that is needed is to be able to resolve symlinks on the remote machine only, even if the substitute name comes back as a path that is local to the remote machine. The solution I have come up with is to replace the front part of the substitute name path with the remote share path that we already know and append the substitute name path back from the end to figure out the target path. Wouldn't that be a more portable solution, particularly if the client is on a UNIX host? |
That was just to investigate how Windows would interpret the symlinks. As I mentioned I also don't think we should resolve remote to local symlinks. What I mean is that with the current implementation we will end up resolving to invalid targets (e.g. imagine an absolute local path that contains the share name, or an UNC path that contains the share name in the hostname, or what happens if it does not - indexOf = -1). This may cause strange, difficult to understand errors which we should avoid and instead do it according to spec and then be able to properly detect which type it is and whether to handle it or bail out with an error. |
Ok understood... However I'm still at a lost to move forward with any other changes for this contribution. I'd appreciate if you could take what I have already proposed and make the changes as you see fit to work with the current implementation as I don't have the detailed level of knowledge of the internal workings of this code base that you do. Thanks! |
Hi Greg, This is the case with and without forcing the dialect to SMB311 |
Yep ok, got it... I never unit tested with a UNC path (if that is what I am interpreting here), however now I get what @mbechler is concerned about, however still not sure how to code it properly as I don't have the detailed knowledge of the internal code base. |
@mbechler Ok points 1, 2, 4 are completed. Point 3 is completed, however for DFS I have no internal knowledge of how this was implemented so I did not add any handling for this scenario. Local target paths will not be resolved, this will be left up to the client to further resolve/process as they will know the share and share directory to construct the root path to the server's local symlink target which will be availble via |
Hi Gregory, Smb2CreateResponse createResp = cr.getResponse(); { this.isSymLink = true; Smb2SymLinkResolver resolver = new Smb2SymLinkResolver(); String targetPath = resolver.parseSymLinkErrorData(createResp.getFileName(), createResp.getErrorData()); this.symLinkTargetPath = targetPath; th.send(new Smb2CloseRequest(th.getConfig(), createResp.getFileId()), RequestParam.NO_RETRY); } { th.send(new Smb2CloseRequest(th.getConfig(), createResp.getFileId()), RequestParam.NO_RETRY); } RecursionLimiter.java: It still seems the intention is to only support DialectVersion.SMB311, will this change in the near future? Now only local paths are supported (\??\) |
Regarding 3.1.1: That is the only version that supports symlinks via this mechanism (providing the symlink data via error response). There might be an alternate route, e.g. making an IOCTL request if the error code is received, but have not looked at this at all. Regarding absolute targets, if it's cross-share or cross-server things become a lot more complicate as now the requests need to be routed differently, and doing that transparently causes all kinds of issues, both architecture-wise and also logically (e.g. what credentials should be used in that case?). I haven't looked closely but I guess some improvement could be made regarding absolute targets on the same share, this should work as is, but I don't think this applies to your example, which is cross-share. |
The exception provided does supply the local target path as part of the message, however this can always be retrieved via Regarding With regards to |
@Dirk-A I tested your code suggestion:
This line after resolving the symlink throws an exception trying to close the request: so I propose we could enhance it this way: |
Hi Gregory, |
I should be able to take it from here. Hoping to be able to work on some stuff over christmas. |
Have not found as much time as I would have liked, but I created a branch (https://github.com/AgNO3/jcifs-ng/tree/GregBragg-Add_symlink_functionality) where I made some changes (fd5bd47). Still a work in progress though. I'm also hoping to implement symlink creation as well, as this would really be benefical for test cases. |
602f81f
to
2a52d08
Compare
Some more progress, implemented symlink creation etc, so I can work on automated test cases next. Also might have a solution for pre 3.1 versions. |
@mbechler I was able to pull down your branch and review, I think I understand the improvements you are making to my contribution. I was able to get the JUnit test to complete successfully with the following changes to the code: Looking forward to seeing the final changes to this enhancment. |
@mbechler It's been awhile since we had any activity on this enhancement. Any thoughts for when we can collaborate further on this PR proposal? Thanks! |
My apologies, I haven't had much time lately and got a bit distracted. Hoping to get back to work soon. |
Hi, it has indeed been a while. My feedback is still that the limitation to MIN version SMB311 is not acceptable for our application needs. These are the local library changes I still maintain to cover all use cases we encountered in the field: Smb2ErrorDataFormat.java =>
.... SmbFile.java => remove throwing exceptions in case of :
Smb2SymLinkResolver.java => take share into account:
|
My comment is that symlinks are only supported with the SMB 3.11 protocol. What you are proposing as a workaround does not follow the Microsoft specs for SMB2 as Moritz has already pointed out in a previous comment. |
Not entirely what I said. The symlink information is only available in the error response starting with 3.11, for earlier versions it has to be explicitly requested as part of the error handling. This need additional logic, but can be done. It will however be very inefficient, especially if the results are not cached. |
Fixes #245
Add symbolic link SMB2 Error Context handling for four use cases for supporting the current SMB 3.1.1 protocol:
isSymLink()
method to see if the file theSmbResource
represents is a symbolic link.