Go to the first, previous, next, last section, table of contents.


@ifnottex

START-INFO-DIR-ENTRY
* CVS Admin Guide: (cvs-admin-guide).   CVS-Nserver Administrator's Guide
END-INFO-DIR-ENTRY

CVS-Nserver Administrator's Guide

Copyright (C) 2001 Alexey Mahotkin

Server-side user authentication

This chapter discusses the user authentication in CVS-Nserver.

What configuration exactly do you need?

There are several most popular ways to setup the repository access.

Authentication basics

CVS-Nserver software uses flexible authentication and authorization mechanism to control access to a repository. Password-checking programs which comply to certain "checkpassword" protocol are used for that purpose. There is a large variety of such programs available, starting from simple UNIX-based authentication, to PAM (Pluggable Authentication Modules) authentication, from Kerberos to SSL.

There are several programs participating in server-side authentication, each of them doing their own particular task, and passing control to each other. Ultimately, when the access is granted, CVS server executable itself comes into play, which talks with a CVS client using the CVS client/server protocol.

There are two primary types of server-side programs: protocol front-ends and password checking programs.

Protocol front-ends are used only for certain types of access methods (namely, for :pserver: and its counterparts). Their only goal is to read the username and password from the network, and pass this information to a password-checking program.

Password-checking programs read the username and password information from protocol front-ends. Then it checks validity of username and password using any database you can imagine. Finally, password-checking program switches the system username to some value taken from database or simply some explicitly specified name (when managing anonymous-only repositories).

General information about how to set up

CVS server requires some TCP listener, such as inetd, that would accept the network connection and run the appropriate programs. We will use inetd itself configuration when discussing the setup of CVS server, because inetd is the least common denominator among the UNIX systems. It is relatively straightforward to convert the configuration examples to some other TCP listener, such as xinetd.

It is highly recommended that you create wrapper shell-script for each type of access method that you need to provide on your server. The nature of CVS-Nserver configuration is such that the command lines tend to be very long (several short lines, usually), albeit logically constructed. Some inetd implementations pose an artificial limit on a command line length, so that you are forced to use the wrapper script.

