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]

Reply via email to