126 Commits
Author SHA1 Message Date
Nicola Murino bca13cd448 vfs: skip listed names that address no entry
Listings leave out the entries naming the listed directory or its
parent, and the names holding a backslash, which no request can
address

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-09-28 20:11:13 +02:00
Nicola Murino 1cc81798ba update gopsutil to v4
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-09-27 09:19:14 +02:00
Nicola Murino 51104ed02f vfs: count what a failed recursive rename already moved
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-27 08:03:54 +02:00
Nicola Murino 48ccf188a0 say what a tolerated failure costs instead of calling it best effort
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-27 07:50:33 +02:00
Nicola Murino b5a2c1dd4f vfs: report the close error when copying a file across roots
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-27 07:42:51 +02:00
Nicola Murino 27d8298384 rename: check the entries of a renamed directory, or refuse the rename
A directory rename authorized the whole tree from a walk performed before the
move, so the file_patterns filters and the per-directory rename permissions
decided on the tree as the walk had read it rather than on the one the move
carried.

The walk no longer authorizes the move. A gate decides from the configuration
alone whether anything can tell the entries of the tree apart: a move that
changes which file_patterns filters govern the contents, or a per-directory
permission that restricts renaming defined at or below either tree. When
something can, the object stores check every entry at the moment they move it,
since they rename a directory by recursing into it, and the filesystems that
rename it in a single operation refuse it, because nothing enumerates what that
operation carries. The type of the source is read again immediately before the
move.

Granting rename_files and rename_dirs separately keeps the pre-move walk.

So renaming a folder into or out of a path where a different file_patterns
filter applies is now refused on the local filesystem, SFTP and HTTP, and
checked entry by entry on the object stores; the same holds for a per-directory
permission that restricts renaming inside either tree. Renames the walk used to
refuse fail with the same error as before. IsRenameAtomic is derived from the
same capability instead of matching the filesystem name.

Reported-by: Wade Sparks (@wsparks-vc)

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-26 23:21:19 +02:00
Nicola Murino d54965865e replace golangci-lint with staticcheck, errcheck and unparam
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-24 15:07:16 +02:00
Nicola Murino 9e670437d0 suppress lint warnings
we should consider to remove the gocyclo linter

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-12 22:34:25 +02:00
Nicola Murino 1497afd09c vfs: skip the listing entries that do not address an entry inside
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-12 22:29:03 +02:00
Nicola Murino 236a9c7c68 vfs: various os.Root improvements
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-03 22:43:59 +02:00
Nicola Murino 5baff82564 vfs: abort a pending Azure copy when the poll loop gives up
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-08-03 22:24:27 +02:00
Nicola Murino 6cce58233c virtual folders: add subpath support
A virtual folder mapping can now re-root the mount onto a sub-path of
the folder: the mount at the virtual path serves the folder starting
from the configured subpath, which stays invisible in the virtual tree.
The same folder can be mapped multiple times with distinct subpaths;
quota remains a property of the whole folder, so every mapping must use
the same limits.

Supported for local, encrypted, S3, GCS, Azure Blob and SFTP folders.

Fixes #2037

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-07-18 16:19:43 +02:00
Nicola Murino bafb7e7d6a modernize the codebase to current Go idioms
Apply the fixes suggested by the modernize analyzers enabled by
default in gopls v0.23: range over int, errors.AsType, min/max,
slices.Backward/Contains, maps.Copy, strings.Cut/CutPrefix/CutSuffix/
SplitSeq, fmt.Appendf, WaitGroup.Go and b.Loop in tests, new(expr)
instead of to.Ptr, removal of ineffective omitempty tags on nested
struct fields.

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-07-13 20:52:29 +02:00
Nicola Murino 661d77f47b vfs: migrate OsFs/CryptFs to os.Root and remove temp_path
Confine all local filesystem access to an os.Root, with path resoultion
enforced by the underlying OS.

Behavior changes an upgrading deployment may notice:

- temp_path is removed and ignored if still configured. Its purpose
  was to stage files (atomic uploads, scratch and streaming data)
  outside the user's storage and rename them into place, and that is
  fundamentally incompatible with the confinement: an os.Root cannot
  rename a file in from outside the root, so every staged upload would
  degrade to a full copy-then-delete even when temp_path is on the
  same filesystem, defeating the very atomicity the option existed to
  provide. It was not a great idea before this change either: a
  temp_path on a different device already turned the final rename into
  a silent full copy. Staged and scratch files (the atomic upload
  temporary, the CryptFs download pipe backing file) now live in the
  storage root itself, on the same filesystem as the data, so the
  final rename stays atomic.

- Cross-folder / cross-root renames are no longer atomic. A rename
  spanning the home and a local virtual folder, or two local folders,
  falls back to copy-then-delete: slower for large data even on the
  same device, and a midway failure can leave a partial tree at the
  destination. Symlinks and other non-regular entries inside a moved
  directory are skipped, not copied, and the rename still reports
  success. File mode bits are not preserved; regular files keep their
  modification time, directories do not.

- Absolute symlinks created outside SFTPGo, or by versions predating
  this change, are no longer traversable and Readlink rejects them with
  permission denied, even when the target is inside the root: os.Root
  refuses an absolute link target regardless of where it points.
  Symlinks created through SFTPGo are stored relative to the link
  directory and keep working.

