How to configure WinCVS with SSH1 Patrick G. Salsbury http://reality.sculptors.com/~salsbury/ 06-28-01 Intro: This document details the procurement, process, and possible pitfalls of implementing WinCVS version control software with Secure Shell (SSH) cryptographic protection. It will explain how to configure the files & directories needed, as well as how to configure SSH public-key authentication so that you are not prompted for a password every time you attempt to issue a CVS command. Background: I have been using CVS and WinCVS (http://www.cvsgui.org/) for a couple of years, and recently made the move to SSH-encrypted CVS sessions on my Unix/Linux boxes. In attempting to roll this out to Windows-only users, I found that the WinCVS software exhibits a bug when used with version 2 of the SSH protocol. This is compounded by the fact that the formerly freely-available version of ssh1 for windows has been removed from the ftp://www.ssh.com/ servers, when they moved to a commercialized version of ssh2. Mind you, the program that they have now is really nice, it just doesn't do ssh1, and it doesn't work with WinCVS. There are also a lot of free and commercial ssh1 terminal clients for windows, such as PuTTY, but these are interactive clients, and CVS requires a command-line client that can issue basic 'ssh user@hostname command' types of commands which run non-interactively. After asking around on the info-cvs mailing list, I found I'd run across a FAQ that had never really been answered very well, and after hammering my head against it for about a month, I finally succeeded in getting all the pieces in the right place today, so I decided to document the hell out of it. :-) Sources: Having said all that, there are a few things you'll need to have to get this working. First, you'll need a version of ssh1 that does command-line stuff. You can still find this outside the US on some sites. (It can't be exported from the US due to the vagaries of United States munitions law, but you can import it from elsewhere. Go figure.) A great place to find this is Google, where you should search for 'ssh-1.2.14-win32bin.zip'. This url should do the trick: http://www.google.com/search?q=ssh-1.2.14-win32bin.zip Google pointed me to various sites in Germany and I confirmed that at least this one has the code in question: German source: http://www.tu-bs.de/rz/Compute-Server/ssh/dos/readme.htm (They also have a fairly complete-looking instruction guide, depending on how your German is. Mine's a bit rusty, but from what I can glean, they seem to have covered it fairly well.) I also found Gordon Chaffee's page at Berkeley to be of great help in figuring out the specific directories to create. (That ssh zip file listed above has the binaries, but no documentation.) His info is here: http://bmrc.berkeley.edu/people/chaffee/winntutil.html#sshnt One other useful tip from Gordon's page is that if you copy the ssh.exe binary to sshc.exe, then it automatically runs with compression on. He said he finds this useful when running CVS commands. I set up my system the same way, but seemed to notice some problems with CVS randomly hanging sometimes. You may want to experiment with the two settings. (The hang may have been caused by long-duration operations, as described in the "Notes" section at the bottom, where WinCVS appears to go dead, but is actually running in the background.) The other page that was incredibly useful in deciphering this issue was a page on SSH also hosted at Berkeley: http://ptolemy.eecs.berkeley.edu/~cxh/sapub/ssh.html Unfortunately, the Berkeley folks seem to have ready access to Windows compilers, which isn't the case for everyone, so I recommend downloading the zip file unless you're comfortable with patching & building your own code on Windows and have the necessary tools on hand. You'll also need a copy of WinCVS, which can be downloaded from http://www.cvsgui.org/ and a copy of WinZip (http://www.winzip.com/) or some other unzipper if you don't already have one. I also recommend installing the TCL toolkit, if you'd like to use the macro functionality of WinCVS. You can find TCL at http://www.scriptics.com/ (Note: As of 03-15-01, I see that WinCVS 1.2 has been released. I have not yet tested SSH functionality with that release.) Setting up the environment: Unzip the ssh-1.2.14-win32bin.zip program and extract it to a directory somewhere, such as c:\Program Files\ssh1 Create a home directory for your own ssh files, such as c:\users\yourname\.ssh or c:\winnt\profiles\yourname\.ssh Edit your AUTOEXEC.BAT file (for Win95/98) and add the following lines: HOME=c:\users\yourname (or wherever you chose to create, above) PATH=%PATH%;c:\Program Files\ssh1 (or wherever you unzipped ssh into) If you're using Windows NT (as I am), you set your environment variables as follows: Right click on "My Computer" and choose "Properties" Click on the "Environment" tab Look in the "User Variables" section. -If you already have a "PATH" variable, click on that. Add ";c:\Program Files\ssh1" to the end of the "Value" box (the ";" separates it from the previous PATH entries), click "Set", then click "Apply". -If you don't already have "PATH" in your User Variables section, type PATH in the "Variable" box, "c:\Program Files\ssh1" in the "Value" box, click "Set", then click "Apply". Next, type "HOME" in the "Variable" Box, and put c:\users\yourname (or wherever you chose) into the "Value" box. Click "Set", then "Apply", then "OK". If you're using Windows 2000, it's almost like the NT configuration, except as follows: Right click on "My Computer" and choose "Properties" Click on the "Advanced" tab Click on the "Environment Variables" button. (The proceed to define your PATH and HOME variables, as above.) Generate host keys for your machine: (Note: This isn't needed for client-only use, and for outgoing SSH connections. It's only used for machines that will have other CVS clients connecting to them.) Create a c:\ssh\etc directory to store your ssh_config (if desired. I don't have one.), ssh_host_key and ssh_host_key.pub files. cd c:/ssh/etc ssh-keygen -b 1024 -f ssh_host_key -N '' -C yourhostname This creates a 1024 bit host key pair and two files, ssh_host_key and ssh_host_key.pub, with no password, and the comment being the name of your machine. If you don't use the -C option, you may see this error: gethostname: No such file or directory Testing: Open up a new MS-DOS window, and type "set". You should see a list of your environment variables, including HOME and PATH. They should now contain the values you just specified above. At this point, provided your path is set up correctly, you should be able to just type 'ssh' and get some help-text on the various flags and options, looking something like this: C:\>ssh Usage: ssh [options] host [command] Options: -l user Log in using this user name. -n Redirect input from /dev/null. -a Disable authentication agent forwarding. -x Disable X11 connection forwarding. -i file Identity for RSA authentication (default: ~/.ssh/identity). -t Tty; allocate a tty even if command is given. -v Verbose; display verbose debugging messages. -q Quiet; don't display any warning messages. -f Fork into background after authentication. -e char Set escape character; ``none'' = disable (default: ~). -c cipher Select encryption algorithm: ``idea'' (default, secure), ``des'', ``3des'', ``tss'', ``arcfour'' (fast, suitable for bulk transfers), ``none'' (no encryption - for debugging only). -p port Connect to this port. Server must be on the same port. -L listen-port:host:port Forward local port to remote address -R listen-port:host:port Forward remote port to local address These cause ssh to listen for connections on a port, and forward them to the other side by connecting to host:port. -C Enable compression. -o 'option' Process the option as if it was read from a configuration file. Now you should be able to log into a remote machine via SSH1 by issuing a command like: ssh -v -l username ssh.hostname.someplace It will ask you for your password on the remote host, and then you should be in. Public Key Authentication: SSH also can use public key authentication in order to verify your identity without constanty prompting you for a password. There are various opinions on the wisdom of creating a public-key that doesn't use passwords to authenticate the user. Indeed, you should weigh the inconvenience of typing your password whenever issuing a CVS command with the general security of your environment and machine. Certainly, a password-less key should not be left on a public or multi-user machine. Anyone who gets access to your windows machine would then be able to get into your Unix account without a password. Think carefully about this. If you are decided that you want to create a public-key to authenticate yourself, you may do so as follows: cd %HOME%\.ssh ssh-keygen -C username@yourhostname This creates a 1024 bit key pair and two files, identity and identity.pub, and the comment being the name of your machine. It will prompt you asking where to store the file, defaulting to $HOME/.ssh/identity. It will also prompt you for a passphrase. Entering one here secures your public key, but also defeats the purpose of generating a key so that you're not prompted for a password. If you just hit "Enter" twice (once for the passphrase, and once for confirmation), it will finish generating the key and name it identity.pub If you don't use the -C option, you may see this error: gethostname: No such file or directory Here's a sample session where I generate keys with no passphrase for a machine called 'myhost'. I saved the keys in C:/tmp because I didn't want to overwrite my real keys. C:\>cd c:\tmp C:\tmp>ssh-keygen -C myhost Initializing random number generator... Generating p: ...............................................................\ .............++ (distance 1296) Generating q: ...............++ (distance 310) Computing the keys... Testing the keys... Key generation complete. Enter file in which to save the key ($HOME/.ssh/identity): C:/tmp/identity Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in C:/tmp/identity. Your public key is: 1024 37 939081187355247279097286066056836200187500166757277461262410055150341\ 83550520111455230281016685131343081711417148543247737788059693359594583390430\ 35273471894877976769330729268657163629521105008373282900217673001284239239960\ 57552669117905824359467449026626998777803348151468268532185939449766323408972\ 39207727 myhost Your public key has been saved in C:/tmp/identity.pub At this point, I like to make a copy of the identity.pub file with a more descriptive name. After you start copying these around to a few different machines, it's nice to know which ones come from where. C:\tmp>copy identity.pub identity_myhost.pub 1 file(s) copied. C:\tmp>dir Volume in drive C has no label. Volume Serial Number is 3964-BC4B Directory of C:\tmp 07/06/00 05:05p . 07/06/00 05:05p .. 02/19/01 12:55a 518 identity 02/19/01 12:55a 322 identity.pub 02/19/01 12:55a 322 identity_myhost.pub 5 File(s) 1,162 bytes 663,879,680 bytes free Now we get to use 'scp' to copy our public key over to our Unix/CVS host. C:\tmp>scp identity_myhost.pub yourname@yourhost.somewhere:/home/yourname/.ssh/identity_myhost.pub (Make sure that /home/yourname/.ssh/ exists!) Password: (Enter your Unix password) Now the key is on the Unix machine, but it still hasn't been authorized. You do this by appending the public key to the end of a file called /home/yourname/.ssh/authorized_keys, like so: C:\tmp>ssh -v -l yourname yourhost.somewhere [Lots of verbose stuff] Password: Unix>cd ~/.ssh Unix>ls -l total 10 -rw-r--r-- 1 salsbury users 681 Feb 18 12:19 authorized_keys -rw------- 1 salsbury users 547 Feb 18 03:16 identity -rw-r--r-- 1 salsbury users 351 Feb 18 03:16 identity.pub -rw-r--r-- 1 salsbury users 351 Feb 18 03:17 identity_machine1.pub -rw-r--r-- 1 salsbury users 330 Feb 18 12:17 identity_machine2.pub -rw-r--r-- 1 salsbury users 322 Feb 18 17:20 identity_myhost.pub -rw------- 1 salsbury users 1333 Feb 18 03:17 known_hosts -rw-r--r-- 1 salsbury users 624 Dec 2 12:14 known_hosts2 -rw------- 1 salsbury users 512 Feb 18 03:18 random_seed Unix>cat identity_myhost.pub >> authorized_keys Unix>ls -l authorized_keys -rw-r--r-- 1 salsbury users 1003 Feb 18 17:30 authorized_keys *Important!* Make sure that your .ssh directory and the files in it are only writable by you! If group write permissions are set on the directory or certain files within it, ssh will refuse to use your RSA keys, and will always prompt you for a password. Unix>chmod -R go-w ~/.ssh A few things to note: The 'cat identity_myhost.pub >> authorized_keys' part will append the new key onto the end of an existing authorized_keys file, or will create a new one if you already have one. Not only is this fast and convenient, but less error-prone than cutting and pasting, as you don't run the risk of an editor trying to word-wrap. (The key is all on 1 very long line.) This is also a safer way of adding the new key, as it won't clobber existing keys in most Unix shells. You can see from the above directory listing why it's a good idea to copy identity.pub to identity_machinename.pub before moving it off of that machine. That prevents it from clobbering the identity.pub key on the machine you're moving it to, and makes it clear which keys come from which machines. The second listing of authorized_keys confirms that the file grew by 322 bytes, or the length of identity_myhost.pub. You could also cat the file, and you'll see the last line contains the same text as identity_myhost.pub. At this point, you should be all set up for public-key based authentication with ssh and scp. Go back to your MS-DOS window and try another SSH. This time, it should let you in with no password prompt. C:\>ssh -v -l yourname yourhost.somewhere [Lots of verbose stuff] Unix> If that works, you're now set to configure WinCVS to use SSH authentication, and then you're off and running! Configuring WinCVS: Start up your WinCVS software. I've tried this with both WinCVS v1.0.6 and v1.1b17, and they both seem to work fine. WinCVS v1.0.6 Pull down CVSAdmin->Preferences (or click CTRL-F1) On the "General" tab enter your CVSROOT information: yourname@yourhost.somewhere:/path/to/cvsroot For Authentication, choose "SSH server" (If you decided not to use the RSA public keys and instead want to enter your password when performing CVS operations, then CVS will appear to hang when you run a command like 'cvs -t update', but it's really waiting for you to enter your password. Hit 'ALT-TAB' and switch to the blank MS-DOS window that has appeared in the background, enter your Unix password, and hit "Enter". CVS should then proceed with its action.) On the "Ports" tab, check the box that says "Check for an alternate rsh name" and enter '/path/to/ssh' or '/path/to/sshc' (if you made a copy of ssh to do auto-compression, as noted above.) You could also specify the full path, but that shouldn't be necessary if your "PATH" variable is set. Click "OK" to accept your changes WinCVS v1.1.b17 Pull down Admin->Preferences (or click CTRL-F1) On the "General" tab enter your CVSROOT information: yourname@yourhost.somewhere:/path/to/cvsroot For Authentication, choose "SSH server" Check the "RSA Identity" box and choose your identity (not identity.pub!) file, if it's not already listed. (It should pick it up from $HOME\.ssh\identity) (This step isn't needed if you decide not to use the RSA public keys and instead want to enter your password when performing CVS operations. In that case, CVS will appear to hang when you run a command like 'cvs -t update', but it's really waiting for you to enter your password. Hit 'ALT-TAB' and switch to the blank MS-DOS window that has appeared in the background, enter your Unix password, and hit "Enter". CVS should then proceed with its action.) On the "Ports" tab, check the box that says "Check for an alternate rsh name" and enter 'ssh' or 'sshc' (if you made a copy of ssh to do auto-compression, as noted above.) You could also specify the full path, but that shouldn't be necessary if your "PATH" variable is set. Click "OK" to accept your changes Now you should be all set! Any CVS commands that you issue will now run through SSH and all of your data will be wrapped in a protective crypto tunnel. Enjoy! Notes: Be patient when doing CVS operations that might take a while. WinCVS doesn't seem to give you updates as it goes along, unlike the Unix client, which will give you status after each file. Even when using the '-t' (trace) option with CVS, (which provides more debugging info) doesn't update until the very end of an operation in WinCVS, while in Unix it will merrily chatter along while working, so that you know the system isn't hung. I just did a checkout of a 5.5Mb CVS module over my dialup line at home (~31.2Kbit/sec), and it took approximately 25 minutes to download everything. During this time, WinCVS looked dead to the world, complete with the system not refreshing the CVS window if I moved another window over it, ALT-TABbing to the MS-DOS window running the ssh command, and seeing no response, etc. The only reason I knew it was still working was by doing 'tcpdump' analysis of my PPP interface, running an 'strace' of the process on my remote CVS server, and seeing the little blinking lights on my modem. :-) During this time, WinCVS showed no signs of life. However, once the operations and download were complete, it came back to life and showered me with updated info as to all the programs it had downloaded. This could almost certainly be improved upon in the user interface, but for now, if you're on a slow link, be patient, and check your modem lights/interface data if you don't believe it's still working. You'll probably also want to turn on compression in CVS and perhaps within ssh by running as 'sshc' (see above). Errata: I've noticed that the 'cvs release' function doesn't seem to want to work over SSH, but haven't yet diagnosed why. It should still be possible to just do an update on the directory to make sure it's synchronized with the Repository, then remove the directory via standard Windows tools. On my setup, it's bombing out with this error: cvs release . (in directory D:\cvs\misc-files\) rsh: can't establish connection cvs [update aborted]: end of file from server (consult above messages if any) cvs release: unable to release `.' *****CVS exited normally with code 0***** I also noticed that my Linux machine was registering a bunch of actual rshd (not sshd) attempts coming from my notebook while I was testing this, so it could be that the WinCVS code isn't using the SSH method for 'release' operations that it is using for others. Someone familiar with the source code will be able to confirm or deny this. ********** Comments, suggestions, and corrections to this doc are welcome at the above email address. Pat