Remote repositories

Your working copy of the sources can be on a different machine than the repository. Using cvsnt in this manner is known as client/server operation. You run cvsnt on a machine which can mount your working directory, known as the client, and tell it to communicate to a machine which can mount the repository, known as the server. Generally, using a remote repository is just like using a local one, except that the format of the repository name is:

:method[;keywords...]:[[user][:password]@]hostname[:[port]][:]/path/to/repository

Specifying a password in the repository name is not recommended during checkout, since this will cause cvsnt to store a cleartext copy of the password in each created directory. cvs login first instead (the section called “Using the client with password authentication”).

With most protocols the username is optional. Your current login name will be used in this case. Also, a special username of '.' (dot) can be used, and means the same as not specifying a username. This can be used for frontends built for older cvs versions which required a username to be specified.

The details of exactly what needs to be set up depend on how you are connecting to the server.

If method is not specified, and the repository name contains :, then the default is ext or server, depending on your platform; both are described in the section called “Connecting with ssh”.

Server requirements

The quick answer to what sort of machine is suitable as a server is that requirements are modest--a server with 32M of memory or even less can handle a fairly large source tree with a fair amount of activity.

The real answer, of course, is more complicated. Estimating the known areas of large memory consumption should be sufficient to estimate memory requirements. There are two such areas documented here; other memory consumption should be small by comparison (if you find that is not the case, let us know, as described in Appendix G, Dealing with bugs in CVS or this manual, so we can update this documentation).

The first area of big memory consumption is large checkouts, when using the cvsnt server. The server consists of two processes for each client that it is serving. Memory consumption on the child process should remain fairly small. Memory consumption on the parent process, particularly if the network connection to the client is slow, can be expected to grow to slightly more than the size of the sources in a single directory, or two megabytes, whichever is larger.

Multiplying the size of each cvsnt server by the number of servers which you expect to have active at one time should give an idea of memory requirements for the server. For the most part, the memory consumed by the parent process probably can be swap space rather than physical memory.

The second area of large memory consumption is diff, when checking in large files. This is required even for binary files. The rule of thumb is to allow about ten times the size of the largest file you will want to check in, although five times may be adequate. For example, if you want to check in a file which is 10 megabytes, you should have 100 megabytes of memory on the machine doing the checkin (the server machine for client/server, or the machine running cvsnt for non-client/server). This can be swap space rather than physical memory. Because the memory is only required briefly, there is no particular need to allow memory for more than one such checkin at a time.

Resource consumption for the client is even more modest--any machine with enough capacity to run the operating system in question should have little trouble.

For information on disk space requirements, see the section called “Creating a repository”.

Connecting with ssh

cvsnt uses the ssh protocol to perform these operations, so the remote user host needs to have a .rhosts file which grants access to the local user.

For example, suppose you are the user mozart on the local machine toe.example.com, and the server machine is faun.example.org. On faun, put the following line into the file .rhosts in bach's home directory:

toe.example.com  mozart

Then test that ssh is working with

ssh -l bach faun.example.org 'echo $PATH'

On some versions of cvsnt :ssh: protocol is available. This is a builtin ssh client which integrates cvs authentication with ssh security.

At its simplest, this is used like :pserver:, as in:

cvs -d :ssh:user@machine.example.org:/usr/local/cvs login
Password: *****
cvs -d :ssh:user@machine.example.org:/usr/local/cvs co myproject

However you can also register your private key with cvs, which it will use instead of a password:

cvs -d :ssh;key='c:\user.ppk':user@machine.example.org:/usr/local/cvs login
Password: ******** (if your key has no passphrase, just press enter here)
cvs -d :ssh:user@machine.example.org:/usr/local/cvs co myproject

The keys should be in the putty private key format. You can use PuttyGen to convert an existing Openssh private key to this format.

:ext: specifies an external ssh program. By default this is ssh but you may specify another program in the CVSROOT using the optional :ext:{program} command. You may alternatively set the CVS_EXT environment variable to invoke another program which can access the remote server (for example, remsh on HP-UX 9 because rsh is something different). It must be a program which can transmit data to and from the server without modifying it

Continuing our example, supposing you want to access the module foo in the repository /usr/local/cvsroot/, on machine faun.example.org, you are ready to go:

