See How do I install CVS? for information on installing CVS.

The CVS Update button is a bit of a hack.

There are two cases:

  1. The CVS Update button is in a workgroup, in which case we operate as the cvs user.
  2. The CVS Update button is on the main page, like it is for Chess and Trust, in which case we operate as the www user.
When we are operating in a workgroup, php/include/cvs.inc.php3 gets called, which calls the php popen() function and runs /home/www/bin/cvs-cvs

The permissions are:

andrews.EECS.Berkeley.EDU 2# ls -l ~www/bin
total 1369
---s--s--x   1 cvs        613708 Nov 21  2007 cvs-cvs
---s--s--x   1 cvs        146912 Mar 24  2012 cvs-svn
drwx------   2 root          512 Nov 21  2007 old
---s--s--x   1 www        613708 Nov 21  2007 www-cvs
andrews.EECS.Berkeley.EDU 3# 

Formerly, /home/www/bin/cvs-cvs was actually located in /usr/slocal because /home/www is mounted nosuid for security reasons.

gigascale:root: %C2> /bin/ls -l /usr/slocal/www/bin/cvs-cvs
---s--s--x   1 cvs      cvs      2960800 Mar 28 15:36 /usr/slocal/www/bin/cvs-cvs

As of 2012, we are not mounting the filesystem nosuid, so we use the files in ~www/bin

cvs-cvs is the same as /usr/local/bin/cvs, except the permissions are changed. It was created with something like:

cp /usr/local/bin/cvs /usr/slocal/www/bin/cvs-cvs
chown cvs /usr/slocal/www/bin/cvs-cvs
chgrp cvs /usr/slocal/www/bin/cvs-cvs
chmod u+s /usr/slocal/www/bin/cvs-cvs
chmod g+s /usr/slocal/www/bin/cvs-cvs
chmod ugo-r /usr/slocal/www/bin/cvs-cvs
chmod ugo-2 /usr/slocal/www/bin/cvs-cvs                                         

When we are updating the main page, we use

andrews.EECS.Berkeley.EDU 5# ls -l ~www/bin/www-cvs
---s--s--x   1 www        613708 Nov 21  2007 /home/www/bin/www-cvs

The cvs account on source is first set up to allow the the cvs account on moog to connect.

  1. Become root on source, then do:
    su - cvs
    # Move the .ssh directory out of the way
    mv .ssh .ssh_bak2
    # The ssh-keygen command will create ~cvs/.ssh with 0700 modes
    ssh-keygen -t rsa
    # Save the file in the default location and use an empty passphrase
    ssh-keygen -t dsa
    # Save the file in the default location and use an empty passphrase
    cd ~cvs/.ssh
    cat id_rsa.pub id_dsa.pub > authorized_keys2
    
  2. Become root on moog, and do
    su - cvs
    # Move the current .ssh directory out of the way
    mv .ssh .ssh_bak2
    mkdir .ssh
    chmod 0700 .ssh
    cd ~cvs/.ssh
    # I'm not sure why it is necessary to copy id_rsa and id_dsa
    # I don't think we use to have to do it?
    scp gigasource:~cvs/.ssh/{id_rsa,id_rsa.pub,id_dsa,id_dsa.pub,authorized_keys2} ~cvs/.ssh
    
  3. As cvs on moog, verify that you can connect using ssh from moog to source without typing the cvs password:
    ssh -v source cvs --version
    

