blob: b39139e5bd7d67da4de790d705060e0f7731e747 [file] [log] [blame]
-*- text -*-
This file documents what users should expect from path-based authz,
and the responsibilities of the implementor of said feature.
============================================================================
WHAT USERS SHOULD EXPECT FROM PATH-BASED AUTHZ
============================================================================
1. CHECKOUTS
Unreadable paths will not be downloaded into a working copy.
However, 'svn update' may cause working paths to disappear or
re-appear based on changing server authorization policies.
(Note: the .svn/entries file may still leak the name of the
unreadable path; see the 'Known Leakage' section below.)
2. LOG MESSAGES
Log information may be restricted, based on readability of
changed-paths.
* If the target of 'svn log' wanders into unreadable territory,
then log output will simply stop at the last readable revision.
If the log is tracing backwards through time, as the plain
"svn log" command does, the target will appear to be added
(without history) in that revision.
* If a revision returned by 'svn log' contains a mixture of
readable/unreadable changed-paths, then the log message is
suppressed, along with the unreadable changed-paths. Only the
revision number, author, date, and readable paths are
displayed.
* If a revision returned by 'svn log' contains only unreadable
changed-paths, then only the revision number is displayed.
It's an official recommendation ("best practice") to avoid the
"mixed" changed-path situation; users should avoid making a single
commit that includes changes to files in both readable and
unreadable areas. This scenario is quite annoying for people who
can't read all the changed-paths.
3. COPIES (BRANCHING AND TAGGING)
Subversion does O(1) copies of entire trees, but unfortunately,
this isn't completely compatible with path-based access control.
In order to copy an entire tree, every path in the tree must be
checked for readability: this is an O(N) operation.
Depending on the specific path-based authz module being used,
however, there are sometimes solutions that aren't quite so
expensive as O(N).
4. TRACING PATH CHANGES
If a Subversion 1.1 client attempts to fetch an older version of a
file or directory, e.g.:
svn cat -r5 foo.c
svn diff -r10:28 bar.c
...then there is a potential for failure, should older versions of
the file exist at unreadable paths. In other words, the tracing of
copies/renames is subject to readability checks.
If history-tracing wanders into unreadable territory, the process
halts; no further information is retrieved.
Example 1: while 'bar.c' might be perfectly readable in both
revisions 10 and 28, the 'svn diff' command (above) will return
error if the file has an unreadable ancestor somewhere between
those two revisions.
Example 2: 'svn blame bar.c' will not be able to retrieve
unauthorized versions of a file, or any ancestors that precede
it. So it will appear that 'bar.c' was wholly added -- without
history -- in the first public version *after* the unreadable
version.
So again, an official recommendation ("best practice") is to avoid
renaming or copying files between public and private areas. For
users without omnipotent read permissions, this will make renames
difficult to follow, and client commands which attempt to trace
history are likely to fail.
5. REVISION PROPERTIES
Users are allowed to attach arbitrary, unversioned properties to
revisions. Additionally, most revisions also have "standard"
revision props (revprops), such as svn:author, svn:date, and
svn:log. Access to revprops may be restricted, based on
readability of changed-paths.
* If a revision contains nothing but unreadable changed-paths,
then all revprops are unreadable and unwritable.
* If a revision has a mixture of readable/unreadable
changed-paths, then all revprops are unreadable, except for
svn:author and svn:date. All revprops are unwritable.
It's an official recommendation ("best practice") to avoid the
latter situation; users should avoid making a single commit that
includes changes to files in both readable and unreadable areas.
This situation is quite annoying for people who can't read all the
changed-paths.
Notice that for the purposes of gating read and write access to
revision properties, Subversion never considers the user's *write*
access to the changed-paths. To understand the reason behind this,
it helps to understand why revprop access is gated at all.
Subversion assumes that revprops for a given revision -- especially
the log message (svn:log) property -- are likely to reveal paths
modified in that revision. It is precisely because Subversion
tries not to reveal unreadable paths to users that revprop access
is limited as described above. So as long as the user has the
requisite read access to the changed-paths, it's okay if he or she
lacks write access to one or more of those paths when attempting to
set or change revprops -- the information Subversion is trying to
protect through its revprop access control is considered safe to
reveal to that user.
6. KNOWN LEAKAGE OF UNREADABLE PATHS
Subversion may (occasionally) leak knowledge of the existence of an
unreadable path. However, the *contents* of an unreadable file or
directory will never be leaked.
Here are the known times when this happens:
* 'svn ls directory-URL': an unreadable directory entry is still
listed along with other entries.
* 'svn checkout/update': an unreadable child doesn't appear in
the working copy, but the .svn/entries file still contains an
entry for it (marked 'absent').
7. LOCKING
If a client attempts to lock or unlock an unreadable path, the
command will fail. If a client attempts to retrieve a lock on one
path, or a list of all locks "below" a directory, only readable
paths will ever be returned; unreadable locked paths remain
unknown.
============================================================================
HOW TO IMPLEMENT PATH-BASED AUTHZ
============================================================================
If an RA server implementation wants to implement path-based authz,
here are its responsibilities:
1. Implement a read-authz callback (see svn_repos_authz_read_func_t),
and pass it to the following svn_repos.h functions:
svn_repos_begin_report()
svn_repos_dir_delta()
svn_repos_history2()
svn_repos_get_logs3()
svn_repos_trace_node_locations()
svn_repos_get_file_revs()
svn_repos_fs_get_locks()
svn_repos_fs_change_rev_prop2()
svn_repos_fs_revision_prop()
svn_repos_fs_revision_proplist()
svn_repos_get_commit_editor3()
svn_repos_replay2()
2. Manually implement authz for incoming network requests that
represent calls to:
RA->get_file()
RA->get_dir()
RA->check_path()
RA->stat()
RA->lock()
RA->lock_many()
RA->unlock()
RA->unlock_many()
RA->get_lock()
(These concepts aren't wrapped by libsvn_repos because it's just
as easy to call an authz func directly on a single path, rather
than pass it to a repos wrapper.)
3. Manually implement authz when receiving network requests that
represent calls to a commit editor:
- do write checks for most editor operations
- do read *and* write checks for copy operations.
(Note that doing full-out authz on whole trees fundamentally
contradicts Subversion's O(1) copy philosophy; in practice,
however, specific authz implementations are able to get the same
effect while being less expensive than O(N).)