README.textile

OpenSSH for git

The primary goal of this patch/hack is to enable public key lookups via a method other than the authorized_keys file. We wanted it to be flexible, so the patch executes a 3rd party program or script. This way, you can implement your public key lookups in any language backed by any dataset – Ruby, Perl, Python, bash, MySQL, Postgres, CouchDB, etc. Our motivation to write this patch is to support large git repositories, but other creative uses may come about.

Auditing

We welcome audits and improvements to the patch (we’re not expert C hackers). The openssh-5.1p1 branch is openssh-5.1p1 with the patch applied. The original commit in this branch is openssh-5.1p1 with an additional .gitignore file.

Security

It should be said that it is unwise to do this; in addition to trusting a script you write with user authentication, the patch is written by some guy in Boston who, while obviously extremely awesome, does not trust himself with the security of your server. If you’re going to run this hack, it is recommended you run this in a chroot jail. As such, we strongly advise against using this patched version of sshd for the main sshd on your server – run a normal install of sshd on a non-standard port.

In summary: USE THIS PATCH AT YOUR OWN RISK.

Setup and Configuration

In order to do so, we added an optional AuthorizedKeysScript option to your sshd_config. The format and functionality is identical to AuthorizedKeysFile, except the path will reference a program instead of a flatfile. The value I use is .ssh/authorized_keys_script.

Writing the Program/Script

The script must follow certain guidelines in order for this to work properly.

Your program will receive the public key on STDIN, and is terminated by EOF. It will be in canoncial SSH public key format, starting with ssh-dss or ssh-rsa, a space, and then the key data. The user@hostname identifier is not included.

Your program’s exit code is the most important output from your script. An exit code of 0 means success, while 1 means failure. Success allows the user to login with that key. It is thus VERY important that your script does not blindly exit with a code of 0, or the user will be able to login as the user.

Your script has the option of outputting ssh options in the same format as authorized_keys. These options are printed to standard out. You must print only the options without any whitespace or newlines at the end (i.e., in Ruby, use print not puts). A valid option string might be command="gitosis-serve jd",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty. Outputting invalid options (or a newline) will result in the user’s key being rejected, regardless of your exit code. Additionally, your scripts output will be entirely ignored if the exit code is not 0.

You should write your script to timeout and exit (with a status code of 1) after some number of seconds, otherwise the sshd session will hang waiting for your script to return. This should not affect the overall sshd daemon, but might leave forked sessions hung, requiring sshd to be restarted.

To-do

SIGCHLD confirmation – is the current handling of SIGCHLD ok?

Add a timeout to assure the script does not permanently hang the sshd session. If timeout occurs, kill the child process.

Make the options output handling a bit less sensitive, e.g. handle if a newline is printed.