Then the source cvs account is set up to allow apache on moog to connect.

  1. As root on moog: ~cvs/.ssh is copied to ~apache/.ssh
    cd ~apache
    mv .ssh .ssh_bak2
    cp -r ~cvs/.ssh .
    chown -R apache .ssh
    
  2. /home/apache/.profile should be owned by the apache user and contain
    CVS_RSH=ssh
    export CVS_RSH
    
    and have permissions
    andrews.EECS.Berkeley.EDU 6# ls -l ~apache/.profile
    -rwxr-xr-x   1 apache        181 Feb 28  2008 /home/apache/.profile
    
  3. This step is no longer required (10/2012)
    On gigasource: ~cvs/.shosts contains:
    gigascale.eecs.berkeley.edu
    gigascale.eecs.berkeley.edu apache
    
  4. On moog, become apache and try to use ssh
    [root@moog trustwww]# su - apache
    -bash-4.1$ ssh -v -l cvs source cvs --version
    OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010
    debug1: Reading configuration data /etc/ssh/ssh_config
    debug1: Applying options for *
    debug1: Connecting to source [128.32.48.234] port 22.
    debug1: Connection established.
    debug1: identity file /var/www/.ssh/identity type -1
    debug1: identity file /var/www/.ssh/id_rsa type 1
    debug1: identity file /var/www/.ssh/id_dsa type -1
    debug1: Remote protocol version 2.0, remote software version Sun_SSH_1.1.4
    debug1: no match: Sun_SSH_1.1.4
    debug1: Enabling compatibility mode for protocol 2.0
    debug1: Local version string SSH-2.0-OpenSSH_5.3
    debug1: SSH2_MSG_KEXINIT sent
    debug1: SSH2_MSG_KEXINIT received
    debug1: kex: server->client aes128-ctr hmac-md5 none
    debug1: kex: client->server aes128-ctr hmac-md5 none
    debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
    debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
    debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
    debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
    debug1: Host 'source' is known and matches the RSA host key.
    debug1: Found key in /var/www/.ssh/known_hosts:1
    debug1: ssh_rsa_verify: signature correct
    ebug1: SSH2_MSG_NEWKEYS sent
    debug1: expecting SSH2_MSG_NEWKEYS
    debug1: SSH2_MSG_NEWKEYS received
    debug1: SSH2_MSG_SERVICE_REQUEST sent
    debug1: SSH2_MSG_SERVICE_ACCEPT received
    debug1: Authentications that can continue: gssapi-keyex,gssapi-with-mic,publickey,password,keyboard-interactive
    debug1: Next authentication method: gssapi-keyex
    debug1: No valid Key exchange context
    debug1: Next authentication method: gssapi-with-mic
    debug1: Unspecified GSS failure.  Minor code may provide more information
    Credentials cache file '/tmp/krb5cc_48' not found
    
    debug1: Unspecified GSS failure.  Minor code may provide more information
    Credentials cache file '/tmp/krb5cc_48' not found
    
    debug1: Unspecified GSS failure.  Minor code may provide more information
    
    
    debug1: Unspecified GSS failure.  Minor code may provide more information
    
    
    debug1: Next authentication method: publickey
    debug1: Trying private key: /var/www/.ssh/identity
    debug1: Offering public key: /var/www/.ssh/id_rsa
    debug1: Server accepts key: pkalg ssh-rsa blen 149
    debug1: read PEM private key done: type RSA
    debug1: Authentication succeeded (publickey).
    debug1: channel 0: new [client-session]
    debug1: Entering interactive session.
    debug1: Sending environment.
    debug1: Sending env LANG = en_US.UTF-8
    debug1: Sending command: cvs --version
    debug1: Remote: Channel 0 set: LANG=en_US.UTF-8
    debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
    debug1: channel 0: forcing write
    
    Concurrent Versions System (CVS) 1.11.22 (client/server)
    
    Copyright (C) 2006 Free Software Foundation, Inc.
    
    Senior active maintainers include Larry Jones, Derek R. Price,
    and Mark D. Baushke.  Please see the AUTHORS and README files from the CVS
    distribution kit for a complete list of contributors and copyrights.
    
    CVS may be copied only under the terms of the GNU General Public License,
    a copy of which can be found with the CVS distribution kit.
    
    Specify the --help option for further information about CVS
    debug1: channel 0: free: client-session, nchannels 1
    Transferred: sent 1856, received 2160 bytes, in 0.1 seconds
    Bytes per second: sent 23947.2, received 27869.6
    debug1: Exit status 0
    -bash-4.1$ 
    
    
  5. Repeat the test, using the full name for source.eecs.berkeley.edu. This might be necessary to manually confirm for moog the authenticity of ource.eecs.berkeley.edu's SSH key.
    -bash-4.1$ whoami
    apache
    -bash-4.1$ ssh -l cvs source cvs --version
    
    Concurrent Versions System (CVS) 1.11.22 (client/server)
    
    Copyright (C) 2006 Free Software Foundation, Inc.
    
    Senior active maintainers include Larry Jones, Derek R. Price,
    and Mark D. Baushke.  Please see the AUTHORS and README files from the CVS
    distribution kit for a complete list of contributors and copyrights.
    
    CVS may be copied only under the terms of the GNU General Public License,
    a copy of which can be found with the CVS distribution kit.
    
    Specify the --help option for further information about CVS
    -bash-4.1$ 
    
    
  6. Then, test cvs update as the apache user on moog
    $ cd /home/www/cvswww/chess.eecs.berkeley.edu/ptolemy
    $ /home/www/bin/cvs-cvs -t update -d
    cvs-cvs update: notice: main loop with CVSROOT=:ext:cvs@gigasource:/home/cvs
     -> Starting server: ssh gigasource -l cvs cvs server
     -> rename(CVS/Entries.Backup,CVS/Entries)
     -> unlink(CVS/Entries.Log)
     -> rename(CVS/Entries.Backup,CVS/Entries)
     -> unlink(CVS/Entries.Log)
    ? src
    ? nightly/ptolemy
    ? nightly/com
    ? nightly/coverage.html
    ? reviews/ptolemy/actor/gui/20001002-design
     -> unlink(CVS/Entries.Static)
     -> unlink(CVS/Entries.Static)
    cvs server: Updating .
    S-> unlink(CVS/Entries.Static)
    S-> unlink(./CVS/Entries.Static)
    S-> rename(CVS/Entries.Backup,CVS/Entries)
    S-> unlink(CVS/Entries.Log)
     -> unlink(CVS/Entries.Static)
    cvs server: Updating group
    S-> unlink(group/CVS/Entries.Static)
    S-> rename(CVS/Entries.Backup,CVS/Entries)
    S-> unlink(CVS/Entries.Log)
     -> unlink(CVS/Entries.Static)
    cvs server: Updating group/library
    S-> unlink(library/CVS/Entries.Static)
    Killed by signal 2.
    cvs-cvs [update aborted]: received interrupt signal
    $
    
    