cvs -d :ext:bach@faun.example.org/usr/local/cvsroot checkout foo

(The bach@ can be omitted if the username is the same on both the local and remote hosts.)

Using 3rd party clients via the extnt wrapper

(Windows only at present) The extnt.exe program is a wrapper client which allows 3rd-party clients to use CVSNT protocols to access a CVSNT server. It uses the :ext: protocol on the client so should be compatible with all existing clients.

The program takes a number of optional parameters, which may or may not be defined by the client. A standard cvs client will only usually pass the -l (username) option.

-l username

Username to use.

-p protocol

protocol to use. Default comes from the protocol= line in extnt.ini. If that is absent uses sspi.

-d directory

repository directory. Default comes from the directory= line in extnt.ini

-P password

Password to use. Default comes from the password= line in extnt.ini

Unless all parameters are passed on the command line by the client, you need to setup extnt.ini with the correct details. This file is laid out as a standard windows .ini file, with the section name based on the hostname to connect to.

[cvs.myserver.org]
protocol=sspi
directory=/cvs

You can define multiple connections to the same host by using the hostname= entry, eg:

[cvs-1]
protocol=sspi
directory=/cvs-repo-1
hostname=cvs.myserver.org

[cvs-2]
protocol=sspi
directory=/cvs-repo-2
hostname=cvs.myserver.org

Configuring the client to call extnt.exe as its :ext: application is client specific.

Direct connection with password authentication

The cvsnt client can also connect to the server using a password protocol. This is particularly useful if using ssh is not feasible (for example, the server is behind a firewall), and Kerberos also is not available.

To use this method, it is necessary to make some adjustments on both the server and client sides.

Setting up the server for Authentication

First of all, you probably want to tighten the permissions on the $CVSROOT and $CVSROOT/CVSROOT directories. See the section called “Security considerations with password authentication”, for more details.

On Windows Server (2003, 2008, 2012 etc.), on the server side, you must run the cvsmanager.exe program which calls the cvs.exe when required. Setup is done using the cvsnt server control panel. the rest of this chapter is mostly Unix related.

On Unix, on the server side, the file /etc/cvsnt/PServer, /etc/cvsnt/Plugins, and /etc/cvsnt/server need to be edited so cvsmanager knows the location of your repositories and other parameters (eg: connection port etc.).

Older versions of CVSNT used /etc/inetd.conf or /etc/xinetd.conf for this purpose - these are no longer used with CVSNT 2.8 and later.

By default, the port number is for pserver is 2401 it would be different for pserver if your client were compiled with CVS_AUTH_PORT defined to something else, though. This can also be sepcified in the CVSROOT variable (the section called “Remote repositories”) or overridden with the CVS_CLIENT_PORT environment variable (Appendix C, All environment variables which affect CVS), or, on Windows Server, set in the cvsnt server control panel.

You can use the /etc/cvsnt/PServer file to specify a temporary directory, or, on Windows Server set this within the cvsnt server control panel.

If you are having trouble setting this up, see the section called “Trouble making a connection to a CVS server”.

CVS passwd file

Because the client stores and transmits passwords in cleartext (almost--see the section called “Security considerations with password authentication”, for details), a separate cvsnt password file is generally used, so people don't compromise their regular passwords when they access the repository. This file is $CVSROOT/CVSROOT/passwd (the section called “The administrative files”). It uses a colon-separated format, similar to /etc/passwd on Unix systems, except that it has fewer fields: cvsnt username, optional password, and an optional system username for cvsnt to run as if authentication succeeds. Here is an example passwd file with five entries:

anonymous:
bach:ULtgRLXo7NRxs
spwang:1sOp854gDF3DY
melissa:tGX1fS8sun6rY:pubcvs
qproj:XR4EZcEs0szik:pubcvs

(The passwords are encrypted according to the standard Unix crypt() function, so it is possible to paste in passwords directly from regular Unix /etc/passwd files.)

The first line in the example will grant access to any cvsnt client attempting to authenticate as user anonymous, no matter what password they use, including an empty password. (This is typical for sites granting anonymous read-only access; for information on how to do the "read-only" part, see the section called “Read-only repository access”.)

The second and third lines will grant access to bach and spwang if they supply their respective plaintext passwords.

