This is a kind of puzzle and I don't know if this will help or not but here goes.
My CVS repository is in
/usr/local/cvsroot and the CVS authorized user group is
cvsusers.
Code:
pita-trona-/usr/local: ls -al
total 88
drwxr-xr-x 19 root root 4096 2010-01-26 11:52 ./
drwxr-xr-x 19 root root 4096 2010-06-17 23:29 ../
drwxr-xr-x 2 root root 4096 2010-01-26 11:52 bin/
drwxrwxr-x 10 root cvsusers 4096 2009-12-17 15:20 cvsroot/
drwxr-xr-x 3 root root 4096 2010-01-26 16:23 doc/
drwxr-xr-x 2 root root 4096 2010-01-13 09:45 etc/
drwxr-xr-x 2 root root 4096 1993-11-24 12:32 games/
drwxr-xr-x 5 root root 4096 2010-01-26 11:52 include/
drwxr-xr-x 2 root root 4096 2010-01-13 09:45 info/
drwxr-xr-x 3 root root 4096 2010-01-13 09:45 lib/
drwxr-xr-x 3 root root 4096 2010-01-26 11:52 lib64/
drwx------ 2 root root 16384 2010-01-13 12:06 lost+found/
drwxr-xr-x 22 root root 4096 2010-01-26 11:52 man/
drwxr-xr-x 3 root root 4096 2010-01-13 09:45 multilib/
drwxr-xr-x 3 root root 4096 2010-06-08 15:02 packages/
drwxr-xr-x 2 root root 4096 2010-06-19 07:06 patches/
drwxr-xr-x 2 root root 4096 2010-01-13 09:45 sbin/
drwxr-xr-x 9 root root 4096 2010-01-26 11:52 share/
drwxr-xr-x 2 root root 4096 2010-05-21 12:37 src/
That is,
root owns the directory and
cvsusers is the group and the mode is 775.
Then,
Code:
cd cvsroot
pita-trona-/usr/local/cvsroot: ls -al
total 40
drwxrwxr-x 10 root cvsusers 4096 2009-12-17 15:20 ./
drwxr-xr-x 19 root root 4096 2010-01-26 11:52 ../
drwxrwxr-x 3 root cvsusers 4096 2010-06-22 11:35 CVSROOT/
drwxr-xr-x 3 trona users 4096 2009-10-07 14:13 county/
drwxr-xr-x 3 trona users 4096 2010-06-19 09:44 general/
drwxrwxr-x 3 trona users 4096 2010-06-19 08:11 gnis/
drwxr-xr-x 3 trona users 4096 2009-10-07 14:14 nhpn/
drwxrwxr-x 5 trona users 4096 2010-06-20 06:46 recipes/
drwxrwxr-x 9 trona users 4096 2010-06-04 07:20 topics/
drwxrwxr-x 3 trona users 4096 2010-06-19 09:44 utils/
"I" own all the source code directories, with group
users and CVSROOT is owner
root, group
cvsusers and mode 775.
Code:
cd CVSROOT
pita-trona-/usr/local/cvsroot/CVSROOT: ls -al
total 152
drwxrwxr-x 3 root cvsusers 4096 2010-06-22 11:35 ./
-rw-rw-r-- 1 root root 495 2009-10-07 13:49 .#checkoutlist
-rw-rw-r-- 1 root root 760 2009-10-07 13:49 .#commitinfo
-rw-rw-r-- 1 root root 1302 2009-10-07 13:49 .#config
-rw-rw-r-- 1 root root 602 2009-10-07 13:49 .#cvswrappers
-rw-rw-r-- 1 root root 1025 2009-10-07 13:49 .#editinfo
-rw-rw-r-- 1 root root 1141 2009-10-07 13:49 .#loginfo
-rw-rw-r-- 1 root root 1087 2009-10-07 13:49 .#modules
-rw-rw-r-- 1 root root 564 2009-10-07 13:49 .#notify
-rw-rw-r-- 1 root root 649 2009-10-07 13:49 .#rcsinfo
-rw-rw-r-- 1 root root 879 2009-10-07 13:49 .#taginfo
-rw-rw-r-- 1 root root 1026 2009-10-07 13:49 .#verifymsg
drwxrwxr-x 10 root cvsusers 4096 2009-12-17 15:20 ../
drwxrwxr-x 2 root root 4096 2009-10-07 13:49 Emptydir/
-r--r--r-- 1 root root 495 2009-10-07 13:49 checkoutlist
-r--r--r-- 1 root root 696 2009-10-07 13:49 checkoutlist,v
-r--r--r-- 1 root root 760 2009-10-07 13:49 commitinfo
-r--r--r-- 1 root root 961 2009-10-07 13:49 commitinfo,v
-r--r--r-- 1 root root 1302 2009-10-07 13:49 config
-r--r--r-- 1 root root 1503 2009-10-07 13:49 config,v
-r--r--r-- 1 root root 602 2009-10-07 13:49 cvswrappers
-r--r--r-- 1 root root 803 2009-10-07 13:49 cvswrappers,v
-r--r--r-- 1 root root 1025 2009-10-07 13:49 editinfo
-r--r--r-- 1 root root 1226 2009-10-07 13:49 editinfo,v
-rw-rw-rw- 1 root root 3482 2010-06-22 11:35 history
-r--r--r-- 1 root root 1141 2009-10-07 13:49 loginfo
-r--r--r-- 1 root root 1342 2009-10-07 13:49 loginfo,v
-r--r--r-- 1 root root 1087 2009-10-07 13:49 modules
-r--r--r-- 1 root root 1288 2009-10-07 13:49 modules,v
-r--r--r-- 1 root root 564 2009-10-07 13:49 notify
-r--r--r-- 1 root root 765 2009-10-07 13:49 notify,v
-rw-r--r-- 1 root root 62 2010-06-19 08:11 passwd
-r--r--r-- 1 root root 649 2009-10-07 13:49 rcsinfo
-r--r--r-- 1 root root 850 2009-10-07 13:49 rcsinfo,v
-r--r--r-- 1 root root 879 2009-10-07 13:49 taginfo
-r--r--r-- 1 root root 1080 2009-10-07 13:49 taginfo,v
-rw-rw-rw- 1 root root 0 2009-10-07 13:49 val-tags
-r--r--r-- 1 root root 1026 2009-10-07 13:49 verifymsg
-r--r--r-- 1 root root 1227 2009-10-07 13:49 verifymsg,v
And the only things in there that may be odd are
history and
val-tags with mode 666.
The only thing I may be using that you may not is use the
pserver access method (thus the
passwd file in
/usr/local/cvsroot/CVSROOT)? Here's a part of a setting up CVS blurb I've written about setting up
pserver you may want to try.
Look in
/etc/services; there ought to be two lines that look like this:
Code:
grep -h cvsps /etc/services
cvspserver 2401/tcp #CVS network server
cvspserver 2401/udp #CVS network server
If they're not there or they are and they're commented (with a leading #), use an editor and add or uncomment both of them, if they look like the above, you're good to go.
Now we need to get the server started, that's done in
/etc/inetd.conf and, most likely, the following will not be there and you need to add it.
First check and see if an entry for
cvspserver exists:
Code:
grep -h cvsps /etc/inetd.conf
If it is not there, do the following:
Code:
vi /etc/inetd.conf
jump to the end of the file and add the following two lines; adjust path names for your system
# CVS services
cvspserver stream tcp nowait root /usr/bin/cvs cvs -f --allow-root=/usr/local/cvsroot pserver
Then you need to restart
inetd, you can reboot or you can
Code:
ps -ef | grep inetd
this gives you the PID of inetd then
kill -HUP <pid of inetd>
Now we should be good to go... except for individual user settings. Well, nothings that easy.
Each of your authorized users needs to add this in their ~/.profile, ~/.bashrc or ~/.login file (can't do this one system-wide).
Code:
export CVSROOT=:pserver:USERID@SEVER.DOMAIN:/usr/local/cvsroot
where "USERID" is the, you know, individual user's login, "SERVER" and "DOMAIN" you'll find in
/etc/HOSTNAME.
When a user does this, they need to log off and log back on again for it to be present in their environment; have them check with
I strongly recommend that you enable CVS passwords (which will be more secure and as a bonus make your life easier for your authorized users).
Doing this requires that you create an encrypted password, either one for each authorized CVS user (hard way, not for the faint of heart) or one for all CVS users (easy, practical way).
There's the quick-and-dirty easy way and there's the hard way. The method described does the job with the
passwd utility and a no-login CVS account. You can accomplish much the same with an encrypted password generator (I'll be happy to forward source code for that), but it's just much simpler to use existing system utilities wherever possible so try this first.
Quick and Easy: Create a password for all CVS users.
Create a new user account. What the heck, why not make the account name
cvs, with the
adduser utility:
Code:
fgrep cvs /etc/group to get the group id -- GID -- number use it below for the userid number
useradd -u GID -c CVS -g cvs -s /bin/false cvs use the GID number, not "GID!"
passwd cvs to generate an encrypted password
enter it
enter it again
What you've done is create a no-login account,
cvs, that's more a less just a place-holder and you've generated an encrypted password for that account (it's in
/etc/shadow) that you're going to use for your authorized CVS users.
Now, get yourself a list of the authorized CVS user account names (their logins). Let's say that bill, frank and steve are the authorized CVS users. You need to create a
passwd file in
/usr/local/cvsroot/CVSROOT.
First we need to see the actual password created above:
Code:
grep -h cvs /etc/shadow
cvs:$1$sQu0Fkv5$y7GE7dmzTiUpf/eexSkmP.:14781:0:99999:7:::
It's
$1$sQu0Fkv5$y7GE7dmzTiUpf/eexSkmP. (everything between the first and second colons).
And, um, your system will not produce the same encrypted password as shown, eh?
So, let's doit toit (you could fiddle with AWK, SED, and who knows what-all but manual works just fine too):
Code:
cd /usr/local/cvsroot/CVSROOT get into the right directory
grep cvs /etc/shadow > passwd create the passwd file containing the encrypted password
vi passwd
move the cursor to the second colon, delete the rest of the line you should have this left
cvs:$1$sQu0Fkv5$y7GE7dmzTiUpf/eexSkmP.
copy/paste that line for as many authorized users you have then back up and change every "cvs" to the individual user logins.
You'll wind up with something like this
Code:
bill:$1$sQu0Fkv5$y7GE7dmzTiUpf/eexSkmP.
frank:$1$sQu0Fkv5$y7GE7dmzTiUpf/eexSkmP.
steve:$1$sQu0Fkv5$y7GE7dmzTiUpf/eexSkmP.
Save that and quit.
Now, bill, frank and steve have the same CVS password (this has nothing whatsoever to do with their account login, it's only used for CVS).
Every authorized CVS user must do the following in their home directory:
Code:
touch .cvspass
chmod 600 .cvspass
cvs login
password: enter the CVS password
Once complete, the authorized CVS users will not need to login again until the CVS password is changed (you do change passwords every so often, right?). Then they'll just execute
cvs login with the new password and they'll be good to go until the next password change. They only need to do the "touch" once (that creates the file).
Hard Way: Use the authorized CVS user's own system passwords.
If you want your users to be able to use their own system passwords for CVS access, well, that's OK but... if passwords are changed periodically (as they should be), you'll have to arrange for that to happen in CVS and that starts to get complicated. Or you'll have to repeat much of the above every time somebody lets you know that their CVS password failed.
The essential problem you have to deal with is that there is no mechanism to directly change a password in
/usr/local/cvsroot/CVSROOT/passwd (nope, can't do that with any utility I know of). So you'd have to create a cron job (or something) that detects a time-stamp change in
/etc/shadow then grabs all your authorized user's password entries in
/etc/shadow and just rebuild
/usr/local/cvsroot/CVSROOT/passwd using those entries.
Not too practical, huh? You'd need to fiddle with cron, grep, awk, sed, and who knows what all. Might be a fun project if you're a glutton for punishment (I'm not). If you want to do this, have at it (and let me know how hard it was, eh?).
The above is the way I've done this on large and small systems -- there may be other ways to accomplish the tasks above and I'm not proud and would be happy to know of any easier way to do this. It's worked for me for over 20 years and I do not find a terrible burden to simply use
vi and change what I need to manually.
I've found CVS to be safe, reliable and easy to use for large-scale software development and maintenance; I hope you will too.
Hope this helps some.