Note that we need to change all the CVS/Root files in ~www/cvswww to contain :ext:cvs@gigasource:/home/cvs

Documented Problems & Remedies:

Cannot exec /usr/local/bin/ssh While updating the TRUST main page on moog:
Updating module trustwww:
     www-cvs update: cannot open /root/.cvsignore: Permission denied
     www-cvs [update aborted]: cannot exec /usr/local/bin/ssh: No such file or directory
     www-cvs [update aborted]: end of file from server (consult above messages if any)
Done!
The issue here is that ~www/trust.eecs.berkeley.edu/config.php contains:
/**                                           
 * Full pathname of the ssh program.              
 */
$siteConfig['sshExecutable'] = '/usr/local/bin/ssh';
// $siteConfig['sshExecutable'] = '/usr/bin/ssh';      
One solution is to create a link.

You have no controlling tty messages

If, when you press the "CVS Update" button, you get:
Updating module ptolemy:
  You have no controlling tty. Cannot read passphrase. 
  cvs-cvs [update aborted]: end of file from server (consult above messages if any) 
                      Done!
then the problem is that cvs is requesting a password.

Things to check

  1. As root on gigasource, su - cvs and then ssh to gigasource. You should not be prompted for a password.
    su - cvs
    ssh -v gigasource date
    
    If you are prompted for a password, check the ssh output for clues
  2. As cvs on gigasource, try the v1 protocol:
    ssh -1 -v gigasource date
    

Aborted by user!

