If we have a look at the permissions in our repository, we’ll see that
every ,v file has permissions 444 (read-only for everyone), and all
directories have permissions 776 (that is, read-write for user &
group, and readable by anyone else). Those are reasonable permissions,
but they imply that all your CVS users belong to the same group as the
repository. To allow all trusted CVS users access to the repository, we
will create a cvsusers group. To do this, add cvsusers:x:4901:john,jack
to
/etc/group to create a cvsusers group, and add john and jack to it.
Note, 4901 is not special, it’s any number not already in use as a
group id or user id – I used it because it’s the default port for a CVS
pserver, which creates a nice link between the two. Now, we should to
change the group of all files in the repository to cvsusers (we only
need to change the group of the directories, but we may as well do it
for all files to be consistent).
john@bolsh:~$ find cvs/ -exec chgrp cvsusers {} ;
This
still leaves us with a sticky problem. The easiest way to see the
problem is with an example. John has a friend Jack that he’s decided to
trust to write to the repository. So Jack gets an account on John’s
machine, logs in, sets CVSROOT to point at the repository and checks
out the project to work away on it. After making some changes, he
checks them in. Let’s see what happens… Before Jack checks anything
in, the files in $CVSROOT/project look like this…
john@bolsh:~/cvs/project$ ls -l
total 16
-r–r–r– 1 john cvsusers 538 Dec 26 16:56 Makefile,v
-r–r–r– 1 jack cvsusers 709 Dec 27 21:47 logic.c,v
-r–r–r– 1 john cvsusers 606 Dec 28 16:55 logic.h,v
-r–r–r– 1 john cvsusers 541 Dec 26 16:56 main.c,v
Now Jack makes a change, and checks it in… jack@bolsh:~/project$ cvs update
cvs server: Updating .
M logic.h
jack@bolsh:~/project$ cvs commit -m “made a change”
cvs commit: Examining .
Checking in logic.h;
/home/john/cvs/project/logic.h,v <– logic.h
new revision: 1.3; previous revision: 1.2
done
jack@bolsh:~/project$
And let’s look at those permissions now… john@bolsh:~/cvs/project$ ls -l
total 16
-r–r–r– 1 john cvsusers 538 Dec 26 16:56 Makefile,v
-r–r–r– 1 jack cvsusers 709 Dec 27 21:47 logic.c,v
-r–r–r– 1 jack jack 737 Dec 28 17:23 logic.h,v
-r–r–r– 1 john cvsusers 541 Dec 26 16:56 main.c,v
john@bolsh:~/cvs/project$
But
we just changed the file to be john:cvsusers – so what’s going on?
Well, CVS is running as jack, and jack’s default group is jack. So when
jack commits his change, and cvs reconstructed the ,v file, naturally
the file’s ownership gets changed too. In this case, that’s fine -
every user can still read the file and the directory has the same
permissions. But what if Jack wants to add some files to a new
subdirectory? jack@bolsh:~/project$ cvs add subdir
? subdir/test
Directory
/home/john/cvs/project/subdir added to the repository
jack@bolsh:~/project$ cvs add subdir/test
cvs server: scheduling file `subdir/test’ for addition
cvs server: use ‘cvs commit’ to add this file permanently
jack@bolsh:~/project$ cvs commit -m “adding new file in subdir”
cvs commit: Examining .
cvs commit: Examining subdir
RCS file: /home/john/cvs/project/subdir/test,v
done
Checking in subdir/test;
/home/john/cvs/project/subdir/test,v <– test
initial revision: 1.1
done
jack@bolsh:~/project$
And now in the repository, we have… john@bolsh:~/cvs/project$ ls -l
total 20
-r–r–r– 1 john cvsusers 538 Dec 26 16:56
Makefile,v
-r–r–r– 1 jack cvsusers 709 Dec 27 21:47 logic.c,v
-r–r–r– 1 jack jack 737 Dec 28 17:23 logic.h,v
-r–r–r– 1 john cvsusers 541 Dec 26 16:56 main.c,v
drwxrwxr-x 2 jack jack 4096 Dec 28 17:29 subdir
As
expected, subdir is owned by the user jack, and the group jack. But
what does this mean? To see, let’s try and update John’s working copy
of the repository now. john@bolsh:~/project$ cvs update -d
cvs update: Updating .
U logic.c
U logic.h
cvs update: Updating subdir
cvs update: failed to create lock directory for `/home/john/cvs/project/subdir’
(/home/john/cvs/project/subdir/#cvs.lock): Permission denied
cvs update: failed to obtain dir lock in repository `/home/john/cvs/project/subdir’
cvs [update aborted]: read lock failed – giving up
Gah!
John no longer has even read-only access to the subdirectory. We can
fix that, but whatever happens he will definitely not have r/w access.
We need to ensure that anyone writing to the repository does so using
the cvsusers group. The way we do this is by setting the setgid bit on
the parent directories. This means that when someone “executes” the
directory (by changing directory into it), their group automatically
becomes the same as the parent directory. By running the command find $CVSROOT -type d -exec chmod g+s {} ;
we ensure that files get created as we want them. Let’s rewind a
little, and (after running the command above) add that subdir and file
again. john@bolsh:~/cvs/project$ ls -al
total 28
drwxrwsr-x 3 john cvsusers 4096 Dec 28 17:39 .
drwxrwsr-x 5 john cvsusers 4096 Dec 27 21:45 ..
-r–r–r– 1 john cvsusers 538 Dec 26 16:56 Makefile,v
-r–r–r– 1 jack cvsusers 709 Dec 27 21:47 logic.c,v
-r–r–r– 1 jack cvsusers 737 Dec 28 17:23 logic.h,v
-r–r–r– 1 john cvsusers 541 Dec 26 16:56 main.c,v
drwxrwsr-x 2 jack cvsusers 4096 Dec 28 17:39 subdir
Note
that the permissions on the repository root, on the project directory
(.. and . respectively), as well as on the newly created directory are
all g+s – a listing of subdir shows that all files and directories are
created with cvsusers as the group owners too.