oscerd opened a new pull request, #28214: URL: https://github.com/apache/camel/pull/28214
Jira: https://issues.apache.org/jira/browse/CAMEL-25886 ## Problem The SFTP consumers (`sftp` in camel-ftp and `mina-sftp`) apply `jailStartingDirectory` to the path built from each listed name only: `RemoteFileConsumer.isWithinStartingDirectory()` compacts that path and compares it with the starting directory as text. A listed entry that the server reports as a symbolic link is therefore handled like any other file, and when it is retrieved the server follows the link to its target, wherever that is. camel-file resolves symbolic links for `jailStartingDirectory` since CAMEL-25412, and the ftp consumer ignores the entries that the server lists as links (`FtpConsumer`, "Ignoring unsupported remote file type"). This gives the SFTP consumers the same semantics as camel-file. ## Change With `jailStartingDirectory` enabled (the default), the SFTP consumers resolve a listed file that the server reports as a symbolic link, and skip it when its target is outside the starting directory or cannot be resolved: - `SftpRemoteFile` (camel-ftp-common) has `default boolean isSymbolicLink()` returning `false`, so `SftpRemoteFileSingle` and other implementations stay compatible. `SftpRemoteFileJCraft` and `MinaSftpRemoteFile` return the link flag of the listing attributes. - New `SftpSymbolicLinkOperations` (camel-ftp-common), implemented by `SftpOperations` and `MinaSftpOperations`: the home directory of the session, `lstat` and `readlink`. It is a separate interface, so `RemoteFileOperations`, which `FtpOperations` implements too, does not change. - `GenericFileConsumer` has a protected overload `isWithinStartingDirectory(Supplier<GenericFile<T>>, String)` that also receives the listed file and delegates to the existing hook by default. `isValidFile()` calls it, so a skipped link is logged as for the lexical check (WARN the first time, DEBUG on later polls), before the in-progress and idempotent repositories are touched. - `AbstractSftpConsumer` overrides it. After the lexical check, an entry flagged as a link is resolved on the server one path segment at a time: an `lstat` of each segment and a `readlink` of each link, a relative target is resolved against the directory of the link, and at most 32 links are followed. It is accepted only when the result is inside the starting directory, which is resolved the same way once per poll (on the first link of the poll). A link that cannot be resolved (dangling, a loop, no target) is skipped. The `realpath` request is not used, because what it returns depends on the server: Apache MINA SSHD, which also runs the embedded test server, does not resolve links in it. - Only the entries that the listing reports as links are resolved, so other files take no extra request, and no entry is required to be a regular file (CAMEL-1247). - `jailStartingDirectory=false` keeps following every link. No option is added, so the endpoint metadata does not change. Links that resolve inside the starting directory, and a starting directory that is itself a link, work as before, so `MinaSftpSymlinkIT` and the "Symbolic Links" section of the mina-sftp documentation stay valid. ## Documentation - `sftp-component.adoc`: new section "Symbolic links and the starting directory", as in `file-component.adoc`. - `mina-sftp-component.adoc`: the "Symbolic Links" section describes the check and its limits. - The catalog copies of both pages are regenerated. - `camel-4x-upgrade-guide-4_24.adoc`: a note under "Upgrading Camel 4.23 to 4.24". The notes for 4.22.3 and 4.18.6 go to the 4_22 and 4_18 guides on main together with the backports. ## Tests - `RemoteFileConsumerStartingDirectoryJailTest` (camel-ftp), with a stubbed server and no network, four new tests: a listed file that is not a link is accepted without a request to the server; links resolving inside are accepted (relative, absolute, through a link to a directory, a link to a link, a link in a sub directory, a starting directory that is itself a link); links resolving outside are skipped (relative upwards, absolute, through a link to a directory outside, a sibling directory whose name extends the polled one, a link in a sub directory); and links that cannot be resolved are skipped (dangling, a loop, no target). - New `SftpConsumerJailStartingDirectorySymlinkIT` (camel-ftp) and `MinaSftpConsumerJailStartingDirectorySymlinkIT` (camel-mina-sftp), five tests each, against the embedded SFTP server with its default settings: a link resolving inside is consumed; links resolving outside (relative and absolute) are skipped, and followed with `jailStartingDirectory=false`; a dangling link is skipped; a link in a starting directory reached through a link is consumed. - Without the production change, `skipsLinkResolvingOutsideStartingDirectory` and `skipsDanglingLink` fail in both ITs, because the links are part of the first poll (batch size 3 and 2 instead of 1). With only the link check of `AbstractSftpConsumer` disabled, the two skip tests of `RemoteFileConsumerStartingDirectoryJailTest` fail. - `mvn verify` of camel-ftp (85 tests and 379 ITs) and camel-mina-sftp (26 tests and 278 ITs, including `MinaSftpSymlinkIT` and the dangling link test of `MinaSftpAdvancedFileOperationsIT`), and the file component tests of camel-core (474) pass, except `FtpProducerHealthCheckIT` on a machine with a non-English locale: it expects the English text "Connection refused", and passes with `LC_ALL=C`. - Full build `mvn clean install -DskipTests -DskipITs`: the catalog copies of the two pages are the only regenerated files. ## Notes - Whether a listing reports an entry as a link depends on the server. OpenSSH and Apache MINA SSHD (with its default settings) list a link with its own attributes; a server that lists the attributes of the target does not show the link, and with `useList=false` there is no listing. The documentation says so. - The check and the retrieval that follows are not atomic (an SFTP open follows links on the server), so the permissions and link settings of the SFTP server still matter. - To be backported to camel-4.22.x and camel-4.18.x, as CAMEL-25412 was. camel-4.18.x has no camel-ftp-common, so there the change goes into both `SftpConsumer` and `MinaSftpConsumer`. _Claude Code on behalf of oscerd_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
