-
Notifications
You must be signed in to change notification settings - Fork 732
Remove usage of deprecated libssh functions #4408
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
base: main
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4408 +/- ##
==========================================
- Coverage 89.78% 88.99% -0.80%
==========================================
Files 257 238 -19
Lines 16884 15273 -1611
==========================================
- Hits 15160 13592 -1568
+ Misses 1724 1681 -43 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
3rd-party/libssh/CMakeLists.txt
Outdated
set(BUILD_SHARED_LIBS OFF) | ||
set(CMAKE_POSITION_INDEPENDENT_CODE ON) | ||
elseif(MSVC) | ||
set(BUILD_SHARED_LIBS OFF) |
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.
To be able to build with libssh internal C functions that are not exposed via LIBSSH_API, it is necessary to not build shared libs in windows.
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.
Instead of disabling the shared lib altogether, would something like WINDOWS_EXPORT_ALL_SYMBOLS work here?
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.
Built and tested in Windows and Linux.
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.
Overall pretty good! Just some concerns about using private SSH headers and some nitpicks
mp::SSH::throw_on_error(sftp_server_session, | ||
session, | ||
"[sftp] server init failed", | ||
sftp_server_init); |
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.
From libssh source /* @deprecated in favor of sftp_server_new() and callbacks based sftp server */
, maybe we should move to a callbacks based sftp server? Although, that'd require a ton more work with little benefit.
I'm not really a fan of including the private header, could make updates painful in the future. Also reimplementing the deprecated functions doesn't seem much better than just defining SSH_SUPPRESS_DEPRECATED
IMO. I don't know, I'd like to get other's thoughts on this
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.
I agree, but the comment plus the commit message leave us with little information. It is not ideal to reimplement, but at least now those functions are "maintained" now. I would be happy to work on moving to the callbacks based sftp server, and that was what I initally researched, but I found no existing documentation on that option. If anyone finds anything I will be happy to take a look at what changes are necessary.
In the case of get_exit_state, there is no other option really. Until we deal with SSH return codes with more consistency, reimplementing seemed like the only viable option.
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.
Yeah the documentation is pretty much nonexistent for sftp server functionality from what I can tell. I could only find this example implementation but that itself isn't well commented or documented
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.
Yeah, apart from the default subsystem request and default data callback... besides, it does say that those two are not supported in windows (ifdef + comment), so I do not think they are an option in this case. Sadly, until we do more research or someone finds some documentation we will have to go with the reimplementations. Is it possible that existing sftp servers all rely on the deprecated functions or old versions?
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.
Our implementation is a pretty popular reference implementation so it's possible
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.
Perhaps just add a comment here explaining the rationale and linking to an issue for moving to a callback-based version?
tests/test_sftpserver.cpp
Outdated
: exit_status_mock.success_status); | ||
|
||
return nullptr; | ||
return (calls++ & 1) ? nullptr : message.get(); |
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.
this check seems odd (pun intended)
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.
I know, but I reached it through trial and error. In the test it seems like there are 2 sftp server inits with a message_get in between, that is why the lambda looks so odd :D
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.
How is calls
different from num_calls
? Could we use the latter value here? It looks like that would match what's happening with exit_status_mock.set_exit_status
just above.
After some research, I have found in Gitlab the following libssh mirror that does implement an sample_sftpserver.c: https://gitlab.com/libssh/libssh-mirror/-/blob/master/examples/sample_sftpserver.c And in the PR they did they comment more on it. From a first (inexperienced) look, moving to callbacks may require a major refactor. Now at least we have a working (?) example. I am unsure if this is a fork of our libssh or viceversa, but I think it would be nice to have this example. |
6504417
to
6e412ed
Compare
Signed-off-by: Vedant Borkar <vedantborkar1234@gmail.com>
Signed-off-by: Vedant Borkar <vedantborkar1234@gmail.com>
Co-authored-by: Mădălin-Florin GOIAN <79133273+MadalinGOIAN@users.noreply.github.com> Signed-off-by: Vedant Borkar <vedantborkar1234@gmail.com>
Signed-off-by: Vedant Borkar <vedantborkar1234@gmail.com>
Signed-off-by: Vedant Borkar <vedantborkar1234@gmail.com>
Signed-off-by: Vedant Borkar <vedantborkar1234@gmail.com>
Signed-off-by: Vedant Borkar <vedantborkar1234@gmail.com>
The deprecated function ssh_get_exit_status was replaced with the supported ssh_get_exit_state by replicating the ssh_get_exit_status within our codebase until we decide to use the additional information that the new function makes accessible (e.g. SIG info, the get_exit_state retcode...). Within the tests due to the more complex behavior of ssh_get_exit_state multiple adjustments had to be made. Moving them to SetUp does not work within SetUp() without further adjustments, so for now the lowest energy solution has been applied.
Most of the existing warnings and errors coming from the deprecated function declarations from the libssh library come from the library itself. It includes the legacy.h header in its main header libssh.h and that header contains all the deprecated functions. Since it has to be built and the warnings come from internal use in deprecated functions of other deprecated functions, the most pragmatic and correct solution is to silence the warnings coming from building libssh itself. The usage of deprecated functions outside libssh will still raise a warning or error.
Also moved the make_sftp_server to the class namespace for future mocking.
The function is replace with its existing internal functionality. Because in this case we cannot rely on the abstraction of S SSH:throw_on_error due to the libssh functions not setting the ssh_error on failure (previously the role of the replaced function), the exception management is done directly.
6e412ed
to
02ddf0b
Compare
On the test, the solution is not very clean. The execution order of the functions is exec->init->msg->exec->exec(not sshfs)->init->msg, (where after the PR init becomes a different msg) so a single index cannot account for behavior of both functions very cleanly |
Perhaps pass in a queue and pop the front element off each time? That would be similar to how |
6d6fde1
to
22f70c6
Compare
The queue does not seem cleaner than just checking PD: I also added a new test to cover the termination signal logging. |
0732a75
to
cdd4dbd
Compare
ssh_init had to be added to the windows daemon and to the client due to static linking. It could be excluded from linux and macos where it is not necessary via macros, but it has no negative effects (as tested in linux). |
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.
Pull Request Overview
This PR removes usage of deprecated libssh functions by replacing them with custom implementations or alternative APIs. The primary changes involve replacing sftp_server_init
with manual initialization logic and ssh_channel_get_exit_status
with ssh_channel_get_exit_state
to handle signal termination properly.
Key changes:
- Replaced deprecated
sftp_server_init
with manual SFTP initialization handling - Replaced
ssh_channel_get_exit_status
withssh_channel_get_exit_state
for better exit state management - Added SSH library initialization/finalization calls in client and daemon entry points
Reviewed Changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
File | Description |
---|---|
src/sshfs_mount/sftp_server.cpp | Implemented manual SFTP initialization replacing deprecated sftp_server_init |
src/ssh/ssh_client.cpp | Added ssh_channel_get_exit_status wrapper using ssh_channel_get_exit_state |
tests/test_ssh_client.cpp | Updated tests to mock ssh_channel_get_exit_state instead of deprecated function |
tests/test_sftpserver.cpp | Added SFTP init message handling to all test cases |
tests/test_sshfsmount.cpp | Added mock SFTP client message setup for mount tests |
tests/test_cli_client.cpp | Updated mocks to use ssh_channel_get_exit_state |
tests/sftp_server_test_fixture.h | Changed fixture to use sftp_server_free instead of deprecated sftp_free |
tests/mock_ssh_test_fixture.h | Updated to mock ssh_channel_get_exit_state |
tests/mock_ssh.h | Changed mock declaration from ssh_channel_get_exit_status to ssh_channel_get_exit_state |
tests/mock_ssh.cpp | Updated mock implementation signature for exit state |
tests/mock_sftpserver.h | Added sftp_reply_version and sftp_server_free mocks |
tests/mock_sftpserver.cpp | Implemented new mock functions |
tests/c_mock_defines.cmake | Updated C mock definitions for new function signatures |
src/sshfs_mount/sftp_server.h | Updated type alias to use sftp_server_free |
src/daemon/daemon_main_win.cpp | Added ssh_init /ssh_finalize calls |
src/client/cli/client.h | Made destructor virtual and non-default |
src/client/cli/client.cpp | Added ssh_init /ssh_finalize in constructor/destructor |
include/multipass/ssh/ssh_client.h | Added private ssh_channel_get_exit_status helper method |
CMakeLists.txt | Added compiler flags to suppress deprecation warnings for libssh |
3rd-party/libssh/CMakeLists.txt | Updated build configuration for Windows |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
3rd-party/libssh/CMakeLists.txt
Outdated
set(BUILD_SHARED_LIBS OFF) | ||
set(CMAKE_POSITION_INDEPENDENT_CODE ON) | ||
elseif(MSVC) | ||
set(BUILD_SHARED_LIBS OFF) |
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.
Instead of disabling the shared lib altogether, would something like WINDOWS_EXPORT_ALL_SYMBOLS work here?
After the stfp_server_init change the libssh premock requires that a new function be mocked in the tests and some adjustments are made. The function to be mocked is sftp_reply_version, which requires minor changes. The adjustment of sftp_get_client_message requires more adjustments due to how many times it is called in the codebase. test_sftpserver.cpp already has a framework that simplifies the changes, while test_sshfsmount.cpp requires the introduction of stateful lambdas to make the tests possible.
A comment was also added in case we want to log part of the sftp server initialization.
Unfortunately it seems that both clang and LLVM diverge in the treatment of captured constants, and the only fix is to either input manually or to use macros.
cdd4dbd
to
558340d
Compare
Unfortunately, it seems like MSVC requires exposing all symbols to be able to access the functions without the LIBSSH_API prefix, which in this case we are only interested in sftp_reply_version, which used to happen internally inside sftp_server_init. Seems like the current best solution, but still could be suboptimal. In this commit it is done by making the libssh library static, but later a CMake option will be set to expose these symbols only on Windows.
The logging framework was included, and the if statement logic was simplified.
558340d
to
eee2f5c
Compare
In the end, the CMake flag you suggested works, so I am closing the related threads. Thanks! |
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.
LGTM
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.
LGTM!
The main purpose of this PR is to replace the deprecated functions in libssh, which are unmantained, by our own code, since those functions do not have replacements. This gives us control over those sections of code and allows us to maintain them.
In terms of tests, the changes were as minimal as possible without changing outside the PREMOCK framework that is used for all libssh functions.
Some of the deprecated warnings came from the building of libssh itself, so those warnings are silenced at the submodule level.
Fixes #4227
MULTI-2243