- Execute-only home directories (e.g. mode 0111) are unusable:
  os.OpenRoot requires read permission, so every operation fails with
  permission denied until the directory is made readable, where
  previously only the listing failed. Since the root open is retried on
  demand, fixing the permissions (or creating a missing home
  externally) makes the same connection work again without
  reconnecting.

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-07-06 13:08:12 +02:00
Nicola Murino b163bab867 azure blob: include container in isSameResource check
Fixes #2254

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-06-29 15:03:31 +02:00
Nicola Murino bbf00e13f9 vfs: refactor Readlink
add new test cases. Most of this code is temporary and will be
removed once we'll switch to os.Root

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-06-27 17:18:03 +02:00
Nicola Murino a55bb5ac92 vfs: fix symlink failure introduced in previous commits
rewrite the checks so that they can handle short paths on Windows
and home dir over symlinks

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-06-27 10:47:58 +02:00
Nicola Murino b482551140 suppress a lint warning
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-06-21 11:15:41 +02:00
Nicola Murino bccb1eb9ce harden symlink checks and add more test cases
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-06-20 21:10:22 +02:00
Nicola Murino 1c93729b40 vfs: normalize cloud key prefix on save
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-06-11 18:45:34 +02:00
Nicola Murino 3205160b02 use hdkf from the sdblib
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-06-08 14:18:37 +02:00
Nicola Murino 02e312f39c fs: enforce a configurable minimum entropy for data-encryption secrets
The CryptFs passphrase and the S3 SSE-C key are used directly as
data-at-rest encryption key material, yet they were accepted with no
strength check, so an operator could protect encrypted data with a
trivially guessable secret.

Add common.secret_min_entropy (default 80): when one of these
secrets is submitted in plain text it must pass a minimum-entropy
check before it is encrypted and stored. The check runs on
plain-text input, so secrets that are already stored keep working even
if the threshold is later raised. The estimate is a heuristic used to
reject obviously weak input, not a measure of cryptographic strength:
always supply key material generated by a CSPRNG.

Thanks to Vishal Shukla (@shukla304) for the report.

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-05-18 19:46:19 +02:00
Nicola Murino dc3899baa1 s3: use 1000 as default page size for better ListObjectsV2 compatibility
Fixes #1951

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-03-15 08:37:19 +01:00
Nicola Murino 2f092d1289 fix: prevent path traversal via edge-level path normalization
Moved path sanitization (backslash conversion and path cleaning) to
the SFTP/FTP handlers before VFS routing and permission checks.

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-03-07 12:03:59 +01:00
Nicola Murino 2b4c1f32fd sftpfs: remove a premature optimization
this may also fix a potential race condition

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-02-15 11:54:45 +01:00
Nicola Murino fbbea4a1fa vfs: fix S3 range off-by-one and part timeouts
wait for all the goroutine before retruning from multipart uploads

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-02-07 20:39:54 +01:00
Nicola Murino e48954f05c update deps
replace deprecated WithCredentialsJSON with WithAuthCredentialsJSON.
This change explicitly enforces `option.ServiceAccount` as the
required credential type from JSON files

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2026-02-04 21:18:50 +01:00
Nicola Murino d42bbef16e refactor: minor improvements to ResolvePath
Make ResolvePath more robust by avoiding implicit reliance on path
normalization performed by external libraries such as pkg/sftp and
ftpserverlib

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-12-11 08:44:30 +01:00
Nicola Murino 90821ffc23 cloud backends: update part size limits
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-11-23 12:56:59 +01:00
Nicola Murino 9fa18c37f7 fix lint warning
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-11-19 19:29:04 +01:00
Nicola Murino 4230da8e7d s3: implement multipart downloads without using the S3 Manager
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-11-19 18:53:27 +01:00
Nicola Murino d2ee43585a remove x/crypto fork
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-09-21 14:21:47 +02:00
Nicola Murino 63366b0007 virtual folders: fix path placeholder check
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-08-17 12:42:37 +02:00
Nicola Murino bdd097b1c7 s3: use multipart uploads only when multiple parts are needed
Fixes #2016

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-07-11 18:45:30 +02:00
Nicola Murino ff5ea7cd40 S3: don't use manager for uploads
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-06-16 18:48:04 +02:00
Nicola Murino d05250923b Revert "GCS: allow a 10 seconds timeout for client creation"
This reverts commit b2e9935049.

Fixes #2000

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-06-10 20:17:35 +02:00
Nicola Murino 60af36813b gcs: improve error checking
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-05-23 19:56:21 +02:00
Nicola Murino 11d8fffd1b remove obsoletes build constraints
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-04-20 17:15:40 +02:00
Nicola Murino 2255c5f000 upgrade golangci-lint to v2
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-03-29 11:36:19 +01:00
Nicola Murino a71e53c8c8 GCS: properly check for googleapi.Error
Fixes #1936

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-03-23 11:37:21 +01:00
Nicola Murino 51a9cf79bc azure blob fs: ensure sas url are not nil before comparing
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-03-15 20:39:42 +01:00
Nicola Murino 0013e35b28 update deps
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-02-06 19:23:05 +01:00
Nicola Murino 24215dc734 remove check for cache key collisions
we use sha256 keys now

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-01-15 19:46:54 +01:00
Nicola Murino 04fa242f57 azblobfs: add support for Azure Identity
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-01-13 20:58:17 +01:00
Nicola Murino b2e9935049 GCS: allow a 10 seconds timeout for client creation
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2025-01-11 11:25:45 +01:00
Nicola Murino 9f873d1059 prefer strings.EqualFold to strings.strings.ToLower where possible
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2024-12-19 19:44:01 +01:00
Nicola Murino c56be285a5 replace fnv with sha256
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2024-12-14 14:42:43 +01:00
Nicola Murino 599ee5a58f EventManager: check file size for more events
Also add some defensive code

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2024-12-14 13:19:02 +01:00
Nicola Murino f8bdb84e8d s3: metadata is not currently supported
remove useless code, we'll add it again once we support metadata

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2024-12-01 17:32:15 +01:00
Nicola Murino 126cb1ee0d remove some useless hooks
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
2024-09-27 15:52:51 +02:00