If you see something like
Updating module hils:
     Aborted by user!
     cvs-cvs [update aborted]: end of file from server (consult above
messages if any)
Done!
then the problem is probably that the CVS/Root file does not contain the right thing. It should contain:
:ext:cvs@gigasource:/home/cvs
Not
:ext:gigasource.eecs.berkeley.edu:/home/cvs
Try the steps above to track down the problem

Problems Checking out a Group Can be a Permissions Issue

Here is the error received:

$ cvs -d :ext:username@gigasource.eecs.berkeley.edu:/home/cvs co groupname
username@gigasource.eecs.berkeley.edu's password:
Permission denied, please try again.
username@gigasource.eecs.berkeley.edu's password:
cvs server: Updating groupname
cvs server: failed to create lock directory for `/home/cvs/groupname'
(/home/cvs/groupname
/#cvs.lock): Permission denied
cvs server: failed to obtain dir lock in repository `/home/cvs/groupname'
cvs [server aborted]: read lock failed - giving up

This is likely a group permission problem. To fix the problem:

gigasource:root: %C2> cd /home/cvs
gigasource:root: %C2> ls -ldg groupname
drwxr-xr-x 2 cvs cvs 512 Jun 4 16:24 groupname
gigasource:root: %C2> ls -ldg infrax
drwxrwsr-x 9 cvs cvs 512 Mar 20 11:36 infrax
gigasource:root: %C2> chmod g+ws groupname
gigasource:root: %C2> ls -ldg groupname
drwxrwsr-x 2 cvs cvs 512 Jun 4 16:24 groupname
gigasource:root: %C2>

cvs [server aborted]: can't getwd in /home/cvsusers: Permission denied

This is not a cvs update button question, but instead a cvs user problem.

This problem occurred only for users who have /home/cvsusers as their home directory on gigascale. The way to reproduce this is:

cxh@maury 50% cvs -t -d :ext:ptolemy@gigasource.eecs.berkeley.edu:/home/cvs co 
ptII
cvs checkout: notice: main loop with CVSROOT=:ext:ptolemy@gigasource.eecs.berke
ley.edu:/home/cvs
 -> Starting server: ssh gigasource.eecs.berkeley.edu -l ptolemy cvs server
ptolemy@gigasource.eecs.berkeley.edu's password:

Warning: Remote host denied X11 forwarding, perhaps xauth program could not be 
run on the server side.^M
S-> do_module (ptII, Updating, , )
S-> do_module (ptII, Updating, , )
cvs [server aborted]: can't getwd in /home/cvsusers: Permission denied
S-> fopen(/home/cvs/CVSROOT/history,a)
cxh@maury 51% Warning: Remote host denied X11 forwarding, perhaps xauth program
 could not be run on the server side.^M
S-> fopen(/home/cvs/CVSROOT/history,a)
Logging in to gigasource as cxh and cding to /home/cvsusers/.ssh:

gigasource.eecs 45# cd /home/cvsusers/.ssh
gigasource.eecs 46# ls
#environment#  environment    environment~   rc             rc~
gigasource.eecs 47# pwd
pwd: cannot determine current directory!

gigasource.eecs 62# cd /home/cvsusers  
gigasource.eecs 63# pwd
pwd: cannot determine current directory!
The solution was to make sure that /usr/slocal was readable by everyone:
gigasource:root: %C2> ls -ldg slocal
drwx--x--x   5 root     other         512 Mar 26 17:55 slocal
gigasource:root: %C2> chmod a+r slocal

Permission denied

