README for VSCVS $Id: README,v 1.6 2003/12/30 19:10:28 chris Exp $ VSCVS allows the `pserver' CVS server facility to be run in relative safety using a chroot'd environment, under the control of an individual user. The vscvs proxy program listens on port 2401 (cvspserver), and examines incoming connections in order to identify the repository to which they refer, using a static table of repositories, by default in /etc/vcvstab. Each repository is contained in a tiny chroot-able filesystem, with the following structure: /path/to/vcvs /etc contain minimal system config files and the CVS /bin binary itself, as well as any libraries which are /lib required for them to run; /tmp is used for temporary files; /repos contains the CVS repository itself. /path/to/vcvs/repos is a symlink to ../../../repos .../tmp and .../repos are owned by the user who `owns' the whole repository. The other directories and their contents are owned by root, so that they cannot be altered by the unprivileged owner. The symlink exists so that the repository can be referred to as `/path/to/vcvs/repos' from within or without the chroot'd environment. The /etc/vcvstab would, for the above example, contain a line owner:/path/to/vcvs where owner is the username (from /etc/passwd) of the user who owns the repository. With the vscvs proxy running on port 2401 from inetd, a remote client could access the repository by setting her CVSROOT to :pserver:user@host:/path/to/vcvs/repos When this is done, cvs is invoked under the UID of owner, in the chroot, with the arguments `--allow-root /path/to/vcvs/repos pserver'. From this stage, access to the repository is as normal. Note that, since (by design) the CVS server always runs under the UID of owner, it is not possible to use normal Unix file permissions to restrict access to different parts of the repository. Broad access control restrictions can be applied by the use of the CVSROOT/readers mechanism, and additional login/password pairs may be created using the CVSROOT/passwd table, but all users will access the repository with the same permissions. Unfortunately, this restriction is rather hard to lift without either assigning additional UIDs to each Unix user (which, in these days of 32-bit UIDs, is not a serious problem of itself, but would lead to irritating nastiness about, for instance, quotas), or implementing ACLs within CVS itself. The approach taken here is to have a small program, vcvs_acltest, which is used to implement control of commit access via the CVSROOT/commitinfo mechanism. vcvs_new_repository sets everything up to make this work properly. Also in this distribution are: vcvs_new_repository Create a new `virtual' CVS repository, generating the directory structure described above. Usage is: vcvs_new_repository username location In order to work, this expects to find a tarball of the appropriate bin/cvs and lib/* to make the repository work. On a Red Hat Linux machine, I found that the following procedure worked; there may be minor changes for other distributions or Unix variants: 1. Obtain a recent source distribution of CVS, and build it using the configure options --prefix=/path/to/cvs-chroot --disable-client where /path/to/cvs-chroot is some path in which you will build CVS. Having done this, make install. You should do this and subsequent steps as root, or chown the various files to UID.GID 0.0 when done. 2. Within the chroot, delete: share/ info/ man/ bin/cvsbug bin/rcs2log 3. Now you need to figure out which shared libraries are required by CVS. Use ldd(1) on Linux, I find $ ldd cvs libcrypt.so.1 => /lib/libcrypt.so.1 (0x4001c000) libc.so.6 => /lib/libc.so.6 (0x40049000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) Copy these libraries to the lib/ directory within the chroot. You may also need libraries which are loaded by libc for (e.g.) NSS support. strace is a good way to identify these. Also create /dev/null and /dev/zero within the chroot. Also copy vcvs_acltest to bin/ in the chroot. 4. Now run ldconfig -r /path/to/cvs-chroot to make the etc/ld.so.cache file. 5. Now, within the /path/to/cvs-chroot, do tar cvzf /path/to/tarball . to make the tarball. Now, put this in some sensible place and change the definition of $tarball at the top of vcvs_new_repository to reflect its location. vcvs_passwd This is a simple interactive script for editing the contents of CVSROOT/passwd and CVSROOT/readers files. This is designed for use by the owner of a VCVS repository, to be used to set up user permissions within the repository. It is a convenient alternative to editing the files directly and does not provide any additional functionality. Usage is as follows: $ CVSROOT=/path/to/vcvs/repos cvs co CVSROOT $ cd CVSROOT $ vcvs_passwd . Username Password Real user Read-only ------------------- ----------- ------------------- --------- chris locked test2 no test2 locked test2 no vcvs_passwd> passwd chris Set password: fishsoup vcvs_passwd(modified)> add fred Generate password for user (y/n) y Set password: fioj21haox vcvs_passwd(modified)> commit Write changes to disk? (y/n) y Changes have been written to the working directory, but not committed to the repository. vcvs_passwd> list Username Password Real user Read-only ------------------- ----------- ------------------- --------- chris set test2 no fred set test2 no test2 locked test2 no vcvs_passwd> quit $ cvs commit [...] cvs commit: Rebuilding administrative file database Note that this script should be used only by the real owner of the repository; in the above example, the access is done using the :local: CVS mechanism; this is essential for a new repository as created by vcvs_new_repository, since the default repository setup does not contain a passwd file which grants access to any users. Also note that-- if you do not use this script-- CVS will not by default automatically regenerate the CVSROOT/passwd file from its version history CVSROOT/passwd,v; to enable this behaviour, you should add the line `passwd' to the bottom of CVSROOT/checkoutlist. If you do not do this, you will need to manually generate the CVSROOT/passwd file in the repository using (for instance) the RCS command co passwd. vcvs_acltest See the description in the committers file generated by vcvs_new_repository, and comments in vcvs_acltest.c.