The fourth line will grant access to melissa, if she supplies the correct password, but her cvsnt operations will actually run on the server side under the system user pubcvs. Thus, there need not be any system user named melissa, but there must be one named pubcvs.

The fifth line shows that system user identities can be shared: any client who successfully authenticates as qproj will actually run as pubcvs, just as melissa does. That way you could create a single, shared system user for each project in your repository, and give each developer their own line in the $CVSROOT/CVSROOT/passwd file. The cvsnt username on each line would be different, but the system username would be the same. The reason to have different cvsnt usernames is that cvsnt will log their actions under those names: when melissa commits a change to a project, the checkin is recorded in the project's history under the name melissa, not pubcvs. And the reason to have them share a system username is so that you can arrange permissions in the relevant area of the repository such that only that account has write-permission there.

If the system-user field is present, all password-authenticated cvsnt commands run as that user; if no system user is specified, cvsnt simply takes the cvsnt username as the system username and runs commands as that user. In either case, if there is no such user on the system, then the cvsnt operation will fail (regardless of whether the client supplied a valid password).

The password and system-user fields can both be omitted (and if the system-user field is omitted, then also omit the colon that would have separated it from the encrypted password). For example, this would be a valid $CVSROOT/CVSROOT/passwd file:

anonymous::pubcvs
fish:rKa5jzULzmhOo:kfogel
sussman:1sOp854gDF3DY

When the password field is omitted or empty, then the client's authentication attempt will succeed with any password, including the empty string. However, the colon after the cvsnt username is always necessary, even if the password is empty.

cvsnt can also fall back to use system authentication. When authenticating a password, the server first checks for the user in the $CVSROOT/CVSROOT/passwd file. If it finds the user, it will use that entry for authentication as described above. But if it does not find the user, or if the cvsnt passwd file does not exist, then the server can try to authenticate the username and password using the operating system's user-lookup routines (this "fallback" behavior can be disabled by setting SystemAuth=no in the cvsnt config file, the section called “The CVSROOT/config configuration file”). Be aware, however, that falling back to system authentication might be a security risk: cvsnt operations would then be authenticated with that user's regular login password, and the p assword flies across the network in plaintext. See the section called “Security considerations with password authentication” for more on this.

You can setup the passwd file by logging in to cvs using another method (local, sserver, gserver, ssh, sspi) and using the cvsnt passwd command to add new users.

Using the client with password authentication

To run a cvsnt command on a remote repository via the password-authenticating server, one specifies the protocol, optional username, repository host, an optional port number, and path to the repository. For example:

cvs -d :pserver:faun.example.org:/usr/local/cvsroot checkout someproj

cvs -d :sserver:faun.example.org:/usr/local/cvsroot checkout someproj

cvs -d :sspi:faun.example.org:/usr/local/cvsroot checkout someproj

With certain protcols, unless you're connecting to a public-access repository (i.e., one where that username doesn't require a password), you'll need to supply a password or log in first. Logging in verifies your password with the repository and stores it in a file. It's done with the login command, which will prompt you interactively for the password if you didn't supply one as part of $CVSROOT:

cvs -d :pserver:bach@faun.example.org:/usr/local/cvsroot login
CVS password:

or

cvs -d :pserver:bach:p4ss30rd@faun.example.org:/usr/local/cvsroot login

After you enter the password, cvsnt verifies it with the server. If the verification succeeds, then that combination of username, host, repository, and password is permanently recorded, so future transactions with that repository won't require you to run cvs login. (If verification fails, cvsnt will exit complaining that the password was incorrect, and nothing will be recorded.)

The records are stored, by default, in the file $HOME/.cvspass (Unix) or the Registry (Windows). The format human-readable, and to a degree human-editable, but note that the passwords are not stored in cleartext--they are trivially encoded to protect them from "innocent" compromise (i.e., inadvertent viewing by a system administrator or other non-malicious person).

Once you have logged in, all cvsnt commands using that remote repository and username will authenticate with the stored password. So, for example

cvs -d :pserver:bach@faun.example.org:/usr/local/cvsroot checkout foo