Updating module ptolemy:
Permission denied, please try again. 
Permission denied, please try again. 
Permission denied (publickey,password,keyboard-interactive,hostbased). 
cvs-cvs [update aborted]: end of file from server (consult above messages if any) 
Done!
The problem here was that /export/home/cvs was group writable, which I fixed:
gigasource:cvs: %C2> ls -ldg /export/home/cvs
drwxrwxr-x  62 cvs      cvs          1536 Dec 18 14:47 /export/home/cvs
gigasource:cvs: %C2> chmod g-w /export/home/cvs
gigasource:cvs: %C2> ls -ldg /export/home/cvs                                 
drwxr-xr-x  62 cvs      cvs          1536 Dec 18 14:47 /export/home/cvs
gigasource:cvs: %C2>
Running ssh -1 -v gigasource date indicated what the problem was:
gigasource:cvs: %C2> ssh -1 -v gigasource date
OpenSSH_3.0.2p1, SSH protocols 1.5/2.0, OpenSSL 0x0090600f
...
debug1: Remote: Authentication refused: bad ownership or modes for directory /export/home/cvs
Another way to check this is to run the sshd daemon in debug mode on a different port and look at the output. In trying to track down why running ssh -l www date as apache did not work, I wrote:
As root on markov, I did
  sshd -p 666 -d
which runs sshd on port 666 in debug mode

And as apache, I did:

ssh -v -l www -p 666 markov
In the sshd window, the following message popped up:
Authentication refused: bad ownership or modes for directory /home/www

Looking at the perms:

markov:root: %C2> ls -ldg /home/cvs /home/www
drwxr-sr-x   7 cvs      cvs           512 Jan 14 12:16 /home/cvs
drwxrwxr-x  35 www      webmastr     1024 Jan 14 11:31 /home/www
If we change /home/www to be not group writable, then as apache
  ssh -l www markov date
works.

Now, I'm not sure if I just caused problems elsewhere by making /home/www not group writable.

cvs update on chess has messages about www@cooley

The last few lines of cvs update on chesswww, on gigascale:
cvs update: Updating resources
cvs update: Updating resources/badges
cvs update: Updating seminars
cvs update: Updating workshop
www@cooley.eecs.berkeley.edu's password:
Permission denied, please try again.
The problem here was that the www account on cooley had been accidentally removed.
  1. Update /etc/auto_home on doppler to point to the right directory
  2. Make the right directory. As root on messier, I did
    cd /export/home1
    mkdir www
    chown www www
    mkdir www/.ssh
    chown www www/.ssh
    chmod 700 www/.ssh
    
  3. As root on gigascale copy over apache's key
    cd ~apache/.ssh
    scp id_dsa.pub messier:/export/home1/www/.ssh/authorized_key
    
  4. As root on gigascale, test with
    su - apache
    ssh -v -l www messier date
    

Also, try running www-cvs in the ~www/chesswww/eecs20 directory as the apache user. Sometimes it is necessary to do this because the host key on the machine that serves the eecs20 pages has changed


Below here is obsolete

Below are my notes about trying to get the cvs button working after moving the cvs repository from an NFS mounted partition to a location on a different machine that is not available by NFS (we use ssh) instead.

cvs-cvs can be a setuid root ! custom cvs binary that sets its uid and gid to the cvs uid and gid. See http://www.loria.fr/~molli/fom-serve/cache/91.html

 Setuid to root is not a great idea.  Any program that modifies
        files and is used by a widely distributed group of users is not a
        good candidate for a setuid program.  (The worst suggestion I've
        ever heard was to make *Emacs* setuid to root.)


        Root access on Unix is too powerful.  Also, it might not work in
        some (secure?) environments.


        Running it setuid to some user other than root might work, if you
        add this line to main.c near the beginning:


                setuid(geteuid());


        Otherwise it uses *your* access rights, rather than the effective
        uid's.


        Also, you have to invent a fake user whose name will show up in
        various places.  But many sites, especially those who might want a
        setuid CVS for "security", want personal accountability -- no
        generic accounts.  I don't know whether accountability outweighs
        file security.


        And finally, unless you take action to limit the "admin"
        command, you are leaving yourself unprotected anyway.

The problem here is that cvs-cvs is initially run as the apache user. We would like to have a separate user run cvs update for security reasons.

One would think that making the cvs-cvs binary setuid/setgid cvs would be sufficient, but if we do that, then only the effective uid and gid are set, but the real uid and gid are still set to be the apache uid and gid:

