The admin API key routes now require any pending password change or
two-factor enrollment to be completed first, like the other admin routes.
Reported-by: Yves Soete, Blacksight LLC <yves.soete@blacksight.io>
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
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>
A user or admin changing its own password, profile or two-factor
settings wrote the whole account back and could overwrite a concurrent
administrator change. Self-service updates are now conditional on the
stored updated_at matching the value read, and every update stores a
strictly increasing updated_at.
Thanks to Thomas Toth for the report.
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
HTTP builds a connection per request, so checkHTTPClientUser is where a
request is authorized, the way the credential check is for SFTP and FTP:
it evaluates the login conditions of the account together with the
denied protocols, the login method and the source address.
An account that is disabled, that reaches its expiration date or that
falls outside its access time restrictions is refused on the next
request. The check is redundant on the paths that already run it before
the call, and costs nothing: the account is in memory.
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
Answering with another account has never been a supported configuration for
these two integrations. Mapping several login names onto a single account is a
feature of the external authentication hook
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
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>
Downloading a public share limited to a single directory as a zip archive
rewrote share.Paths[0] to "/" so the entry names came out relative to that
directory. The value it overwrote is the policy every later public request is
authorized against: the browsable listing resolves the requested path under
Paths[0] and the upload handler derives its destination prefix from it.
The rewrite stays confined to the copy the handler holds only if the data
provider returns a share that owns its paths. The memory provider did not:
getACopy assigned the Paths slice by header, so the copy kept pointing at the
array stored in the provider map and the rewrite reached the stored share.
From that moment the link served the whole filesystem of the share owner. Any
recipient, with no account and nothing beyond the share URL, could list and
download every file the owner can reach, and a read-write share also accepted
uploads at the owner's root. The archive returned to the recipient who
triggered the change was still limited to the shared directory, so the
response revealed nothing. The SQL and bolt providers rebuild the slice while
decoding the stored row and were not affected.
The list of files to archive is now local to the handler, so the share is no
longer written to, and getACopy clones the paths, so a copy never shares state
with the provider.
The regression test downloads a share limited to one directory twice and
checks the archive, the stored paths, the browsable listing and a file outside
the share in between, with whichever data provider the test suite runs with.
Thanks to Yutaka Sasaki (@SAYUTIM) for the report.
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
An instance that starts with an empty admins table caches that state until
restart, so it keeps serving the setup page after another instance completes
the initial configuration. Instances backed by a shared SQL provider now
re-check the database, rate limited to one query per second and only until
the first admin is found
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>