should just work (unless the password changes on the server side, in which case you'll have to re-run cvs login).

Note that if the :pserver: were not present in the repository specification, cvsnt would assume it should use ssh to connect with the server instead (the section called “Connecting with ssh”).

Of course, once you have a working copy checked out and are running cvsnt commands from within it, there is no longer any need to specify the repository explicitly, because cvsnt can deduce the repository from the working copy's CVS subdirectory.

The password for a given remote repository can be removed from the password cache by using the cvs logout command.

Security considerations with password authentication

With pserver and sserver, the passwords are stored on the client side in a trivial encoding of the cleartext and in the pserver case transmitted in the same encoding. The encoding is done only to prevent inadvertent password compromises (i.e., a system administrator accidentally looking at the file), and will not prevent even a naive attacker from gaining the password.

With sserver, the client/server connection is encrypted using SSL, and the risk of the password being sniffed 'on the wire' is very low.

With sspi, if cvsnt login is used to gain access to a remote server, the passwords are stored on the client side in the same manner as pserver. However the passwords are never transmitted insecurely over the internet.

With pserver and sserver, the separate cvsnt password file (the section called “Setting up the server for Authentication”) allows people to use a different password for repository access than for login access. With other protocols the system passwords are used and the password field in the passwd file is ignored.

Once a user has non-read-only access to the repository, she can execute programs on the server system through a variety of means. Thus, repository access implies fairly broad system access as well. It might be possible to modify cvsnt to prevent that, but no one has done so as of this writing.

Note that because the $CVSROOT/CVSROOT directory contains passwd and other files which are used to check security, you must control the permissions on this directory as tightly as the permissions on /etc. The same applies to the $CVSROOT directory itself and any directory above it in the tree. Anyone who has write access to such a directory will have the ability to become any user on the system. Note that these permissions are typically tighter than you would use if you are not using pserver.

In summary, with a password server anyone who gets the password gets repository access (which may imply some measure of general system access as well).

With pserver, the password is available to anyone who can sniff network packets or read a protected (i.e., user read-only) file. Other protocols do not have this problem.

Direct connection with GSSAPI

GSSAPI is a generic interface to network security systems such as Kerberos 5. If you have a working GSSAPI library, you can have cvsnt connect via a direct tcp connection, authenticating with GSSAPI.

To do this, cvsnt needs to be compiled with GSSAPI support; when configuring cvsnt it tries to detect whether GSSAPI libraries using kerberos version 5 are present. You can also use the -with-gssapi flag to configure.

The connection is authenticated using GSSAPI, but the message stream is not authenticated by default. You must use the -a global option to request stream authentication.

The data transmitted is not encrypted by default. Encryption support must be compiled into both the client and the server; use the -enable-encrypt configure option to turn it on. You must then use the -x global option to request encryption.

GSSAPI connections are handled on the server side by the same server which handles the password authentication server; see the section called “Setting up the server for Authentication”. If you are using a GSSAPI mechanism such as Kerberos which provides for strong authentication, you will probably want to disable the ability to authenticate via cleartext passwords. To do so, create an empty CVSROOT/passwd password file, and set SystemAuth=no in the config file (the section called “The CVSROOT/config configuration file”).

The GSSAPI server uses a principal name of cvs/hostname, where hostname is the canonical name of the server host. You will have to set this up as required by your GSSAPI mechanism.

To connect using GSSAPI, use :gserver:. For example,

cvs -d :gserver:faun.example.org:/usr/local/cvsroot checkout foo

Connecting with fork

This access method allows you to connect to a repository on your local disk via the remote protocol. In other words it does pretty much the same thing as :local:, but various quirks, bugs and the like are those of the remote cvsnt rather than the local cvsnt.

For day-to-day operations you might prefer either :local: or :fork:, depending on your preferences. Of course :fork: comes in particularly handy in testing or debugging cvsnt and the remote protocol. Specifically, we avoid all of the network-related setup/configuration, timeouts, and authentication inherent in the other remote access methods but still create a connection which uses the remote protocol.

To connect using the fork method, use :fork: and the pathname to your local repository. For example:

cvs -d :fork:/usr/local/cvsroot checkout foo

Using repository aliases

Repository aliases hide the real paths to the repositories on the server behind virtual names. The server information is hidden to clients which increases security and means the cvs root strings are independent of the server architecture.

Aliases are normally specified in the /etc/cvsnt/PServer file on Unix, or in the CVSNT Server Control Panel on Windows. Especially on Windows is is recommended that aliases are used to avoid exposing Windows drive letters (C:, D:) to the clients.