---s--s--x   1 root     root      573456 Mar 28 15:01 /usr/slocal/www/bin/cvs-c
vs
gigascale:root: %C2> su - apache
      Use of cluster of workstations is governed by the
      UC Computer Use Policy, see:
      http://socrates.berkeley.edu:7015/policy/usepolicy.htm


$ CVS_RSH=ssh
$ export CVS_RSH
$ cd /export/home/www/cvswww/ptolemy
$ /usr/slocal/www/bin/cvs-cvs -t -n update
gsrc custom hack setuid(geteuid()) called.
### Note that getuid() returns 14264, which is the cvs uid
 getuid(): 14264 geteuid(): 14264 getgid(): 416 getegid(): 416
 current working directory is /export/home/www/cvswww/ptolemy
cvs-cvs update: notice: main loop with CVSROOT=:ext:gigasource:/home/cvs
 -> Starting server: ssh gigasource cvs server
? src
? find
? nightly/ptolemy
? nightly/com
? nightly/coverage.html
? reviews/ptolemy/actor/gui/20001002-design
cvs server: Updating reviews/template
cvs server: Updating sysadmin
cvs-cvs update: notice: main loop with CVSROOT=:ext:cvs@gigasource:/home/cvs
 -> Starting server: ssh gigasource -l cvs cvs server
cvs-cvs [update aborted]: received interrupt signal
$ exit
gigascale:root: %C2> chown cvs.cvs /usr/slocal/www/bin/cvs-cvs
gigascale:root: %C2> su - apache
      Use of cluster of workstations is governed by the
      UC Computer Use Policy, see:
      http://socrates.berkeley.edu:7015/policy/usepolicy.htm

$ CVS_RSH=ssh
$ export CVS_RSH
$ cd /export/home/www/cvswww/ptolemy
$ /usr/slocal/www/bin/cvs-cvs -t -n update
gsrc custom hack setuid(geteuid()) called.
### Note that getuid() returns 1003, which is the uid of apache
 getuid(): 1003 geteuid(): 14264 getgid(): 105 getegid(): 416
 current working directory is /export/home/www/cvswww/ptolemy
cvs-cvs update: notice: main loop with CVSROOT=:ext:gigasource:/home/cvs
 -> Starting server: ssh gigasource cvs server
apache@gigasource's password: cvs-cvs [update aborted]: received interrupt sign
al
$ exit
One potential workaround is to use change the CVS/Root entries to use :ext:cvs@gigasource.eecs.berkeley.edu:/home/cvs, but the problem is that the real userid is still that of apache, so the ssh fails?
Updating module ptolemy:
gsrc custom hack setuid(geteuid()) called. 
getuid(): 1003 geteuid(): 14264 getgid(): 105 getegid(): 416 
current working directory is /export/home/www/cvswww/ptolemy 
cvs-cvs update: notice: main loop with CVSROOT=:ext:cvs@gigasource.eecs.berkeley.edu:/home/cvs 
 -> Starting server: ssh gigasource.eecs.berkeley.edu -l cvs cvs server 
  Aborted by user! 
cvs-cvs [update aborted]: end of file from server (consult above messages if any) 
Done!
The problem here was that the cvs account on gigasource was not set up to handle the fully qualified domainname? Changing :ext:cvs@gigasource.eecs.berkeley.edu:/home/cvs to :ext:cvs@gigasource:/home/cvs seems to have helped

The hack was to modify main.c in the cvs sources:

#define CVS_USER_UID 14264
#define CVS_GID 416
    
    setgid(CVS_GID);
    setuid(CVS_USER_UID);

    fprintf(stderr, "gsrc custom hack setuid(geteuid()) called.n");
    fprintf(stderr, " getuid(): %d geteuid(): %d getgid(): %d getegid(): %dn",
      getuid(), geteuid(), getgid(), getegid());

    getwd(wd);
    fprintf(stderr, " current working directory is %sn", wd);