We assume that you are creating the wrapper scripts in `/usr/local/bin' directory. We assume that your inetd configuration is in the `/etc/inetd.conf'. We assume that all the programs that are included in CVS-Nserver distribution are installed in `/usr/bin'. Other third-party tools, such as alternative checkpassword implementations, are installed in `/usr/local/bin'.

Using SSL in CVS-Nserver

SSL (Secure Sockets Layer) could be used to protect communications between client and server. There are two methods for doing that.

First method is wrapping the `:pserver:' protocol with some SSL tunnelling software, such as `stunnel' (see section `stunnel' -- SSL tunneling). See section Wrapping `:pserver:' with SSL. In this mode the username and password are still used, but unlike the ordinary `:pserver:', the communications are fully encrypted, and passwords do not travel over the network in clear text.

Second method (not yet implemented) is setting up proper SSL support. That is, every developer would get her SSL certificate, and the CVS client would present that certificate to a server. Server checks the certificate, and extracts the username from there. So, there are no passwords used in this scheme, and no `:pserver:' protocol. Of course, all communications are fully encrypted. Unfortunately, this method is not yet implemented.

How the server-side programs communicate

This chapter describes the theory behind CVS-Nserver architecture. You may safely skip this section on first reading, and read it only after you've seen actual examples of particular protocols in the following sections.

Basic information about :pserver: protocol

:pserver: protocol first appeared as the authentication extension to the client-server protocol, and is now one of the most popular ways to setup the CVS server. However, there are several deficiencies in the :pserver: that make it extremely unsecure if used carelessly. Primary source of insecurety is that passwords are translated in clear text over the (untrusted) network, allowing the attacker to sniff the passwords.

:pserver: protocol by default uses~TCP port 2401.

It must be said, however, that :pserver: could be wrapped in SSL (Secure Sockets Layer), thus eliminating this danger and bringing the :pserver: back to usability. Plain unprotected :pserver: should be used only in fully trusted networks, or for unimportant tasks such as anonymous access to repository.

The whole purpose of :pserver: is to transfer from the client to the remote server three things: username, password, and directory where repository resides.

The protocol front-end for :pserver: is called `cvs-pserver'. It takes the following command line arguments:

cvs-pserver /repos1 ... /reposN -- checkpassword ...

Here the /repos1 ... /reposN is the list of repositories that are served by that particular server. End of this list is marked with --. If the client specifies repository not in that list, authentication fails, and no checkpassword program is run. After the end of list marker follows the name of password-checking program, with its own arguments.

:pserver: with system authentication

One of the simplest ways to setup the :pserver:-based repository is with system authentication. The checkpassword password-checking program is used for that purpose.

checkpassword checks the supplied username and password against the UNIX system users database (looking into `/etc/passwd', or into `/etc/shadow'). If the password is correct, it switches the user id to the provided username, and executes the CVS server binary itself. Thus, the CVS server runs as the individual system user, with all the appropriate priviliges granted.

:pserver: with PAM authentication

PAM (Pluggable Authentication Modules) is the convenient and flexible method of managing authentication methods used by particular programs. You can change the way an application handles authentication simply editing an appropriate configuration file: no recompilation is ever needed. You can add entirely new methods of authentication simply adding new PAM-module.

There is a special version of `checkpassword', called `checkpassword-pam'. It takes the following arguments:

checkpassword-pam service-name cvs-binary-with-args

The service-name argument specifies the "service" that is used for authentication purposes. Shortly, service name is the name of the file in `/etc/pam.d/' directory which contains the list of PAM modules consulted for authentication.

Most often, while setting up the CVS server, you will use the `cvspserver' as the service name; that is, the appropriate PAM-file will be called `/etc/pam.d/cvspserver'.

The `checkpassword-pam' calls the PAM library, asking it whether the username and password are valid. If it is, the `checkpassword-pam' changes user id to that of the provided username.

:pserver: with virtual repositories

Virtual repositories: overview

A special password-checking program called `vchkpw' allows to use the so-called virtual repositories.

There is a separate database of virtual users in each virtual repository, and the authentication is done against that particular database. Each virtual user has a corresponding system user to switch to. In most cases almost all virtual users for a given repository switch to the same single system user. One of the virtual users is designated to a repository administrator, and this user needs to switch to its own system user, with additional privileges. Thus, only two system users are allocated to each repository, while allowing an unlimited number of virtual users.

Additional advantage of virtual repositories is that they could be completely administrated over the network, not bothering the administrator of server machine. The remote administration is handled by the cvs client, and consists in adding, enabling, disabling, and deleting users, and changing user information, including password. Ordinary users can change their own password, not bothering the repository administrator.

The user database for the virtual repository is stored in the `cvspasswd' file in the `CVSROOT/' subdirectory of the repository. The `cvschkpw' program uses that file to authenticate virtual users and to switch to the system account specified for each virtual users (most of the time almost all users switch to the same account). section Setting up server.

Setting up system accounts for virtual repository

First you need to create system accounts that would own your repository. It is not discussed here exactly how to do that, because the methods vary from system to system. Only the suggested names and purpose of those accounts is discussed. You will need the following groups and accounts:

`cvsadmin' account
This account will own the repository directory itself, and the `CVSROOT/' subdirectory. This account has the `cvsadmin' group as its primary group, and additionally belongs to the `cvs' group.
`cvsadmin' group
This group will own the `CVSROOT/' subdirectory in the repository, and all of its contents.
`cvs' account
This account owns two files: `CVSROOT/history' and `CVSROOT/val-tags', and also all subdirectories except for the `CVSROOT/' (and files in them) will belong to this account. This account has the `cvs' group as its primary group.
`cvs' group
This group will own the repository directory itself, every subdirectory except for the `CVSROOT/', and all the files in those subdirectories. No system accounts that belong to real users should ever be in the `cvs' group. Only the `cvsadmin' and `cvs' accounts should be in this group.

Note that the two accounts and two groups mentioned above are used for a single repository. If you're hosting several virtual repositories on a single machine, you will have to create two accounts and two groups for each of those repositories. Suppose you have a repository in `/repos1'. Create, for example, `repos1cvs' and `repos1admin' accounts and groups, for this repository. Later on we will use generic `cvs' and `cvsadmin' names.

Setting up filesystem permissions in virtual repository

Now it's time to create the virtual repository. The permissions on various parts of repository should be set up very carefully, so there is a special script for that purpose, called `init-cvs-repository.sh'.

It takes the following command-line arguments:

  init-cvs-repository.sh [-v] /path/to/repository [cvs cvsadmin]

The only required argument is the `/path/to/repository', which specifies the path to the repository to be created. This directory must not exist prior to its creation: this is done to protect the already-setup directory from occasional breaking the permissions apart.

The script executes certain sequence of simple commands: mostly `chmod', `chown', and `touch'. The `cvs init' is executed also. If you want to see which commands exactly are executed by `init-cvs-repository.sh', add the `-v' (verbose) option.

The script uses two distinct names for the ordinary CVS user and CVS administrator. Each of those names specify both the account and the group. The default names are `cvs' and `cvsadmin'. You can specify another names as command line arguments. For example, this command line:

  init-cvs-repository.sh /repos1 repos1user repos1admin

creates the repository in the `/repos1' directory, with account and group both called `repos1user', and with account and group both called `repos1admin'.

Setting up server

You now have to setup the wrapper script that would handle the virtual users' access to the repository. Here is its sample contents:

#! /bin/sh
CVSPASSWD=/usr/bin/cvspasswd \
exec /usr/bin/cvs-pserver /repos1 -- \
/usr/bin/cvschkpw /usr/bin/cvs pserver

The `CVSPASSWD=/usr/bin/cvspasswd' part means that the `/usr/bin/cvspasswd' program would be used to let ordinary users change their passwords (using newer CVS clients) (see section Changing passwords in virtual repository). In a rare event when you don't want or don't need to let your users change their passwords, simply remove that line.

The `/usr/bin/cvs-pserver' is the protocol wrapper for the `:pserver:' protocol. It takes a list of repositories being served: here there is only a single repository, `/repos1', and the end-of-list marker, `--'.

Next line specifies the appropriate checkpassword-style program to use, that is, `/usr/bin/cvschkpw'. This program uses the `CVSROOT/cvspasswd' file for authentication, and switches to the system user specified there.

Finally, after the `cvschkpw' successfully authenticated user, it executes the CVS binary itself: `/usr/bin/cvs pserver'.

Suppose that wrapper script mentioned above is written to the `repos1-pserver.sh' file in the `/usr/local/bin/' directory. Make this file executable with `chmod +x', and edit the `/etc/inetd.conf' (or appropriate configuration file, if you are using the `inetd' replacement). You should add a line to this file, unless it already exists:

cvspserver  stream  tcp  nowait root /usr/local/bin/repos1-pserver cvs

After that, make your `inetd' to re-read its configuration file. Now, the `inetd' will listen on port specified by the `cvspserver' service (port 2401 by default), and run the wrapper script, when new connections arrive.

Changing passwords in virtual repository

Ordinary users of virtual repository should be allowed to change their own passwords. Of course, the `cvspasswd' file is protected by the filesystem permissions, so a special program, `cvspasswd' is used for that purpose.

Users could change their password with help of the CVS-Nserver client, using the `cvs passwd -p' command. The client will ask them for their current password, and for new password, with confirmation. After that the client will contact the server and ask it to change the password.

If the @env{CVSPASSWD} environment variable is set, the program specified by this variable is executed, and the old and new password is passwd to it via stdin. `cvspasswd' program should be installed setuid `root'. FIXME: fix the `cvspasswd', and fix it here.

Note that if for some reason you do not want to allow your users to change their passwords, don't specify the @env{CVSPASSWD} environment variable in the wrapper script (see section Setting up server).

Wrapping `:pserver:' with SSL

There is an open-source SSL tunneling software, called `stunnel' (see section `stunnel' -- SSL tunneling). It could be used to wrap the `:pserver:' communications with SSL, so that sensitive information like passwords and files' contents would go over the network in encrypted form.

You may use the `stunnel' together with any `checkpassword'-style program, be it ordinary UNIX authentication, PAM, or virtual repositories.

For example only, suppose that we are protecting the `:pserver:' with UNIX authentication, that is, using the `checkpassword' program.

By default the SSL-tunneled `:pserver:' uses port 22401.

You should arrange your system startup scripts so that `stunnel' daemon would start up automatically every time the machine reboots. Suppose, the startup script is called `/etc/init.d/cvs-stunnel', and contains the following:

#! /bin/sh
/usr/local/bin/stunnel -d 22401 -l /usr/bin/cvs-pserver --
cvs-pserver /repos --
/usr/local/bin/checkpassword /usr/bin/cvs pserver


Go to the first, previous, next, last section, table of contents.